Author: ion
Date: Mon Nov 13 01:31:45 2006
New Revision: 24730
URL:
http://svn.reactos.org/svn/reactos?rev=24730&view=rev
Log:
- Cleanup fastio.c
- Implement FsRtlMdlReadDev (this function is not called, no risk of regressions).
- Move FsRtlAcquireFileExclusive and FsRtlReleaseFileExclusive from filelock.c to
fastio.c.
- Bugfix these functions to actually call FsRtlEnter/ExitFileSystem.
- Huge cleanusp of filelock.c, but no code changes, except the usage of some simpler
macros provided by NTIFS.H (with equivalent code).
Modified:
trunk/reactos/ntoskrnl/fs/fastio.c
trunk/reactos/ntoskrnl/fs/filelock.c
Modified: trunk/reactos/ntoskrnl/fs/fastio.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/fs/fastio.c?rev=2…
==============================================================================
--- trunk/reactos/ntoskrnl/fs/fastio.c (original)
+++ trunk/reactos/ntoskrnl/fs/fastio.c Mon Nov 13 01:31:45 2006
@@ -1,13 +1,12 @@
/*
- * COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS Kernel
+ * LICENSE: GPL - See COPYING in the top level directory
* FILE: ntoskrnl/fs/fastio.c
* PURPOSE: File System Routines which support Fast I/O or Cc Access.
- *
- * PROGRAMMERS: Alex Ionescu (alex(a)relsoft.net)
- */
-
-/* INCLUDES ****************************************************************/
+ * PROGRAMMERS: Alex Ionescu (alex.ionescu(a)reactos.org)
+*/
+
+/* INCLUDES ******************************************************************/
#include <ntoskrnl.h>
#define NDEBUG
@@ -19,6 +18,7 @@
extern ULONG CcFastReadResourceMiss;
extern ULONG CcFastReadWait;
extern ULONG CcFastReadNoWait;
+ULONG CcFastMdlReadNotPossible;
/* FUNCTIONS *****************************************************************/
@@ -26,8 +26,8 @@
* @implemented
*/
VOID
-STDCALL
-FsRtlIncrementCcFastReadResourceMiss( VOID )
+NTAPI
+FsRtlIncrementCcFastReadResourceMiss(VOID)
{
CcFastReadResourceMiss++;
}
@@ -36,8 +36,8 @@
* @implemented
*/
VOID
-STDCALL
-FsRtlIncrementCcFastReadNotPossible( VOID )
+NTAPI
+FsRtlIncrementCcFastReadNotPossible(VOID)
{
CcFastReadNotPossible++;
}
@@ -46,8 +46,8 @@
* @implemented
*/
VOID
-STDCALL
-FsRtlIncrementCcFastReadWait( VOID )
+NTAPI
+FsRtlIncrementCcFastReadWait(VOID)
{
CcFastReadWait++;
}
@@ -56,86 +56,53 @@
* @implemented
*/
VOID
-STDCALL
-FsRtlIncrementCcFastReadNoWait( VOID )
+NTAPI
+FsRtlIncrementCcFastReadNoWait(VOID)
{
CcFastReadNoWait++;
}
/*
- * NAME EXPORTED
- * FsRtlCopyRead@32
- *
- * DESCRIPTION
- *
- * ARGUMENTS
- *
- * RETURN VALUE
- *
- * NOTE
- * From Bo Branten's ntifs.h v12.
- *
* @unimplemented
*/
BOOLEAN
-STDCALL
-FsRtlCopyRead(IN PFILE_OBJECT FileObject,
- IN PLARGE_INTEGER FileOffset,
- IN ULONG Length,
- IN BOOLEAN Wait,
- IN ULONG LockKey,
+NTAPI
+FsRtlCopyRead(IN PFILE_OBJECT FileObject,
+ IN PLARGE_INTEGER FileOffset,
+ IN ULONG Length,
+ IN BOOLEAN Wait,
+ IN ULONG LockKey,
OUT PVOID Buffer,
OUT PIO_STATUS_BLOCK IoStatus,
- IN PDEVICE_OBJECT DeviceObject)
+ IN PDEVICE_OBJECT DeviceObject)
{
UNIMPLEMENTED;
return FALSE;
}
/*
- * NAME EXPORTED
- * FsRtlCopyWrite@32
- *
- * DESCRIPTION
- *
- * ARGUMENTS
- *
- * RETURN VALUE
- *
- * NOTE
- * From Bo Branten's ntifs.h v12.
- *
* @unimplemented
*/
BOOLEAN
-STDCALL
-FsRtlCopyWrite(IN PFILE_OBJECT FileObject,
- IN PLARGE_INTEGER FileOffset,
- IN ULONG Length,
- IN BOOLEAN Wait,
- IN ULONG LockKey,
+NTAPI
+FsRtlCopyWrite(IN PFILE_OBJECT FileObject,
+ IN PLARGE_INTEGER FileOffset,
+ IN ULONG Length,
+ IN BOOLEAN Wait,
+ IN ULONG LockKey,
OUT PVOID Buffer,
OUT PIO_STATUS_BLOCK IoStatus,
- IN PDEVICE_OBJECT DeviceObject)
+ IN PDEVICE_OBJECT DeviceObject)
{
UNIMPLEMENTED;
return FALSE;
}
/*
- * NAME EXPORTED
- * FsRtlGetFileSize@8
- *
- * DESCRIPTION
- *
- * ARGUMENTS
- *
- * RETURN VALUE
- *
* @implemented
*/
NTSTATUS
-STDCALL
+NTAPI
FsRtlGetFileSize(IN PFILE_OBJECT FileObject,
IN OUT PLARGE_INTEGER FileSize)
{
@@ -182,19 +149,10 @@
}
/*
- * NAME EXPORTED
- * FsRtlMdlRead@24
- *
- * DESCRIPTION
- *
- * ARGUMENTS
- *
- * RETURN VALUE
- *
- * @implemented
- */
-BOOLEAN
-STDCALL
+ * @implemented
+ */
+BOOLEAN
+NTAPI
FsRtlMdlRead(IN PFILE_OBJECT FileObject,
IN PLARGE_INTEGER FileOffset,
IN ULONG Length,
@@ -244,19 +202,10 @@
}
/*
- * NAME EXPORTED
- * FsRtlMdlReadComplete@8
- *
- * DESCRIPTION
- *
- * ARGUMENTS
- *
- * RETURN VALUE
- *
- * @implemented
- */
-BOOLEAN
-STDCALL
+ * @implemented
+ */
+BOOLEAN
+NTAPI
FsRtlMdlReadComplete(IN PFILE_OBJECT FileObject,
IN OUT PMDL MdlChain)
{
@@ -291,25 +240,11 @@
return FsRtlMdlReadCompleteDev(FileObject, MdlChain, DeviceObject);
}
-
-/*
- * NAME EXPORTED
- * FsRtlMdlReadCompleteDev@12
- *
- * DESCRIPTION
- *
- * ARGUMENTS
- *
- * RETURN VALUE
- *
- * NOTE
- * From Bo Branten's ntifs.h v13.
- * (CcMdlReadCompleteDev declared in internal/cc.h)
- *
- * @implemented
- */
-BOOLEAN
-STDCALL
+/*
+ * @implemented
+ */
+BOOLEAN
+NTAPI
FsRtlMdlReadCompleteDev(IN PFILE_OBJECT FileObject,
IN PMDL MdlChain,
IN PDEVICE_OBJECT DeviceObject)
@@ -320,19 +255,10 @@
}
/*
- * NAME EXPORTED
- * FsRtlMdlReadDev@28
- *
- * DESCRIPTION
- *
- * ARGUMENTS
- *
- * RETURN VALUE
- *
- * @unimplemented
- */
-BOOLEAN
-STDCALL
+ * @implemented
+ */
+BOOLEAN
+NTAPI
FsRtlMdlReadDev(IN PFILE_OBJECT FileObject,
IN PLARGE_INTEGER FileOffset,
IN ULONG Length,
@@ -341,25 +267,115 @@
OUT PIO_STATUS_BLOCK IoStatus,
IN PDEVICE_OBJECT DeviceObject)
{
- UNIMPLEMENTED;
- return FALSE;
-}
-
-
-/*
- * NAME EXPORTED
- * FsRtlMdlWriteComplete@12
- *
- * DESCRIPTION
- *
- * ARGUMENTS
- *
- * RETURN VALUE
- *
- * @implemented
- */
-BOOLEAN
-STDCALL
+ PFSRTL_COMMON_FCB_HEADER FcbHeader;
+ BOOLEAN Result = TRUE;
+ LARGE_INTEGER Offset;
+ PFAST_IO_DISPATCH FastIoDispatch;
+ PDEVICE_OBJECT Device;
+ PAGED_CODE();
+
+ /* No actual read */
+ if (!Length)
+ {
+ /* Return success */
+ IoStatus->Status = STATUS_SUCCESS;
+ IoStatus->Information = 0;
+ return TRUE;
+ }
+
+ /* Sanity check */
+ ASSERT(MAXLONGLONG - FileOffset->QuadPart >= (LONGLONG)Length);
+
+ /* Get the offset and FCB header */
+ Offset.QuadPart = FileOffset->QuadPart + Length;
+ FcbHeader = (PFSRTL_COMMON_FCB_HEADER)FileObject->FsContext;
+
+ /* Enter the FS */
+ FsRtlEnterFileSystem();
+ CcFastMdlReadWait++;
+
+ /* Lock the FCB */
+ ExAcquireResourceShared(FcbHeader->Resource, TRUE);
+
+ /* Check if this is a fast I/O cached file */
+ if (!(FileObject->PrivateCacheMap) ||
+ (FcbHeader->IsFastIoPossible == FastIoIsNotPossible))
+ {
+ /* It's not, so fail */
+ CcFastMdlReadNotPossible += 1;
+ Result = FALSE;
+ goto Cleanup;
+ }
+
+ /* Check if we need to find out if fast I/O is available */
+ if (FcbHeader->IsFastIoPossible == FastIoIsQuestionable)
+ {
+ /* Sanity check */
+ ASSERT(!KeIsExecutingDpc());
+
+ /* Get the Fast I/O table */
+ Device = IoGetRelatedDeviceObject(FileObject);
+ FastIoDispatch = Device->DriverObject->FastIoDispatch;
+
+ /* Sanity check */
+ ASSERT(FastIoDispatch != NULL);
+ ASSERT(FastIoDispatch->FastIoCheckIfPossible != NULL);
+
+ /* Ask the driver if we can do it */
+ if (!FastIoDispatch->FastIoCheckIfPossible(FileObject,
+ FileOffset,
+ Length,
+ TRUE,
+ LockKey,
+ TRUE,
+ IoStatus,
+ Device))
+ {
+ /* It's not, fail */
+ CcFastMdlReadNotPossible += 1;
+ Result = FALSE;
+ goto Cleanup;
+ }
+ }
+
+ /* Check if we read too much */
+ if (Offset.QuadPart > FcbHeader->FileSize.QuadPart)
+ {
+ /* We did, check if the file offset is past the end */
+ if (FileOffset->QuadPart >= FcbHeader->FileSize.QuadPart)
+ {
+ /* Set end of file */
+ IoStatus->Status = STATUS_END_OF_FILE;
+ IoStatus->Information = 0;
+ goto Cleanup;
+ }
+
+ /* Otherwise, just normalize the length */
+ Length = (ULONG)(FcbHeader->FileSize.QuadPart - FileOffset->QuadPart);
+ }
+
+ /* Set this as top-level IRP */
+ PsGetCurrentThread()->TopLevelIrp = FSRTL_FAST_IO_TOP_LEVEL_IRP;
+
+ /* Attempt a read */
+ CcMdlRead(FileObject, FileOffset, Length, MdlChain, IoStatus);
+ FileObject->Flags |= FO_FILE_FAST_IO_READ;
+
+ /* Remove the top-level IRP flag */
+ PsGetCurrentThread()->TopLevelIrp = 0;
+
+ /* Return to caller */
+Cleanup:
+ ExReleaseResourceLite(FcbHeader->Resource);
+ FsRtlExitFileSystem();
+ return Result;
+}
+
+/*
+ * @implemented
+ */
+BOOLEAN
+NTAPI
FsRtlMdlWriteComplete(IN PFILE_OBJECT FileObject,
IN PLARGE_INTEGER FileOffset,
IN PMDL MdlChain)
@@ -400,19 +416,10 @@
}
/*
- * NAME EXPORTED
- * FsRtlMdlWriteCompleteDev@16
- *
- * DESCRIPTION
- *
- * ARGUMENTS
- *
- * RETURN VALUE
- *
- * @implemented
- */
-BOOLEAN
-STDCALL
+ * @implemented
+ */
+BOOLEAN
+NTAPI
FsRtlMdlWriteCompleteDev(IN PFILE_OBJECT FileObject,
IN PLARGE_INTEGER FileOffset,
IN PMDL MdlChain,
@@ -423,25 +430,15 @@
return TRUE;
}
-
-/*
- * NAME EXPORTED
- * FsRtlPrepareMdlWrite@24
- *
- * DESCRIPTION
- *
- * ARGUMENTS
- *
- * RETURN VALUE
- *
- * @implemented
- */
-BOOLEAN
-STDCALL
-FsRtlPrepareMdlWrite(IN PFILE_OBJECT FileObject,
- IN PLARGE_INTEGER FileOffset,
- IN ULONG Length,
- IN ULONG LockKey,
+/*
+ * @implemented
+ */
+BOOLEAN
+NTAPI
+FsRtlPrepareMdlWrite(IN PFILE_OBJECT FileObject,
+ IN PLARGE_INTEGER FileOffset,
+ IN ULONG Length,
+ IN ULONG LockKey,
OUT PMDL *MdlChain,
OUT PIO_STATUS_BLOCK IoStatus)
{
@@ -487,23 +484,14 @@
}
/*
- * NAME EXPORTED
- * FsRtlPrepareMdlWriteDev@28
- *
- * DESCRIPTION
- *
- * ARGUMENTS
- *
- * RETURN VALUE
- *
* @unimplemented
*/
BOOLEAN
-STDCALL
-FsRtlPrepareMdlWriteDev(IN PFILE_OBJECT FileObject,
- IN PLARGE_INTEGER FileOffset,
- IN ULONG Length,
- IN ULONG LockKey,
+NTAPI
+FsRtlPrepareMdlWriteDev(IN PFILE_OBJECT FileObject,
+ IN PLARGE_INTEGER FileOffset,
+ IN ULONG Length,
+ IN ULONG LockKey,
OUT PMDL *MdlChain,
OUT PIO_STATUS_BLOCK IoStatus,
IN PDEVICE_OBJECT DeviceObject)
@@ -512,4 +500,79 @@
return FALSE;
}
+/*
+* @implemented
+*/
+VOID
+NTAPI
+FsRtlAcquireFileExclusive(IN PFILE_OBJECT FileObject)
+{
+ PFAST_IO_DISPATCH FastDispatch;
+ PDEVICE_OBJECT DeviceObject;
+ PFSRTL_COMMON_FCB_HEADER FcbHeader;
+
+ /* Get the Device Object and fast dispatch */
+ DeviceObject = IoGetBaseFileSystemDeviceObject(FileObject);
+ FastDispatch = DeviceObject->DriverObject->FastIoDispatch;
+
+ /* Check if we have to do a Fast I/O Dispatch */
+ if ((FastDispatch) && (FastDispatch->AcquireFileForNtCreateSection))
+ {
+ /* Enter the file system and call it */
+ FsRtlEnterFileSystem();
+ FastDispatch->AcquireFileForNtCreateSection(FileObject);
+ return;
+ }
+
+ /* Get the FCB Header */
+ FcbHeader = (PFSRTL_COMMON_FCB_HEADER)FileObject->FsContext;
+ if (FcbHeader->Resource)
+ {
+ /* Use a Resource Acquire */
+ FsRtlEnterFileSystem();
+ ExAcquireResourceExclusive(FcbHeader->Resource, TRUE);
+ }
+
+ /* All done, return */
+ return;
+}
+
+/*
+* @implemented
+*/
+VOID
+NTAPI
+FsRtlReleaseFile(IN PFILE_OBJECT FileObject)
+{
+ PFAST_IO_DISPATCH FastDispatch;
+ PDEVICE_OBJECT DeviceObject;
+ PFSRTL_COMMON_FCB_HEADER FcbHeader;
+
+ /* Get the Device Object */
+ DeviceObject = IoGetBaseFileSystemDeviceObject(FileObject);
+
+ FastDispatch = DeviceObject->DriverObject->FastIoDispatch;
+
+ /* Check if we have to do a Fast I/O Dispatch */
+ if ((FastDispatch) && (FastDispatch->ReleaseFileForNtCreateSection))
+ {
+ /* Call the release function and exit the file system */
+ FastDispatch->ReleaseFileForNtCreateSection(FileObject);
+ FsRtlExitFileSystem();
+ return;
+ }
+
+ /* Get the FCB Header */
+ FcbHeader = (PFSRTL_COMMON_FCB_HEADER)FileObject->FsContext;
+ if (FcbHeader->Resource)
+ {
+ /* Use a Resource release */
+ ExReleaseResourceLite(FcbHeader->Resource);
+ FsRtlExitFileSystem();
+ }
+
+ /* All done, return */
+ return;
+}
+
/* EOF */
Modified: trunk/reactos/ntoskrnl/fs/filelock.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/fs/filelock.c?rev…
==============================================================================
--- trunk/reactos/ntoskrnl/fs/filelock.c (original)
+++ trunk/reactos/ntoskrnl/fs/filelock.c Mon Nov 13 01:31:45 2006
@@ -25,14 +25,10 @@
NPAGED_LOOKASIDE_LIST LockTocLookaside;
PAGED_LOOKASIDE_LIST LockLookaside;
-
-
__inline BOOLEAN
-IsOverlappingLock(
- PFILE_LOCK_INFO Lock,
- PLARGE_INTEGER StartOffset,
- PLARGE_INTEGER EndOffset
- )
+IsOverlappingLock(PFILE_LOCK_INFO Lock,
+ PLARGE_INTEGER StartOffset,
+ PLARGE_INTEGER EndOffset)
{
if ((ULONGLONG)StartOffset->QuadPart > (ULONGLONG)Lock->EndingByte.QuadPart)
{
@@ -47,13 +43,10 @@
return TRUE;
}
-
__inline BOOLEAN
-IsSurroundingLock(
- PFILE_LOCK_INFO Lock,
- PLARGE_INTEGER StartOffset,
- PLARGE_INTEGER EndOffset
- )
+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)
@@ -64,58 +57,72 @@
return FALSE;
}
-
-/**********************************************************************
- * NAME PRIVATE
- * FsRtlpInitFileLockingImplementation
- *
- */
VOID
-STDCALL INIT_FUNCTION
+NTAPI
FsRtlInitSystem(VOID)
{
- ExInitializeNPagedLookasideList( &LockTocLookaside,
+ /* Initialize the list for all lock information structures */
+ ExInitializeNPagedLookasideList(&LockTocLookaside,
NULL,
NULL,
0,
sizeof(FILE_LOCK_TOC),
IFS_POOL_TAG,
- 0
- );
-
- ExInitializeNPagedLookasideList( &GrantedLookaside,
+ 0);
+
+ /* Initialize the list for granted locks */
+ ExInitializeNPagedLookasideList(&GrantedLookaside,
NULL,
NULL,
0,
sizeof(FILE_LOCK_GRANTED),
IFS_POOL_TAG,
- 0
- );
-
- ExInitializePagedLookasideList( &LockLookaside,
+ 0);
+
+ /* Initialize the list for lock allocations */
+ ExInitializePagedLookasideList(&LockLookaside,
NULL,
NULL,
0,
sizeof(FILE_LOCK),
IFS_POOL_TAG,
- 0
- );
-
- ExInitializeFastMutex(&LockTocMutex);
-
-}
-
-/**********************************************************************
- * NAME PRIVATE
- * FsRtlpFileLockCancelRoutine
- *
- */
+ 0);
+
+ /* Initialize the lock information mutex */
+ ExInitializeFastMutex(&LockTocMutex);
+}
+
+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)
+{
+ /* Check if we have a complete routine */
+ if (CompleteRoutine)
+ {
+ /* Check if we have a file object */
+ if (FileObject) FileObject->LastLock = NULL;
+
+ /* Set the I/O Status and do completion */
+ Irp->IoStatus.Status = Status;
+ *NewStatus = CompleteRoutine(Context, Irp);
+ }
+ else
+ {
+ /* Otherwise do a normal I/O complete request */
+ FsRtlCompleteRequest(Irp, Status);
+ *NewStatus = Status;
+ }
+}
+
VOID
STDCALL
-FsRtlpFileLockCancelRoutine(
- IN PDEVICE_OBJECT DeviceObject,
- IN PIRP Irp
- )
+FsRtlpFileLockCancelRoutine(IN PDEVICE_OBJECT DeviceObject,
+ IN PIRP Irp)
{
KIRQL oldIrql;
PKSPIN_LOCK SpinLock;
@@ -135,28 +142,17 @@
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
-
-}
-
-/**********************************************************************
- * NAME PRIVATE
- * FsRtlpCheckLockForReadOrWriteAccess
- *
- * Return:
- * TRUE: can read/write
- * FALSE: can't read/write
- */
+}
+
BOOLEAN
FASTCALL
-FsRtlpCheckLockForReadOrWriteAccess(
- IN PFILE_LOCK FileLock,
- IN PLARGE_INTEGER FileOffset,
- IN PLARGE_INTEGER Length,
- IN ULONG Key,
- IN PFILE_OBJECT FileObject,
- IN PEPROCESS Process,
- IN BOOLEAN Read
- )
+FsRtlpCheckLockForReadOrWriteAccess(IN PFILE_LOCK FileLock,
+ IN PLARGE_INTEGER FileOffset,
+ IN PLARGE_INTEGER Length,
+ IN ULONG Key,
+ IN PFILE_OBJECT FileObject,
+ IN PEPROCESS Process,
+ IN BOOLEAN Read)
{
KIRQL oldirql;
PFILE_LOCK_TOC LockToc;
@@ -212,1163 +208,920 @@
return TRUE;
}
-
-/**********************************************************************
- * NAME EXPORTED
- * FsRtlCheckLockForReadAccess
- *
- * @implemented
- */
-BOOLEAN
-STDCALL
-FsRtlCheckLockForReadAccess (
- IN PFILE_LOCK FileLock,
- IN PIRP Irp
- )
-{
- PIO_STACK_LOCATION Stack;
- LARGE_INTEGER LocalLength;
-
- Stack = IoGetCurrentIrpStackLocation(Irp);
-
- LocalLength.u.LowPart = Stack->Parameters.Read.Length;
- LocalLength.u.HighPart = 0;
-
- return FsRtlpCheckLockForReadOrWriteAccess( FileLock,
-
&Stack->Parameters.Read.ByteOffset,
- &LocalLength,
- Stack->Parameters.Read.Key,
- Stack->FileObject,
- IoGetRequestorProcess(Irp),
- TRUE /* Read */
- );
-}
-
-
-/**********************************************************************
- * NAME EXPORTED
- * FsRtlCheckLockForWriteAccess
- *
- * @implemented
- */
-BOOLEAN
-STDCALL
-FsRtlCheckLockForWriteAccess (
- IN PFILE_LOCK FileLock,
- IN PIRP Irp
- )
-{
- PIO_STACK_LOCATION Stack;
- LARGE_INTEGER LocalLength;
-
- Stack = IoGetCurrentIrpStackLocation(Irp);
-
- LocalLength.u.LowPart = Stack->Parameters.Read.Length;
- LocalLength.u.HighPart = 0;
-
- return FsRtlpCheckLockForReadOrWriteAccess( FileLock,
-
&Stack->Parameters.Write.ByteOffset,
- &LocalLength,
- Stack->Parameters.Write.Key,
- Stack->FileObject,
- IoGetRequestorProcess(Irp),
- FALSE /* Read */
- );
-
-}
-
-
-
-
-/**********************************************************************
- * NAME EXPORTED
- * FsRtlFastCheckLockForRead
- *
- * @implemented
- */
-BOOLEAN
-STDCALL
-FsRtlFastCheckLockForRead (
- IN PFILE_LOCK FileLock,
- IN PLARGE_INTEGER FileOffset,
- IN PLARGE_INTEGER Length,
- IN ULONG Key,
- IN PFILE_OBJECT FileObject,
- IN PEPROCESS Process
- )
-{
- return FsRtlpCheckLockForReadOrWriteAccess( FileLock,
- FileOffset,
- Length,
- Key,
- FileObject,
- Process,
- TRUE /* Read */
- );
-}
-
-
-/**********************************************************************
- * NAME EXPORTED
- * FsRtlFastCheckLockForWrite
- *
- * @implemented
- */
-BOOLEAN
-STDCALL
-FsRtlFastCheckLockForWrite (
- IN PFILE_LOCK FileLock,
- IN PLARGE_INTEGER FileOffset,
- IN PLARGE_INTEGER Length,
- IN ULONG Key,
- IN PFILE_OBJECT FileObject,
- IN PEPROCESS Process
- )
-{
- return FsRtlpCheckLockForReadOrWriteAccess( FileLock,
- FileOffset,
- Length,
- Key,
- FileObject,
- Process,
- FALSE /* Read */
- );
-}
-
-
-
-/**********************************************************************
- * NAME PRIVATE
- * FsRtlpFastUnlockAllByKey
- *
- */
NTSTATUS
FASTCALL
-FsRtlpFastUnlockAllByKey(
- IN PFILE_LOCK FileLock,
- IN PFILE_OBJECT FileObject,
- IN PEPROCESS Process,
- IN ULONG Key,
- IN BOOLEAN UseKey,
- IN PVOID Context OPTIONAL
- )
-{
- KIRQL oldirql;
- PFILE_LOCK_TOC LockToc;
- PFILE_LOCK_GRANTED Granted, tmp;
- BOOLEAN Unlock = FALSE;
- //must make local copy since FILE_LOCK struct is allowed to be paged
- BOOLEAN GotUnlockRoutine;
- LIST_ENTRY UnlockedListHead;
- PLIST_ENTRY EnumEntry;
-
- ASSERT(FileLock);
- LockToc = FileLock->LockInformation;
-
- if (LockToc == NULL)
- {
- return STATUS_RANGE_NOT_LOCKED;
- }
-
- InitializeListHead(&UnlockedListHead);
- GotUnlockRoutine = FileLock->UnlockRoutine != NULL;
- KeAcquireSpinLock(&LockToc->SpinLock, &oldirql);
-
- LIST_FOR_EACH_SAFE(Granted, tmp, &LockToc->GrantedListHead, FILE_LOCK_GRANTED,
ListEntry)
- {
-
- if (Granted->Lock.ProcessId == Process &&
- Granted->Lock.FileObject == FileObject &&
- (!UseKey || (UseKey && Granted->Lock.Key == Key)) )
- {
- RemoveEntryList(&Granted->ListEntry);
- Unlock = TRUE;
-
- 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(&UnlockedListHead,&Granted->ListEntry);
- }
- else
- {
+FsRtlpFastUnlockAllByKey(IN PFILE_LOCK FileLock,
+ IN PFILE_OBJECT FileObject,
+ IN PEPROCESS Process,
+ IN ULONG Key,
+ IN BOOLEAN UseKey,
+ IN PVOID Context OPTIONAL)
+{
+ KIRQL oldirql;
+ PFILE_LOCK_TOC LockToc;
+ PFILE_LOCK_GRANTED Granted, tmp;
+ BOOLEAN Unlock = FALSE;
+ //must make local copy since FILE_LOCK struct is allowed to be paged
+ BOOLEAN GotUnlockRoutine;
+ LIST_ENTRY UnlockedListHead;
+ PLIST_ENTRY EnumEntry;
+
+ ASSERT(FileLock);
+ LockToc = FileLock->LockInformation;
+
+ if (LockToc == NULL)
+ {
+ return STATUS_RANGE_NOT_LOCKED;
+ }
+
+ InitializeListHead(&UnlockedListHead);
+ GotUnlockRoutine = FileLock->UnlockRoutine != NULL;
+ KeAcquireSpinLock(&LockToc->SpinLock, &oldirql);
+
+ LIST_FOR_EACH_SAFE(Granted, tmp, &LockToc->GrantedListHead, FILE_LOCK_GRANTED,
ListEntry)
+ {
+
+ if (Granted->Lock.ProcessId == Process &&
+ Granted->Lock.FileObject == FileObject &&
+ (!UseKey || (UseKey && Granted->Lock.Key == Key)) )
+ {
+ RemoveEntryList(&Granted->ListEntry);
+ Unlock = TRUE;
+
+ 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(&UnlockedListHead,&Granted->ListEntry);
+ }
+ else
+ {
+ ExFreeToNPagedLookasideList(&GrantedLookaside,Granted);
+ }
+ }
+ }
+
+ KeReleaseSpinLock(&LockToc->SpinLock, oldirql);
+
+ if (Unlock)
+ {
+ //call unlock routine for each unlocked lock (if any)
+ while (!IsListEmpty(&UnlockedListHead))
+ {
+ EnumEntry = RemoveTailList(&UnlockedListHead);
+ Granted = CONTAINING_RECORD(EnumEntry,FILE_LOCK_GRANTED, ListEntry);
+
+ FileLock->UnlockRoutine(Granted->UnlockContext,
&Granted->Lock);
ExFreeToNPagedLookasideList(&GrantedLookaside,Granted);
- }
- }
- }
-
- KeReleaseSpinLock(&LockToc->SpinLock, oldirql);
-
- if (Unlock)
- {
- //call unlock routine for each unlocked lock (if any)
- while (!IsListEmpty(&UnlockedListHead))
- {
- EnumEntry = RemoveTailList(&UnlockedListHead);
- Granted = CONTAINING_RECORD(EnumEntry,FILE_LOCK_GRANTED, ListEntry);
-
- FileLock->UnlockRoutine(Granted->UnlockContext, &Granted->Lock);
- ExFreeToNPagedLookasideList(&GrantedLookaside,Granted);
- }
-
- //NOTE: holding spinlock while calling this
- KeAcquireSpinLock(&LockToc->SpinLock, &oldirql);
- FsRtlpCompletePendingLocks(FileLock, LockToc, &oldirql, Context);
-
- if (IsListEmpty(&LockToc->GrantedListHead))
- {
- KeReleaseSpinLock(&LockToc->SpinLock, oldirql);
- FsRtlAreThereCurrentFileLocks(FileLock) = FALSE;
- }
- else
- {
- KeReleaseSpinLock(&LockToc->SpinLock, oldirql);
- }
-
- return STATUS_SUCCESS;
- }
-
- return STATUS_RANGE_NOT_LOCKED;
-}
-
-/**********************************************************************
- * NAME EXPORTED
- * FsRtlFastUnlockAll
- *
- * @implemented
- */
-NTSTATUS
-STDCALL
-FsRtlFastUnlockAll /*ByProcess*/ (
- IN PFILE_LOCK FileLock,
- IN PFILE_OBJECT FileObject,
- IN PEPROCESS Process,
- IN PVOID Context OPTIONAL
- )
-{
- return FsRtlpFastUnlockAllByKey( FileLock,
- FileObject,
- Process,
- 0, /* Key is ignored */
- FALSE, /* Do NOT use Key */
- Context
- );
-}
-
-/**********************************************************************
- * NAME EXPORTED
- * FsRtlFastUnlockAllByKey
- *
- * @implemented
- */
-NTSTATUS
-STDCALL
-FsRtlFastUnlockAllByKey (
- IN PFILE_LOCK FileLock,
- IN PFILE_OBJECT FileObject,
- IN PEPROCESS Process,
- IN ULONG Key,
- IN PVOID Context OPTIONAL
- )
-{
- return FsRtlpFastUnlockAllByKey( FileLock,
- FileObject,
- Process,
- Key,
- TRUE, /* Use Key */
- Context
- );
-}
-
-
-/**********************************************************************
- * NAME PRIVATE
- * FsRtlpAddLock
- *
- * NOTE
- * Spinlock held at entry !!
- */
+ }
+
+ //NOTE: holding spinlock while calling this
+ KeAcquireSpinLock(&LockToc->SpinLock, &oldirql);
+ FsRtlpCompletePendingLocks(FileLock, LockToc, &oldirql, Context);
+
+ if (IsListEmpty(&LockToc->GrantedListHead))
+ {
+ KeReleaseSpinLock(&LockToc->SpinLock, oldirql);
+ FsRtlAreThereCurrentFileLocks(FileLock) = FALSE;
+ }
+ else
+ {
+ KeReleaseSpinLock(&LockToc->SpinLock, oldirql);
+ }
+
+ return STATUS_SUCCESS;
+ }
+
+ return STATUS_RANGE_NOT_LOCKED;
+}
+
BOOLEAN
FASTCALL
-FsRtlpAddLock(
- IN PFILE_LOCK_TOC LockToc,
- IN PFILE_OBJECT FileObject,
- IN PLARGE_INTEGER FileOffset,
- IN PLARGE_INTEGER Length,
- IN PEPROCESS Process,
- IN ULONG Key,
- IN BOOLEAN ExclusiveLock,
- IN PVOID Context
- )
-{
- PFILE_LOCK_GRANTED Granted;
- LARGE_INTEGER EndOffset;
-
- EndOffset.QuadPart = FileOffset->QuadPart + Length->QuadPart - 1;
-
- //loop and try to find conflicking locks
- LIST_FOR_EACH(Granted, &LockToc->GrantedListHead, FILE_LOCK_GRANTED,
ListEntry)
- {
- if (IsOverlappingLock(&Granted->Lock, FileOffset, &EndOffset))
- {
- //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)
- {
- //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))
+FsRtlpAddLock(IN PFILE_LOCK_TOC LockToc,
+ IN PFILE_OBJECT FileObject,
+ IN PLARGE_INTEGER FileOffset,
+ IN PLARGE_INTEGER Length,
+ IN PEPROCESS Process,
+ IN ULONG Key,
+ IN BOOLEAN ExclusiveLock,
+ IN PVOID Context)
+{
+ PFILE_LOCK_GRANTED Granted;
+ LARGE_INTEGER EndOffset;
+
+ EndOffset.QuadPart = FileOffset->QuadPart + Length->QuadPart - 1;
+
+ //loop and try to find conflicking locks
+ LIST_FOR_EACH(Granted, &LockToc->GrantedListHead, FILE_LOCK_GRANTED,
ListEntry)
+ {
+ if (IsOverlappingLock(&Granted->Lock, FileOffset, &EndOffset))
+ {
+ //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)
{
- break;
+ //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))
+ {
+ break;
+ }
+
+ //else keep locking for conflicts
+ continue;
}
- //else keep locking for conflicts
- continue;
- }
-
- //we found a conflict:
- //we want shared access to an excl. lock OR exlc. access to a shared lock
- 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.ProcessId = Process;
- //ending offset
- Granted->Lock.EndingByte = EndOffset;
- Granted->UnlockContext = Context;
-
- InsertHeadList(&LockToc->GrantedListHead,&Granted->ListEntry);
- return TRUE;
-}
-
-
-
-/**********************************************************************
- * NAME PRIVATE
- * FsRtlpCompletePendingLocks
- *
- * NOTE
- * Spinlock held at entry !!
- */
+ //we found a conflict:
+ //we want shared access to an excl. lock OR exlc. access to a shared lock
+ 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.ProcessId = Process;
+ //ending offset
+ Granted->Lock.EndingByte = EndOffset;
+ Granted->UnlockContext = Context;
+
+ InsertHeadList(&LockToc->GrantedListHead,&Granted->ListEntry);
+ return TRUE;
+}
+
VOID
FASTCALL
-FsRtlpCompletePendingLocks(
- IN PFILE_LOCK FileLock,
- IN PFILE_LOCK_TOC LockToc,
- IN OUT PKIRQL oldirql,
- IN PVOID Context
- )
-{
- //walk pending list, FIFO order, try 2 complete locks
- PLIST_ENTRY EnumEntry;
- PIRP Irp, tmp;
- PIO_STACK_LOCATION Stack;
- LIST_ENTRY CompletedListHead;
-
- InitializeListHead(&CompletedListHead);
-
- LIST_FOR_EACH_SAFE(Irp, tmp, &LockToc->PendingListHead, IRP,
Tail.Overlay.ListEntry)
- {
- Stack = IoGetCurrentIrpStackLocation(Irp);
- if (FsRtlpAddLock(LockToc,
- Stack->FileObject,
- &Stack->Parameters.LockControl.ByteOffset,
- Stack->Parameters.LockControl.Length,
- IoGetRequestorProcess(Irp),
- Stack->Parameters.LockControl.Key,
- Stack->Flags & SL_EXCLUSIVE_LOCK,
- Irp->Tail.Overlay.DriverContext[2] //Context
- ) )
- {
- RemoveEntryList(&Irp->Tail.Overlay.ListEntry);
-
- if (!IoSetCancelRoutine(Irp, NULL))
- {
- //irp is canceled and cancelroutine will run when we release the lock
- InitializeListHead(&Irp->Tail.Overlay.ListEntry);
- continue;
- }
-
- /*
- 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);
- }
- }
-
- KeReleaseSpinLock(&LockToc->SpinLock, *oldirql);
-
- //complete irp's (if any)
- while (!IsListEmpty(&CompletedListHead))
- {
- EnumEntry = RemoveTailList(&CompletedListHead);
-
- Irp = CONTAINING_RECORD(EnumEntry, IRP, Tail.Overlay.ListEntry);
-
- Irp->IoStatus.Status = STATUS_SUCCESS;
- Irp->IoStatus.Information = 0;
-
- if (FileLock->CompleteLockIrpRoutine)
- {
- 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
- {
- IoCompleteRequest(Irp, IO_NO_INCREMENT);
- }
-
- }
-
- KeAcquireSpinLock(&LockToc->SpinLock, oldirql);
-}
-
-
-
-/**********************************************************************
- * NAME PRIVATE
- * FsRtlpUnlockSingle
- *
- */
+FsRtlpCompletePendingLocks(IN PFILE_LOCK FileLock,
+ IN PFILE_LOCK_TOC LockToc,
+ IN OUT PKIRQL oldirql,
+ IN PVOID Context)
+{
+ //walk pending list, FIFO order, try 2 complete locks
+ PLIST_ENTRY EnumEntry;
+ PIRP Irp, tmp;
+ PIO_STACK_LOCATION Stack;
+ LIST_ENTRY CompletedListHead;
+
+ InitializeListHead(&CompletedListHead);
+
+ LIST_FOR_EACH_SAFE(Irp, tmp, &LockToc->PendingListHead, IRP,
Tail.Overlay.ListEntry)
+ {
+ Stack = IoGetCurrentIrpStackLocation(Irp);
+ if (FsRtlpAddLock(LockToc,
+ Stack->FileObject,
+ &Stack->Parameters.LockControl.ByteOffset,
+ Stack->Parameters.LockControl.Length,
+ IoGetRequestorProcess(Irp),
+ Stack->Parameters.LockControl.Key,
+ Stack->Flags & SL_EXCLUSIVE_LOCK,
+ Irp->Tail.Overlay.DriverContext[2] //Context
+ ) )
+ {
+ RemoveEntryList(&Irp->Tail.Overlay.ListEntry);
+
+ if (!IoSetCancelRoutine(Irp, NULL))
+ {
+ //irp is canceled and cancelroutine will run when we release the lock
+ InitializeListHead(&Irp->Tail.Overlay.ListEntry);
+ continue;
+ }
+
+ /*
+ 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);
+ }
+ }
+
+ KeReleaseSpinLock(&LockToc->SpinLock, *oldirql);
+
+ //complete irp's (if any)
+ while (!IsListEmpty(&CompletedListHead))
+ {
+ EnumEntry = RemoveTailList(&CompletedListHead);
+
+ Irp = CONTAINING_RECORD(EnumEntry, IRP, Tail.Overlay.ListEntry);
+
+ Irp->IoStatus.Status = STATUS_SUCCESS;
+ Irp->IoStatus.Information = 0;
+
+ if (FileLock->CompleteLockIrpRoutine)
+ {
+ 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
+ {
+ IoCompleteRequest(Irp, IO_NO_INCREMENT);
+ }
+
+ }
+
+ KeAcquireSpinLock(&LockToc->SpinLock, oldirql);
+}
+
NTSTATUS
FASTCALL
-FsRtlpUnlockSingle(
- 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 CallUnlockRoutine
- )
-{
- KIRQL oldirql;
- PFILE_LOCK_TOC LockToc;
- PFILE_LOCK_GRANTED Granted, tmp;
-
- ASSERT(FileLock);
- LockToc = FileLock->LockInformation;
-
- if (LockToc == NULL)
- {
- return STATUS_RANGE_NOT_LOCKED;
- }
-
- KeAcquireSpinLock(&LockToc->SpinLock, &oldirql );
-
- LIST_FOR_EACH_SAFE(Granted, tmp, &LockToc->GrantedListHead,
FILE_LOCK_GRANTED,ListEntry)
- {
-
- //must be exact match
- if (FileOffset->QuadPart == Granted->Lock.StartingByte.QuadPart &&
- Length->QuadPart == Granted->Lock.Length.QuadPart &&
- Granted->Lock.ProcessId == Process &&
- Granted->Lock.FileObject == FileObject &&
- Granted->Lock.Key == Key)
- {
- RemoveEntryList(&Granted->ListEntry);
- FsRtlpCompletePendingLocks(FileLock, LockToc, &oldirql, Context);
-
- if (IsListEmpty(&LockToc->GrantedListHead))
- {
+FsRtlpUnlockSingle(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 CallUnlockRoutine)
+{
+ KIRQL oldirql;
+ PFILE_LOCK_TOC LockToc;
+ PFILE_LOCK_GRANTED Granted, tmp;
+
+ ASSERT(FileLock);
+ LockToc = FileLock->LockInformation;
+
+ if (LockToc == NULL)
+ {
+ return STATUS_RANGE_NOT_LOCKED;
+ }
+
+ KeAcquireSpinLock(&LockToc->SpinLock, &oldirql );
+
+ LIST_FOR_EACH_SAFE(Granted, tmp, &LockToc->GrantedListHead,
FILE_LOCK_GRANTED,ListEntry)
+ {
+
+ //must be exact match
+ if (FileOffset->QuadPart == Granted->Lock.StartingByte.QuadPart &&
+ Length->QuadPart == Granted->Lock.Length.QuadPart &&
+ Granted->Lock.ProcessId == Process &&
+ Granted->Lock.FileObject == FileObject &&
+ Granted->Lock.Key == Key)
+ {
+ RemoveEntryList(&Granted->ListEntry);
+ FsRtlpCompletePendingLocks(FileLock, LockToc, &oldirql, Context);
+
+ if (IsListEmpty(&LockToc->GrantedListHead))
+ {
+ KeReleaseSpinLock(&LockToc->SpinLock, oldirql);
+
+ FsRtlAreThereCurrentFileLocks(FileLock) = FALSE; //paged data
+ }
+ else
+ {
+ KeReleaseSpinLock(&LockToc->SpinLock, oldirql);
+ }
+
+ if (FileLock->UnlockRoutine && CallUnlockRoutine)
+ {
+ FileLock->UnlockRoutine(Granted->UnlockContext,
&Granted->Lock);
+ }
+
+ ExFreeToNPagedLookasideList(&GrantedLookaside, Granted);
+
+ return STATUS_SUCCESS;
+ }
+ }
+
+ KeReleaseSpinLock(&LockToc->SpinLock, oldirql);
+
+ return STATUS_RANGE_NOT_LOCKED;
+
+}
+
+/* PUBLIC FUNCTIONS **********************************************************/
+
+/*
+ * @implemented
+ */
+PFILE_LOCK_INFO
+NTAPI
+FsRtlGetNextFileLock(IN PFILE_LOCK FileLock,
+ IN BOOLEAN Restart)
+{
+ /*
+ Messy enumeration of granted locks.
+ 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...
+ */
+ KIRQL oldirql;
+ PLIST_ENTRY EnumEntry;
+ PFILE_LOCK_GRANTED Granted;
+ PFILE_LOCK_TOC LockToc;
+ BOOLEAN FoundPrevious = FALSE;
+ //must make local copy since FILE_LOCK struct is allowed to be in paged mem
+ FILE_LOCK_INFO LocalLastReturnedLockInfo;
+ PVOID LocalLastReturnedLock;
+
+ ASSERT(FileLock);
+ LockToc = FileLock->LockInformation;
+ if (LockToc == NULL)
+ {
+ return NULL;
+ }
+
+ LocalLastReturnedLock = FileLock->LastReturnedLock;
+
+ KeAcquireSpinLock(&LockToc->SpinLock,&oldirql);
+
+restart:;
+
+ EnumEntry = LockToc->GrantedListHead.Flink;
+
+ if (Restart)
+ {
+ if (EnumEntry != &LockToc->GrantedListHead)
+ {
+ Granted = CONTAINING_RECORD(EnumEntry,FILE_LOCK_GRANTED,ListEntry);
+ LocalLastReturnedLockInfo = Granted->Lock;
+ KeReleaseSpinLock(&LockToc->SpinLock,oldirql);
+
+ FileLock->LastReturnedLockInfo = LocalLastReturnedLockInfo;
+ FileLock->LastReturnedLock = EnumEntry;
+ return &FileLock->LastReturnedLockInfo;
+ }
+ else
+ {
+ KeReleaseSpinLock(&LockToc->SpinLock,oldirql);
+ return NULL;
+ }
+ }
+
+ //else: continue enum
+ while (EnumEntry != &LockToc->GrantedListHead)
+ {
+ //found previous lock?
+ if (EnumEntry == LocalLastReturnedLock)
+ {
+ FoundPrevious = TRUE;
+ //get next
+ EnumEntry = EnumEntry->Flink;
+ if (EnumEntry != &LockToc->GrantedListHead)
+ {
+ Granted = CONTAINING_RECORD(EnumEntry,FILE_LOCK_GRANTED,ListEntry);
+ LocalLastReturnedLockInfo = Granted->Lock;
+ KeReleaseSpinLock(&LockToc->SpinLock,oldirql);
+
+ FileLock->LastReturnedLockInfo = LocalLastReturnedLockInfo;
+ FileLock->LastReturnedLock = EnumEntry;
+ return &FileLock->LastReturnedLockInfo;
+ }
+ break;
+ }
+ EnumEntry = EnumEntry->Flink;
+ }
+
+ if (!FoundPrevious)
+ {
+ //got here? uh no, didn't find our last lock..must have been freed...restart
+ Restart = TRUE;
+ goto restart;
+ }
+
+ KeReleaseSpinLock(&LockToc->SpinLock,oldirql);
+
+ return NULL;//no (more) locks
+}
+
+/*
+ * @implemented
+ */
+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, //seems meaningless for fast io
+ IN BOOLEAN ExclusiveLock,
+ OUT PIO_STATUS_BLOCK IoStatus,
+ IN PIRP Irp OPTIONAL,
+ IN PVOID Context OPTIONAL,
+ IN BOOLEAN AlreadySynchronized)
+{
+ PFILE_LOCK_TOC LockToc;
+ KIRQL oldirql;
+
+ ASSERT(FileLock);
+ if (FileLock->LockInformation == NULL)
+ {
+ ExAcquireFastMutex(&LockTocMutex);
+ //still NULL?
+ if (FileLock->LockInformation == NULL)
+ {
+ FileLock->LockInformation =
ExAllocateFromNPagedLookasideList(&LockTocLookaside);
+ LockToc = FileLock->LockInformation;
+ KeInitializeSpinLock(&LockToc->SpinLock);
+ InitializeListHead(&LockToc->GrantedListHead);
+ InitializeListHead(&LockToc->PendingListHead);
+ }
+ ExReleaseFastMutex(&LockTocMutex);
+ }
+
+ LockToc = FileLock->LockInformation;
+ KeAcquireSpinLock(&LockToc->SpinLock, &oldirql);
+
+ //try add new lock (while holding spin lock)
+ if (FsRtlpAddLock(LockToc,
+ FileObject,
+ FileOffset,
+ Length,
+ Process,
+ Key,
+ ExclusiveLock,
+ Context
+ ) )
+ {
+ IoStatus->Status = STATUS_SUCCESS;
+ }
+ else if (Irp && !FailImmediately)
+ {
+ //failed + irp + no fail = make. pending
+
+ Irp->Tail.Overlay.DriverContext[3] = &LockToc->SpinLock;
+ Irp->Tail.Overlay.DriverContext[2] = Context;
+
+ (void)IoSetCancelRoutine(Irp, FsRtlpFileLockCancelRoutine);
+ if (Irp->Cancel && IoSetCancelRoutine(Irp, NULL))
+ {
+ //irp was canceled
KeReleaseSpinLock(&LockToc->SpinLock, oldirql);
- FsRtlAreThereCurrentFileLocks(FileLock) = FALSE; //paged data
- }
- else
- {
- KeReleaseSpinLock(&LockToc->SpinLock, oldirql);
- }
-
- if (FileLock->UnlockRoutine && CallUnlockRoutine)
- {
- FileLock->UnlockRoutine(Granted->UnlockContext,
&Granted->Lock);
- }
-
- ExFreeToNPagedLookasideList(&GrantedLookaside, Granted);
-
- return STATUS_SUCCESS;
- }
- }
-
- KeReleaseSpinLock(&LockToc->SpinLock, oldirql);
-
- return STATUS_RANGE_NOT_LOCKED;
-
-}
-
-
-
-/**********************************************************************
- * NAME EXPORTED
- * FsRtlFastUnlockSingle
- *
+ Irp->IoStatus.Status = STATUS_CANCELLED;
+ Irp->IoStatus.Information = 0;
+ IoCompleteRequest(Irp, IO_NO_INCREMENT);
+
+ return TRUE;
+ }
+
+ IoMarkIrpPending(Irp);
+ Irp->IoStatus.Status = IoStatus->Status = STATUS_PENDING;
+ Irp->IoStatus.Information = 0;
+
InsertHeadList(&LockToc->PendingListHead,&Irp->Tail.Overlay.ListEntry);
+
+ }
+ else
+ {
+ IoStatus->Status = STATUS_LOCK_NOT_GRANTED;
+ }
+
+ KeReleaseSpinLock(&LockToc->SpinLock, oldirql); //fires cancel routine
+
+ //never pending if no irp;-)
+ ASSERT(!(IoStatus->Status == STATUS_PENDING && !Irp));
+
+ if (IoStatus->Status != STATUS_PENDING)
+ {
+ if (IoStatus->Status == STATUS_SUCCESS)
+ {
+ FsRtlAreThereCurrentFileLocks(FileLock) = TRUE;
+ }
+
+ if (Irp)
+ {
+ Irp->IoStatus.Status = IoStatus->Status;
+ Irp->IoStatus.Information = 0;
+ if (FileLock->CompleteLockIrpRoutine)
+ {
+ if (FileLock->CompleteLockIrpRoutine(Context,Irp)!=STATUS_SUCCESS)
+ {
+ //CompleteLockIrpRoutine complain: revert changes
+ FsRtlpUnlockSingle( FileLock,
+ FileObject,
+ FileOffset,
+ Length,
+ Process,
+ Key,
+ NULL, /* context */
+ FALSE /* don't call unlock copletion routine */
+ );
+ }
+ }
+ else
+ {
+ IoCompleteRequest(Irp, IO_NO_INCREMENT);
+ }
+ }
+ }
+
+ //NOTE: only fast io seems to care about this return value
+ return (IoStatus->Status == STATUS_SUCCESS || FailImmediately);
+}
+
+/*
+ * @implemented
+ */
+BOOLEAN
+NTAPI
+FsRtlCheckLockForReadAccess(IN PFILE_LOCK FileLock,
+ IN PIRP Irp)
+{
+ PIO_STACK_LOCATION Stack;
+ LARGE_INTEGER LocalLength;
+
+ /* Get the I/O Stack location and length */
+ Stack = IoGetCurrentIrpStackLocation(Irp);
+ LocalLength.QuadPart = Stack->Parameters.Read.Length;
+
+ /* Call the internal API */
+ return FsRtlpCheckLockForReadOrWriteAccess(FileLock,
+ &Stack->Parameters.
+ Read.ByteOffset,
+ &LocalLength,
+ Stack->Parameters.Read.Key,
+ Stack->FileObject,
+ IoGetRequestorProcess(Irp),
+ TRUE);
+}
+
+/*
+ * @implemented
+ */
+BOOLEAN
+NTAPI
+FsRtlCheckLockForWriteAccess(IN PFILE_LOCK FileLock,
+ IN PIRP Irp)
+{
+ PIO_STACK_LOCATION Stack;
+ LARGE_INTEGER LocalLength;
+
+ /* Get the I/O Stack location and length */
+ Stack = IoGetCurrentIrpStackLocation(Irp);
+ LocalLength.QuadPart = Stack->Parameters.Read.Length;
+
+ /* Call the internal API */
+ return FsRtlpCheckLockForReadOrWriteAccess(FileLock,
+ &Stack->Parameters.
+ Read.ByteOffset,
+ &LocalLength,
+ Stack->Parameters.Read.Key,
+ Stack->FileObject,
+ IoGetRequestorProcess(Irp),
+ FALSE);
+}
+
+/*
+ * @implemented
+ */
+BOOLEAN
+NTAPI
+FsRtlFastCheckLockForRead(IN PFILE_LOCK FileLock,
+ IN PLARGE_INTEGER FileOffset,
+ IN PLARGE_INTEGER Length,
+ IN ULONG Key,
+ IN PFILE_OBJECT FileObject,
+ IN PEPROCESS Process)
+{
+ /* Call the internal API */
+ return FsRtlpCheckLockForReadOrWriteAccess(FileLock,
+ FileOffset,
+ Length,
+ Key,
+ FileObject,
+ Process,
+ TRUE);
+}
+
+/*
+ * @implemented
+ */
+BOOLEAN
+NTAPI
+FsRtlFastCheckLockForWrite(IN PFILE_LOCK FileLock,
+ IN PLARGE_INTEGER FileOffset,
+ IN PLARGE_INTEGER Length,
+ IN ULONG Key,
+ IN PFILE_OBJECT FileObject,
+ IN PEPROCESS Process)
+{
+ /* Call the internal API */
+ return FsRtlpCheckLockForReadOrWriteAccess(FileLock,
+ FileOffset,
+ Length,
+ Key,
+ FileObject,
+ Process,
+ FALSE);
+}
+
+/*
* @implemented
*/
NTSTATUS
-STDCALL
-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
- )
-{
- return FsRtlpUnlockSingle( FileLock,
+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)
+{
+ /* Call the internal API */
+ return FsRtlpUnlockSingle(FileLock,
FileObject,
FileOffset,
Length,
Process,
Key,
Context,
- TRUE /* call unlock copletion routine */
- );
-}
-
-/**********************************************************************
- * NAME EXPORTED
- * FsRtlpDumpFileLocks
- *
- * NOTE: used for testing and debugging
- */
-VOID
-FASTCALL
-FsRtlpDumpFileLocks(
- IN PFILE_LOCK FileLock
- )
-{
- KIRQL oldirql;
- PFILE_LOCK_TOC LockToc;
- PFILE_LOCK_GRANTED Granted;
- PIRP Irp;
- PIO_STACK_LOCATION Stack;
-
- ASSERT(FileLock);
- LockToc = FileLock->LockInformation;
-
- if (LockToc == NULL)
- {
- DPRINT1("No file locks\n");
- return;
- }
-
- DPRINT1("Dumping granted file locks, FIFO order\n");
-
- KeAcquireSpinLock(&LockToc->SpinLock, &oldirql);
-
- LIST_FOR_EACH(Granted, &LockToc->GrantedListHead, FILE_LOCK_GRANTED ,
ListEntry)
- {
- 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,
- Granted->Lock.EndingByte.QuadPart,
- Granted->Lock.Key,
- Granted->Lock.ProcessId,
- Granted->Lock.FileObject
- );
-
- }
-
- DPRINT1("Dumping pending file locks, FIFO order\n");
-
- LIST_FOR_EACH(Irp, &LockToc->PendingListHead, IRP , Tail.Overlay.ListEntry)
- {
- Stack = IoGetCurrentIrpStackLocation(Irp);
-
- 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,
- Stack->Parameters.LockControl.ByteOffset.QuadPart +
Stack->Parameters.LockControl.Length->QuadPart - 1,
- Stack->Parameters.LockControl.Key,
- IoGetRequestorProcess(Irp),
- Stack->FileObject
- );
-
- }
-
- KeReleaseSpinLock(&LockToc->SpinLock, oldirql);
-}
-
-
-
-/**********************************************************************
- * NAME EXPORTED
- * FsRtlGetNextFileLock
- *
- * RETURN VALUE
- * NULL if no more locks.
- *
- * @implemented
- */
-PFILE_LOCK_INFO
-STDCALL
-FsRtlGetNextFileLock (
- IN PFILE_LOCK FileLock,
- IN BOOLEAN Restart
- )
-{
- /*
- Messy enumeration of granted locks.
- 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...
- */
- KIRQL oldirql;
- PLIST_ENTRY EnumEntry;
- PFILE_LOCK_GRANTED Granted;
- PFILE_LOCK_TOC LockToc;
- BOOLEAN FoundPrevious = FALSE;
- //must make local copy since FILE_LOCK struct is allowed to be in paged mem
- FILE_LOCK_INFO LocalLastReturnedLockInfo;
- PVOID LocalLastReturnedLock;
-
- ASSERT(FileLock);
- LockToc = FileLock->LockInformation;
- if (LockToc == NULL)
- {
- return NULL;
- }
-
- LocalLastReturnedLock = FileLock->LastReturnedLock;
-
- KeAcquireSpinLock(&LockToc->SpinLock,&oldirql);
-
-restart:;
-
- EnumEntry = LockToc->GrantedListHead.Flink;
-
- if (Restart)
- {
- if (EnumEntry != &LockToc->GrantedListHead)
- {
- Granted = CONTAINING_RECORD(EnumEntry,FILE_LOCK_GRANTED,ListEntry);
- LocalLastReturnedLockInfo = Granted->Lock;
- KeReleaseSpinLock(&LockToc->SpinLock,oldirql);
-
- FileLock->LastReturnedLockInfo = LocalLastReturnedLockInfo;
- FileLock->LastReturnedLock = EnumEntry;
- return &FileLock->LastReturnedLockInfo;
- }
- else
- {
- KeReleaseSpinLock(&LockToc->SpinLock,oldirql);
- return NULL;
- }
- }
-
- //else: continue enum
- while (EnumEntry != &LockToc->GrantedListHead)
- {
- //found previous lock?
- if (EnumEntry == LocalLastReturnedLock)
- {
- FoundPrevious = TRUE;
- //get next
- EnumEntry = EnumEntry->Flink;
- if (EnumEntry != &LockToc->GrantedListHead)
- {
- Granted = CONTAINING_RECORD(EnumEntry,FILE_LOCK_GRANTED,ListEntry);
- LocalLastReturnedLockInfo = Granted->Lock;
- KeReleaseSpinLock(&LockToc->SpinLock,oldirql);
-
- FileLock->LastReturnedLockInfo = LocalLastReturnedLockInfo;
- FileLock->LastReturnedLock = EnumEntry;
- return &FileLock->LastReturnedLockInfo;
- }
- break;
- }
- EnumEntry = EnumEntry->Flink;
- }
-
- if (!FoundPrevious)
- {
- //got here? uh no, didn't find our last lock..must have been freed...restart
- Restart = TRUE;
- goto restart;
- }
-
- KeReleaseSpinLock(&LockToc->SpinLock,oldirql);
-
- return NULL;//no (more) locks
-}
-
-
-/**********************************************************************
- * NAME EXPORTED
- * FsRtlInitializeFileLock
- *
- * NOTE
- * Called when creating/allocating/initializing FCB
- *
- * @implemented
- */
-VOID
-STDCALL
-FsRtlInitializeFileLock (
- IN PFILE_LOCK FileLock,
- IN PCOMPLETE_LOCK_IRP_ROUTINE CompleteLockIrpRoutine OPTIONAL,
- IN PUNLOCK_ROUTINE UnlockRoutine OPTIONAL
- )
-{
-
- FsRtlAreThereCurrentFileLocks(FileLock) = FALSE;
- FileLock->CompleteLockIrpRoutine = CompleteLockIrpRoutine;
- FileLock->UnlockRoutine = UnlockRoutine;
- FileLock->LockInformation = NULL;
-
-}
-
-
-/**********************************************************************
- * NAME EXPORTED
- * FsRtlPrivateLock
- *
- * @implemented
- */
-BOOLEAN
-STDCALL
-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, //seems meaningless for fast io
- IN BOOLEAN ExclusiveLock,
- OUT PIO_STATUS_BLOCK IoStatus,
- IN PIRP Irp OPTIONAL,
- IN PVOID Context OPTIONAL,
- IN BOOLEAN AlreadySynchronized
- )
-{
- PFILE_LOCK_TOC LockToc;
- KIRQL oldirql;
-
- ASSERT(FileLock);
- if (FileLock->LockInformation == NULL)
- {
- ExAcquireFastMutex(&LockTocMutex);
- //still NULL?
- if (FileLock->LockInformation == NULL)
- {
- FileLock->LockInformation =
ExAllocateFromNPagedLookasideList(&LockTocLookaside);
- LockToc = FileLock->LockInformation;
- KeInitializeSpinLock(&LockToc->SpinLock);
- InitializeListHead(&LockToc->GrantedListHead);
- InitializeListHead(&LockToc->PendingListHead);
- }
- ExReleaseFastMutex(&LockTocMutex);
- }
-
- LockToc = FileLock->LockInformation;
- KeAcquireSpinLock(&LockToc->SpinLock, &oldirql);
-
- //try add new lock (while holding spin lock)
- if (FsRtlpAddLock(LockToc,
- FileObject,
- FileOffset,
- Length,
- Process,
- Key,
- ExclusiveLock,
- Context
- ) )
- {
- IoStatus->Status = STATUS_SUCCESS;
- }
- else if (Irp && !FailImmediately)
- {
- //failed + irp + no fail = make. pending
-
- Irp->Tail.Overlay.DriverContext[3] = &LockToc->SpinLock;
- Irp->Tail.Overlay.DriverContext[2] = Context;
-
- (void)IoSetCancelRoutine(Irp, FsRtlpFileLockCancelRoutine);
- if (Irp->Cancel && IoSetCancelRoutine(Irp, NULL))
- {
- //irp was canceled
- KeReleaseSpinLock(&LockToc->SpinLock, oldirql);
-
- Irp->IoStatus.Status = STATUS_CANCELLED;
- Irp->IoStatus.Information = 0;
- IoCompleteRequest(Irp, IO_NO_INCREMENT);
-
- return TRUE;
- }
-
- IoMarkIrpPending(Irp);
- Irp->IoStatus.Status = IoStatus->Status = STATUS_PENDING;
- Irp->IoStatus.Information = 0;
-
InsertHeadList(&LockToc->PendingListHead,&Irp->Tail.Overlay.ListEntry);
-
- }
- else
- {
- IoStatus->Status = STATUS_LOCK_NOT_GRANTED;
- }
-
- KeReleaseSpinLock(&LockToc->SpinLock, oldirql); //fires cancel routine
-
- //never pending if no irp;-)
- ASSERT(!(IoStatus->Status == STATUS_PENDING && !Irp));
-
- if (IoStatus->Status != STATUS_PENDING)
- {
- if (IoStatus->Status == STATUS_SUCCESS)
- {
- FsRtlAreThereCurrentFileLocks(FileLock) = TRUE;
- }
-
- if (Irp)
- {
- Irp->IoStatus.Status = IoStatus->Status;
- Irp->IoStatus.Information = 0;
- if (FileLock->CompleteLockIrpRoutine)
- {
- if (FileLock->CompleteLockIrpRoutine(Context,Irp)!=STATUS_SUCCESS)
- {
- //CompleteLockIrpRoutine complain: revert changes
- FsRtlpUnlockSingle( FileLock,
+ TRUE);
+}
+
+/*
+ * @implemented
+ */
+NTSTATUS
+NTAPI
+FsRtlFastUnlockAll(IN PFILE_LOCK FileLock,
+ IN PFILE_OBJECT FileObject,
+ IN PEPROCESS Process,
+ IN PVOID Context OPTIONAL)
+{
+ /* Call the generic function by process */
+ return FsRtlpFastUnlockAllByKey(FileLock,
FileObject,
- FileOffset,
- Length,
+ Process,
+ 0,
+ FALSE,
+ Context);
+}
+
+/*
+ * @implemented
+ */
+NTSTATUS
+NTAPI
+FsRtlFastUnlockAllByKey(IN PFILE_LOCK FileLock,
+ IN PFILE_OBJECT FileObject,
+ IN PEPROCESS Process,
+ IN ULONG Key,
+ IN PVOID Context OPTIONAL)
+{
+ /* Call the generic function by key */
+ return FsRtlpFastUnlockAllByKey(FileLock,
+ FileObject,
Process,
Key,
- NULL, /* context */
- FALSE /* don't call unlock copletion routine */
- );
- }
- }
- else
- {
- IoCompleteRequest(Irp, IO_NO_INCREMENT);
- }
- }
- }
-
- //NOTE: only fast io seems to care about this return value
- return (IoStatus->Status == STATUS_SUCCESS || FailImmediately);
-
-}
-
-
-
-/**********************************************************************
- * NAME EXPORTED
- * FsRtlProcessFileLock
- *
+ TRUE,
+ Context);
+}
+
+/*
* @implemented
*/
NTSTATUS
-STDCALL
-FsRtlProcessFileLock (
- IN PFILE_LOCK FileLock,
- IN PIRP Irp,
- IN PVOID Context OPTIONAL
- )
-{
- PIO_STACK_LOCATION Stack;
- NTSTATUS Status;
- IO_STATUS_BLOCK LocalIoStatus;
-
- ASSERT(FileLock);
- Stack = IoGetCurrentIrpStackLocation(Irp);
- Irp->IoStatus.Information = 0;
-
- switch(Stack->MinorFunction)
- {
- case IRP_MN_LOCK:
- //ret: BOOLEAN
- FsRtlPrivateLock( FileLock,
- Stack->FileObject,
- &Stack->Parameters.LockControl.ByteOffset, //not
pointer!
- Stack->Parameters.LockControl.Length,
- IoGetRequestorProcess(Irp),
- Stack->Parameters.LockControl.Key,
- Stack->Flags & SL_FAIL_IMMEDIATELY,
- Stack->Flags & SL_EXCLUSIVE_LOCK,
- &LocalIoStatus,
- Irp,
- Context,
- FALSE);
-
- return LocalIoStatus.Status;
-
- case IRP_MN_UNLOCK_SINGLE:
- Status = FsRtlFastUnlockSingle ( FileLock,
- Stack->FileObject,
-
&Stack->Parameters.LockControl.ByteOffset,
- Stack->Parameters.LockControl.Length,
- IoGetRequestorProcess(Irp),
- Stack->Parameters.LockControl.Key,
- Context,
- FALSE);
- break;
-
- case IRP_MN_UNLOCK_ALL:
- Status = FsRtlFastUnlockAll( FileLock,
- Stack->FileObject,
- IoGetRequestorProcess(Irp),
- Context );
- break;
-
- case IRP_MN_UNLOCK_ALL_BY_KEY:
- Status = FsRtlFastUnlockAllByKey ( FileLock,
- Stack->FileObject,
- IoGetRequestorProcess(Irp),
- Stack->Parameters.LockControl.Key,
- Context );
-
- break;
-
- default:
- Irp->IoStatus.Status = Status = STATUS_INVALID_DEVICE_REQUEST;
- IoCompleteRequest(Irp, IO_NO_INCREMENT);
- return Status;
- }
-
-
- Irp->IoStatus.Status = Status;
- Irp->IoStatus.Information = 0;
-
- IoCompleteRequest(Irp,IO_NO_INCREMENT);
-
- return Status;
-}
-
-
-/**********************************************************************
- * NAME EXPORTED
- * FsRtlUninitializeFileLock
- *
+NTAPI
+FsRtlProcessFileLock(IN PFILE_LOCK FileLock,
+ IN PIRP Irp,
+ IN PVOID Context OPTIONAL)
+{
+ PIO_STACK_LOCATION IoStackLocation;
+ NTSTATUS Status;
+ IO_STATUS_BLOCK IoStatusBlock;
+
+ /* Get the I/O Stack location */
+ IoStackLocation = IoGetCurrentIrpStackLocation(Irp);
+ ASSERT(IoStackLocation->MajorFunction == IRP_MJ_LOCK_CONTROL);
+
+ /* Clear the I/O status block and check what function this is */
+ IoStatusBlock.Information = 0;
+ switch(IoStackLocation->MinorFunction)
+ {
+ /* A lock */
+ case IRP_MN_LOCK:
+
+ /* Call the private lock routine */
+ FsRtlPrivateLock(FileLock,
+ IoStackLocation->FileObject,
+ &IoStackLocation->
+ Parameters.LockControl.ByteOffset,
+ IoStackLocation->Parameters.LockControl.Length,
+ IoGetRequestorProcess(Irp),
+ IoStackLocation->Parameters.LockControl.Key,
+ IoStackLocation->Flags & SL_FAIL_IMMEDIATELY,
+ IoStackLocation->Flags & SL_EXCLUSIVE_LOCK,
+ &IoStatusBlock,
+ Irp,
+ Context,
+ FALSE);
+ break;
+
+ /* A single unlock */
+ case IRP_MN_UNLOCK_SINGLE:
+
+ /* Call fast unlock */
+ IoStatusBlock.Status =
+ FsRtlFastUnlockSingle(FileLock,
+ IoStackLocation->FileObject,
+ &IoStackLocation->Parameters.LockControl.
+ ByteOffset,
+ IoStackLocation->Parameters.LockControl.
+ Length,
+ IoGetRequestorProcess(Irp),
+ IoStackLocation->Parameters.LockControl.
+ Key,
+ Context,
+ FALSE);
+
+ /* Complete the IRP */
+ FsRtlCompleteLockIrpReal(FileLock->CompleteLockIrpRoutine,
+ Context,
+ Irp,
+ IoStatusBlock.Status,
+ &Status,
+ NULL);
+ break;
+
+ /* Total unlock */
+ case IRP_MN_UNLOCK_ALL:
+
+ /* Do a fast unlock */
+ IoStatusBlock.Status = FsRtlFastUnlockAll(FileLock,
+ IoStackLocation->
+ FileObject,
+ IoGetRequestorProcess(Irp),
+ Context);
+
+ /* Complete the IRP */
+ FsRtlCompleteLockIrpReal(FileLock->CompleteLockIrpRoutine,
+ Context,
+ Irp,
+ IoStatusBlock.Status,
+ &Status,
+ NULL);
+ break;
+
+ /* Unlock by key */
+ case IRP_MN_UNLOCK_ALL_BY_KEY:
+
+ /* Do it */
+ IoStatusBlock.Status =
+ FsRtlFastUnlockAllByKey(FileLock,
+ IoStackLocation->FileObject,
+ IoGetRequestorProcess(Irp),
+ IoStackLocation->Parameters.
+ LockControl.Key,
+ Context);
+
+ /* Complete the IRP */
+ FsRtlCompleteLockIrpReal(FileLock->CompleteLockIrpRoutine,
+ Context,
+ Irp,
+ IoStatusBlock.Status,
+ &Status,
+ NULL);
+ break;
+
+ /* Invalid request */
+ default:
+
+ /* Complete it */
+ FsRtlCompleteRequest(Irp, STATUS_INVALID_DEVICE_REQUEST);
+ IoStatusBlock.Status = STATUS_INVALID_DEVICE_REQUEST;
+ break;
+ }
+
+ /* Return the status */
+ return IoStatusBlock.Status;
+}
+
+/*
* @implemented
*/
VOID
-STDCALL
-FsRtlUninitializeFileLock (
- IN PFILE_LOCK FileLock
- )
-{
- PFILE_LOCK_TOC LockToc;
- PIRP Irp;
- PFILE_LOCK_GRANTED Granted;
- PLIST_ENTRY EnumEntry;
- KIRQL oldirql;
-
- ASSERT(FileLock);
- if (FileLock->LockInformation == NULL)
- {
- return;
- }
-
- LockToc = FileLock->LockInformation;
-
- KeAcquireSpinLock(&LockToc->SpinLock, &oldirql);
-
- //remove and free granted locks
- while (!IsListEmpty(&LockToc->GrantedListHead))
- {
- EnumEntry = RemoveTailList(&LockToc->GrantedListHead);
- Granted = CONTAINING_RECORD(EnumEntry, FILE_LOCK_GRANTED, ListEntry);
- ExFreeToNPagedLookasideList(&GrantedLookaside, Granted);
- }
-
- //remove, complete and free all pending locks
- 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;
- }
-
- KeReleaseSpinLock(&LockToc->SpinLock, oldirql);
-
- Irp->IoStatus.Status = STATUS_RANGE_NOT_LOCKED;
- Irp->IoStatus.Information = 0;
- IoCompleteRequest(Irp, IO_NO_INCREMENT);
-
- KeAcquireSpinLock(&LockToc->SpinLock, &oldirql);
-
- }
-
- KeReleaseSpinLock(&LockToc->SpinLock, oldirql);
-
- ExFreeToNPagedLookasideList(&LockTocLookaside, LockToc);
-
- FsRtlAreThereCurrentFileLocks(FileLock) = FALSE;
- FileLock->LockInformation = NULL;
-
-}
-
-
-/**********************************************************************
- * NAME EXPORTED
- * FsRtlAllocateFileLock
- *
- * NOTE
- * Only present in NT 5.0 or later.
- * FCB FILE_LOCK struct should/is acording to DDK allocated from paged pool!
- *
+NTAPI
+FsRtlInitializeFileLock (IN PFILE_LOCK FileLock,
+ IN PCOMPLETE_LOCK_IRP_ROUTINE CompleteLockIrpRoutine OPTIONAL,
+ IN PUNLOCK_ROUTINE UnlockRoutine OPTIONAL)
+{
+ /* Setup the lock */
+ FileLock->FastIoIsQuestionable = FALSE;
+ FileLock->CompleteLockIrpRoutine = CompleteLockIrpRoutine;
+ FileLock->UnlockRoutine = UnlockRoutine;
+ FileLock->LockInformation = NULL;
+}
+
+/*
+ * @implemented
+ */
+VOID
+NTAPI
+FsRtlUninitializeFileLock(IN PFILE_LOCK FileLock)
+{
+ PFILE_LOCK_TOC LockToc;
+ PIRP Irp;
+ PFILE_LOCK_GRANTED Granted;
+ PLIST_ENTRY EnumEntry;
+ KIRQL OldIrql;
+
+ /* Get the lock information */
+ LockToc = FileLock->LockInformation;
+ if (!FileLock->LockInformation) return;
+
+ /* Acquire the lock queue */
+ KeAcquireSpinLock(&LockToc->SpinLock, &OldIrql);
+
+ /* Loop the lock tree */
+ while (!IsListEmpty(&LockToc->GrantedListHead))
+ {
+ /* Get the entry */
+ EnumEntry = RemoveTailList(&LockToc->GrantedListHead);
+
+ /* Get the granted lock and free it */
+ Granted = CONTAINING_RECORD(EnumEntry, FILE_LOCK_GRANTED, ListEntry);
+ ExFreeToNPagedLookasideList(&GrantedLookaside, Granted);
+ }
+
+ /* Loop the waiting locks */
+ while (!IsListEmpty(&LockToc->PendingListHead))
+ {
+ /* Get the entry and IRP */
+ EnumEntry = RemoveTailList(&LockToc->PendingListHead);
+ Irp = CONTAINING_RECORD(EnumEntry, IRP, Tail.Overlay.ListEntry);
+
+ /* Release the lock */
+ KeReleaseSpinLock(&LockToc->SpinLock, OldIrql);
+
+ /* Acquire cancel spinlock and clear the cancel routine */
+ IoAcquireCancelSpinLock(&Irp->CancelIrql);
+ IoSetCancelRoutine(Irp, NULL);
+ IoReleaseCancelSpinLock(Irp->CancelIrql);
+
+ /* Complete the IRP */
+ Irp->IoStatus.Information = 0;
+ Irp->IoStatus.Status = STATUS_RANGE_NOT_LOCKED;
+ IoCompleteRequest(Irp, IO_NO_INCREMENT);
+
+ /* Acquire the lock again */
+ KeAcquireSpinLock(&LockToc->SpinLock, &OldIrql);
+ }
+
+ /* Release the lock and free it */
+ KeReleaseSpinLock(&LockToc->SpinLock, OldIrql);
+ ExFreeToNPagedLookasideList(&LockTocLookaside, LockToc);
+
+ /* Remove the lock information pointer */
+ FileLock->LockInformation = NULL;
+}
+
+/*
* @implemented
*/
PFILE_LOCK
-STDCALL
-FsRtlAllocateFileLock(
- IN PCOMPLETE_LOCK_IRP_ROUTINE CompleteLockIrpRoutine OPTIONAL,
- IN PUNLOCK_ROUTINE UnlockRoutine OPTIONAL
- )
-{
- PFILE_LOCK FileLock;
-
- FileLock = ExAllocateFromPagedLookasideList(&LockLookaside);
-
- FsRtlInitializeFileLock(FileLock,
- CompleteLockIrpRoutine,
- UnlockRoutine
- );
-
- return FileLock;
-}
-
-/**********************************************************************
- * NAME EXPORTED
- * FsRtlFreeFileLock
- *
- * NOTE
- * Only present in NT 5.0 or later.
- * FCB FILE_LOCK struct should/is acording to DDK allocated from paged pool!
- *
+NTAPI
+FsRtlAllocateFileLock(IN PCOMPLETE_LOCK_IRP_ROUTINE CompleteLockIrpRoutine OPTIONAL,
+ IN PUNLOCK_ROUTINE UnlockRoutine OPTIONAL)
+{
+ PFILE_LOCK FileLock;
+
+ /* Try to allocate it */
+ FileLock = ExAllocateFromPagedLookasideList(&LockLookaside);
+ if (FileLock)
+ {
+ /* Initialize it */
+ FsRtlInitializeFileLock(FileLock,
+ CompleteLockIrpRoutine,
+ UnlockRoutine);
+ }
+
+ /* Return the lock */
+ return FileLock;
+}
+
+/*
* @implemented
*/
VOID
-STDCALL
-FsRtlFreeFileLock(
- IN PFILE_LOCK 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;
-}
-
+NTAPI
+FsRtlFreeFileLock(IN PFILE_LOCK FileLock)
+{
+ /* Uninitialize and free the lock */
+ FsRtlUninitializeFileLock(FileLock);
+ ExFreeToPagedLookasideList(&LockLookaside, FileLock);
+}
/* EOF */