mirror of
https://github.com/reactos/reactos.git
synced 2025-08-07 00:03:03 +00:00
filelock.c:
-general cleanup -fix signed -> unsigned comparsion -allow zero length unlocks to complete with success -makes some more wine reg. tests pass ntdef.h: add macros LIST_FOR_EACH and LIST_FOR_EACH_SAFE svn path=/trunk/; revision=12391
This commit is contained in:
parent
f5e28a77d1
commit
c97559f3c5
5 changed files with 258 additions and 233 deletions
|
@ -113,12 +113,5 @@
|
||||||
|
|
||||||
#endif /* !__USE_W32API */
|
#endif /* !__USE_W32API */
|
||||||
|
|
||||||
typedef struct _FILE_LOCK_TOC {
|
|
||||||
KSPIN_LOCK SpinLock;
|
|
||||||
LIST_ENTRY GrantedListHead;
|
|
||||||
LIST_ENTRY PendingListHead;
|
|
||||||
LIST_ENTRY CompletedListHead;
|
|
||||||
LIST_ENTRY UnlockedListHead;
|
|
||||||
} FILE_LOCK_TOC, *PFILE_LOCK_TOC;
|
|
||||||
|
|
||||||
#endif /* __INCLUDE_FILE_H */
|
#endif /* __INCLUDE_FILE_H */
|
||||||
|
|
|
@ -28,8 +28,14 @@ typedef struct _MCB {
|
||||||
typedef struct _FILE_LOCK_GRANTED {
|
typedef struct _FILE_LOCK_GRANTED {
|
||||||
LIST_ENTRY ListEntry;
|
LIST_ENTRY ListEntry;
|
||||||
FILE_LOCK_INFO Lock;
|
FILE_LOCK_INFO Lock;
|
||||||
|
PVOID UnlockContext;
|
||||||
} FILE_LOCK_GRANTED, *PFILE_LOCK_GRANTED;
|
} FILE_LOCK_GRANTED, *PFILE_LOCK_GRANTED;
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct _FILE_LOCK_TOC {
|
||||||
|
KSPIN_LOCK SpinLock;
|
||||||
|
LIST_ENTRY GrantedListHead;
|
||||||
|
LIST_ENTRY PendingListHead;
|
||||||
|
} FILE_LOCK_TOC, *PFILE_LOCK_TOC;
|
||||||
|
|
||||||
#endif /* __INCLUDE_DDK_FSTYPES_H */
|
#endif /* __INCLUDE_DDK_FSTYPES_H */
|
||||||
|
|
|
@ -39,6 +39,20 @@
|
||||||
#define SECONDS_TO_100NS(seconds) (((LONGLONG)(seconds)) * MILLIS_TO_100NS(1000L))
|
#define SECONDS_TO_100NS(seconds) (((LONGLONG)(seconds)) * MILLIS_TO_100NS(1000L))
|
||||||
|
|
||||||
|
|
||||||
|
/* Helpers for enumarating lists */
|
||||||
|
#define LIST_FOR_EACH(entry, head) \
|
||||||
|
for(entry = (head)->Flink; entry != (head); entry = entry->Flink)
|
||||||
|
|
||||||
|
/*
|
||||||
|
Safe version which saves pointer to the next entry so the current ptr->field entry
|
||||||
|
can be unlinked without corrupting the list. NOTE: Never unlink tmp_entry!!!!!!!!!
|
||||||
|
*/
|
||||||
|
#define LIST_FOR_EACH_SAFE(tmp_entry, head, ptr, type, field) \
|
||||||
|
for ((tmp_entry)=(head)->Flink; (tmp_entry)!=(head) && \
|
||||||
|
((ptr) = CONTAINING_RECORD(tmp_entry,type,field)) && \
|
||||||
|
((tmp_entry) = (tmp_entry)->Flink); )
|
||||||
|
|
||||||
|
|
||||||
#ifndef __USE_W32API
|
#ifndef __USE_W32API
|
||||||
|
|
||||||
#define ANYSIZE_ARRAY (1)
|
#define ANYSIZE_ARRAY (1)
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
/* $Id: filelock.c,v 1.16 2004/12/23 12:30:48 ekohl Exp $
|
/* $Id: filelock.c,v 1.17 2004/12/30 02:30:40 gdalsnes Exp $
|
||||||
*
|
*
|
||||||
* reactos/ntoskrnl/fs/filelock.c
|
* reactos/ntoskrnl/fs/filelock.c
|
||||||
*
|
*
|
||||||
|
@ -13,18 +13,54 @@ NOTE:
|
||||||
I'm not using resource syncronization here, since FsRtlFastCheckLockForRead/Write
|
I'm not using resource syncronization here, since FsRtlFastCheckLockForRead/Write
|
||||||
are allowed to be called at DISPATCH_LEVEL. Must therefore use nonpaged memory for
|
are allowed to be called at DISPATCH_LEVEL. Must therefore use nonpaged memory for
|
||||||
the lists.
|
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;
|
FAST_MUTEX LockTocMutex;
|
||||||
NPAGED_LOOKASIDE_LIST GrantedLookaside;
|
NPAGED_LOOKASIDE_LIST GrantedLookaside;
|
||||||
NPAGED_LOOKASIDE_LIST LockTocLookaside;
|
NPAGED_LOOKASIDE_LIST LockTocLookaside;
|
||||||
PAGED_LOOKASIDE_LIST LockLookaside;
|
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
|
* NAME PRIVATE
|
||||||
* FsRtlpInitFileLockingImplementation
|
* FsRtlpInitFileLockingImplementation
|
||||||
|
@ -62,6 +98,7 @@ FsRtlpInitFileLockingImplementation(VOID)
|
||||||
);
|
);
|
||||||
|
|
||||||
ExInitializeFastMutex(&LockTocMutex);
|
ExInitializeFastMutex(&LockTocMutex);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**********************************************************************
|
/**********************************************************************
|
||||||
|
@ -78,28 +115,22 @@ FsRtlpFileLockCancelRoutine(
|
||||||
{
|
{
|
||||||
KIRQL oldIrql;
|
KIRQL oldIrql;
|
||||||
PKSPIN_LOCK SpinLock;
|
PKSPIN_LOCK SpinLock;
|
||||||
PCOMPLETE_LOCK_IRP_ROUTINE CompleteLockIrpRoutine;
|
|
||||||
|
|
||||||
//don't need this since we have our own sync. protecting irp cancellation
|
//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);
|
KeAcquireSpinLock(SpinLock, &oldIrql);
|
||||||
|
|
||||||
RemoveEntryList(&Irp->Tail.Overlay.ListEntry);
|
RemoveEntryList(&Irp->Tail.Overlay.ListEntry);
|
||||||
|
|
||||||
KeReleaseSpinLock(SpinLock, oldIrql);
|
KeReleaseSpinLock(SpinLock, oldIrql);
|
||||||
|
|
||||||
Irp->IoStatus.Status = STATUS_CANCELLED;
|
Irp->IoStatus.Status = STATUS_CANCELLED;
|
||||||
|
Irp->IoStatus.Information = 0;
|
||||||
|
|
||||||
CompleteLockIrpRoutine = ((PFILE_LOCK)Irp->Tail.Overlay.DriverContext[0])->CompleteLockIrpRoutine;
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||||
if (CompleteLockIrpRoutine)
|
|
||||||
{
|
|
||||||
CompleteLockIrpRoutine(Irp->Tail.Overlay.DriverContext[2], Irp);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
IofCompleteRequest(Irp, IO_NO_INCREMENT);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -107,6 +138,9 @@ FsRtlpFileLockCancelRoutine(
|
||||||
* NAME PRIVATE
|
* NAME PRIVATE
|
||||||
* FsRtlpCheckLockForReadOrWriteAccess
|
* FsRtlpCheckLockForReadOrWriteAccess
|
||||||
*
|
*
|
||||||
|
* Return:
|
||||||
|
* TRUE: can read/write
|
||||||
|
* FALSE: can't read/write
|
||||||
*/
|
*/
|
||||||
BOOLEAN
|
BOOLEAN
|
||||||
FASTCALL
|
FASTCALL
|
||||||
|
@ -124,8 +158,10 @@ FsRtlpCheckLockForReadOrWriteAccess(
|
||||||
PFILE_LOCK_TOC LockToc;
|
PFILE_LOCK_TOC LockToc;
|
||||||
PFILE_LOCK_GRANTED Granted;
|
PFILE_LOCK_GRANTED Granted;
|
||||||
PLIST_ENTRY EnumEntry;
|
PLIST_ENTRY EnumEntry;
|
||||||
|
LARGE_INTEGER EndOffset;
|
||||||
|
|
||||||
ASSERT(FileLock);
|
ASSERT(FileLock);
|
||||||
|
|
||||||
LockToc = FileLock->LockInformation;
|
LockToc = FileLock->LockInformation;
|
||||||
|
|
||||||
if (LockToc == NULL || Length->QuadPart == 0)
|
if (LockToc == NULL || Length->QuadPart == 0)
|
||||||
|
@ -133,15 +169,16 @@ FsRtlpCheckLockForReadOrWriteAccess(
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
EndOffset.QuadPart = FileOffset->QuadPart + Length->QuadPart - 1;
|
||||||
|
|
||||||
KeAcquireSpinLock(&LockToc->SpinLock, &oldirql);
|
KeAcquireSpinLock(&LockToc->SpinLock, &oldirql);
|
||||||
|
|
||||||
EnumEntry = LockToc->GrantedListHead.Flink;
|
LIST_FOR_EACH(EnumEntry, &LockToc->GrantedListHead)
|
||||||
while ( EnumEntry != &LockToc->GrantedListHead)
|
|
||||||
{
|
{
|
||||||
Granted = CONTAINING_RECORD(EnumEntry, FILE_LOCK_GRANTED , ListEntry );
|
Granted = CONTAINING_RECORD(EnumEntry, FILE_LOCK_GRANTED, ListEntry);
|
||||||
|
|
||||||
//if overlapping
|
//if overlapping
|
||||||
if(!(REQUEST_START_OFF > LOCK_END_OFF(Granted->Lock) ||
|
if(IsOverlappingLock(&Granted->Lock, FileOffset, &EndOffset))
|
||||||
REQUEST_END_OFF < LOCK_START_OFF(Granted->Lock)))
|
|
||||||
{
|
{
|
||||||
//No read conflict if (shared lock) OR (exclusive + our lock)
|
//No read conflict if (shared lock) OR (exclusive + our lock)
|
||||||
//No write conflict if exclusive lock AND our lock
|
//No write conflict if exclusive lock AND our lock
|
||||||
|
@ -152,30 +189,26 @@ FsRtlpCheckLockForReadOrWriteAccess(
|
||||||
Granted->Lock.Key == Key ) )
|
Granted->Lock.Key == Key ) )
|
||||||
{
|
{
|
||||||
//AND if lock surround request region, stop searching and grant
|
//AND if lock surround request region, stop searching and grant
|
||||||
if (REQUEST_START_OFF >= LOCK_START_OFF(Granted->Lock) &&
|
if (IsSurroundingLock(&Granted->Lock, FileOffset, &EndOffset) )
|
||||||
REQUEST_END_OFF <= LOCK_END_OFF(Granted->Lock))
|
|
||||||
{
|
{
|
||||||
EnumEntry = &LockToc->GrantedListHead;//indicate no conflict
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
//else continue searching for conflicts
|
|
||||||
}
|
|
||||||
else //conflict
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
EnumEntry = EnumEntry->Flink;
|
|
||||||
}
|
|
||||||
|
|
||||||
KeReleaseSpinLock(&LockToc->SpinLock, oldirql);
|
KeReleaseSpinLock(&LockToc->SpinLock, oldirql);
|
||||||
|
|
||||||
if (EnumEntry == &LockToc->GrantedListHead)
|
|
||||||
{ //no conflict
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//else continue searching for conflicts
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
//found conflict
|
||||||
|
KeReleaseSpinLock(&LockToc->SpinLock, oldirql);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//no conflict
|
||||||
|
KeReleaseSpinLock(&LockToc->SpinLock, oldirql);
|
||||||
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -206,7 +239,7 @@ FsRtlCheckLockForReadAccess (
|
||||||
Stack->Parameters.Read.Key,
|
Stack->Parameters.Read.Key,
|
||||||
Stack->FileObject,
|
Stack->FileObject,
|
||||||
IoGetRequestorProcess(Irp),
|
IoGetRequestorProcess(Irp),
|
||||||
TRUE//Read?
|
TRUE /* Read */
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -238,7 +271,7 @@ FsRtlCheckLockForWriteAccess (
|
||||||
Stack->Parameters.Write.Key,
|
Stack->Parameters.Write.Key,
|
||||||
Stack->FileObject,
|
Stack->FileObject,
|
||||||
IoGetRequestorProcess(Irp),
|
IoGetRequestorProcess(Irp),
|
||||||
FALSE//Read?
|
FALSE /* Read */
|
||||||
);
|
);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -269,7 +302,7 @@ FsRtlFastCheckLockForRead (
|
||||||
Key,
|
Key,
|
||||||
FileObject,
|
FileObject,
|
||||||
Process,
|
Process,
|
||||||
TRUE//Read?
|
TRUE /* Read */
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -297,7 +330,7 @@ FsRtlFastCheckLockForWrite (
|
||||||
Key,
|
Key,
|
||||||
FileObject,
|
FileObject,
|
||||||
Process,
|
Process,
|
||||||
FALSE//Read?
|
FALSE /* Read */
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -314,8 +347,8 @@ FsRtlpFastUnlockAllByKey(
|
||||||
IN PFILE_LOCK FileLock,
|
IN PFILE_LOCK FileLock,
|
||||||
IN PFILE_OBJECT FileObject,
|
IN PFILE_OBJECT FileObject,
|
||||||
IN PEPROCESS Process,
|
IN PEPROCESS Process,
|
||||||
IN DWORD Key, /* FIXME: guess */
|
IN DWORD Key,
|
||||||
IN BOOLEAN UseKey, /* FIXME: guess */
|
IN BOOLEAN UseKey,
|
||||||
IN PVOID Context OPTIONAL
|
IN PVOID Context OPTIONAL
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
|
@ -325,7 +358,8 @@ FsRtlpFastUnlockAllByKey(
|
||||||
PFILE_LOCK_GRANTED Granted;
|
PFILE_LOCK_GRANTED Granted;
|
||||||
BOOLEAN Unlock = FALSE;
|
BOOLEAN Unlock = FALSE;
|
||||||
//must make local copy since FILE_LOCK struct is allowed to be paged
|
//must make local copy since FILE_LOCK struct is allowed to be paged
|
||||||
PUNLOCK_ROUTINE GotUnlockRoutine;
|
BOOLEAN GotUnlockRoutine;
|
||||||
|
LIST_ENTRY UnlockedListHead;
|
||||||
|
|
||||||
ASSERT(FileLock);
|
ASSERT(FileLock);
|
||||||
LockToc = FileLock->LockInformation;
|
LockToc = FileLock->LockInformation;
|
||||||
|
@ -335,14 +369,12 @@ FsRtlpFastUnlockAllByKey(
|
||||||
return STATUS_RANGE_NOT_LOCKED;
|
return STATUS_RANGE_NOT_LOCKED;
|
||||||
}
|
}
|
||||||
|
|
||||||
GotUnlockRoutine = FileLock->UnlockRoutine;
|
InitializeListHead(&UnlockedListHead);
|
||||||
|
GotUnlockRoutine = FileLock->UnlockRoutine != NULL;
|
||||||
KeAcquireSpinLock(&LockToc->SpinLock, &oldirql);
|
KeAcquireSpinLock(&LockToc->SpinLock, &oldirql);
|
||||||
|
|
||||||
EnumEntry = LockToc->GrantedListHead.Flink;
|
LIST_FOR_EACH_SAFE(EnumEntry, &LockToc->GrantedListHead, Granted, FILE_LOCK_GRANTED, ListEntry)
|
||||||
while (EnumEntry != &LockToc->GrantedListHead )
|
|
||||||
{
|
{
|
||||||
Granted = CONTAINING_RECORD(EnumEntry,FILE_LOCK_GRANTED, ListEntry);
|
|
||||||
EnumEntry = EnumEntry->Flink;
|
|
||||||
|
|
||||||
if (Granted->Lock.Process == Process &&
|
if (Granted->Lock.Process == Process &&
|
||||||
Granted->Lock.FileObject == FileObject &&
|
Granted->Lock.FileObject == FileObject &&
|
||||||
|
@ -357,7 +389,7 @@ FsRtlpFastUnlockAllByKey(
|
||||||
Put on unlocked list and call unlock routine for them afterwards.
|
Put on unlocked list and call unlock routine for them afterwards.
|
||||||
This way we don't have to restart enum after each call
|
This way we don't have to restart enum after each call
|
||||||
*/
|
*/
|
||||||
InsertHeadList(&LockToc->UnlockedListHead,&Granted->ListEntry);
|
InsertHeadList(&UnlockedListHead,&Granted->ListEntry);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -366,21 +398,23 @@ FsRtlpFastUnlockAllByKey(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
KeReleaseSpinLock(&LockToc->SpinLock, oldirql);
|
||||||
|
|
||||||
if (Unlock)
|
if (Unlock)
|
||||||
{
|
{
|
||||||
//call unlock routine for each unlocked lock (if any)
|
//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);
|
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);
|
ExFreeToNPagedLookasideList(&GrantedLookaside,Granted);
|
||||||
KeAcquireSpinLock(&LockToc->SpinLock, &oldirql);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//NOTE: holding spinlock while calling this
|
//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))
|
||||||
{
|
{
|
||||||
|
@ -391,10 +425,10 @@ FsRtlpFastUnlockAllByKey(
|
||||||
{
|
{
|
||||||
KeReleaseSpinLock(&LockToc->SpinLock, oldirql);
|
KeReleaseSpinLock(&LockToc->SpinLock, oldirql);
|
||||||
}
|
}
|
||||||
|
|
||||||
return STATUS_SUCCESS;
|
return STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
KeReleaseSpinLock(&LockToc->SpinLock, oldirql);
|
|
||||||
return STATUS_RANGE_NOT_LOCKED;
|
return STATUS_RANGE_NOT_LOCKED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -416,7 +450,7 @@ FsRtlFastUnlockAll /*ByProcess*/ (
|
||||||
return FsRtlpFastUnlockAllByKey( FileLock,
|
return FsRtlpFastUnlockAllByKey( FileLock,
|
||||||
FileObject,
|
FileObject,
|
||||||
Process,
|
Process,
|
||||||
0, /* Key */
|
0, /* Key is ignored */
|
||||||
FALSE, /* Do NOT use Key */
|
FALSE, /* Do NOT use Key */
|
||||||
Context
|
Context
|
||||||
);
|
);
|
||||||
|
@ -455,7 +489,7 @@ FsRtlFastUnlockAllByKey (
|
||||||
* NOTE
|
* NOTE
|
||||||
* Spinlock held at entry !!
|
* Spinlock held at entry !!
|
||||||
*/
|
*/
|
||||||
NTSTATUS
|
BOOLEAN
|
||||||
FASTCALL
|
FASTCALL
|
||||||
FsRtlpAddLock(
|
FsRtlpAddLock(
|
||||||
IN PFILE_LOCK_TOC LockToc,
|
IN PFILE_LOCK_TOC LockToc,
|
||||||
|
@ -464,58 +498,60 @@ FsRtlpAddLock(
|
||||||
IN PLARGE_INTEGER Length,
|
IN PLARGE_INTEGER Length,
|
||||||
IN PEPROCESS Process,
|
IN PEPROCESS Process,
|
||||||
IN ULONG Key,
|
IN ULONG Key,
|
||||||
IN BOOLEAN ExclusiveLock
|
IN BOOLEAN ExclusiveLock,
|
||||||
|
IN PVOID Context
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
PLIST_ENTRY EnumEntry;
|
PLIST_ENTRY EnumEntry;
|
||||||
PFILE_LOCK_GRANTED Granted;
|
PFILE_LOCK_GRANTED Granted;
|
||||||
|
LARGE_INTEGER EndOffset;
|
||||||
|
|
||||||
EnumEntry = LockToc->GrantedListHead.Flink;
|
EndOffset.QuadPart = FileOffset->QuadPart + Length->QuadPart - 1;
|
||||||
while (EnumEntry != &LockToc->GrantedListHead)
|
|
||||||
|
//loop and try to find conflicking locks
|
||||||
|
LIST_FOR_EACH(EnumEntry, &LockToc->GrantedListHead)
|
||||||
{
|
{
|
||||||
Granted = CONTAINING_RECORD(EnumEntry,FILE_LOCK_GRANTED, ListEntry);
|
Granted = CONTAINING_RECORD(EnumEntry,FILE_LOCK_GRANTED, ListEntry);
|
||||||
//if overlapping
|
|
||||||
if(!(REQUEST_START_OFF > LOCK_END_OFF(Granted->Lock) ||
|
if (IsOverlappingLock(&Granted->Lock, FileOffset, &EndOffset))
|
||||||
REQUEST_END_OFF < LOCK_START_OFF(Granted->Lock)))
|
|
||||||
{
|
{
|
||||||
//never conflict if shared lock and we want to add a shared lock
|
//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 (!Granted->Lock.ExclusiveLock && !ExclusiveLock)
|
||||||
{
|
{
|
||||||
//AND if lock surround region, stop searching and insert lock
|
//if existing lock surround new lock, we know that no other exclusive lock
|
||||||
if (REQUEST_START_OFF >= LOCK_START_OFF(Granted->Lock) &&
|
//may overlap with our new lock;-D
|
||||||
REQUEST_END_OFF <= LOCK_END_OFF(Granted->Lock))
|
if (IsSurroundingLock(&Granted->Lock, FileOffset, &EndOffset))
|
||||||
{
|
{
|
||||||
EnumEntry = &LockToc->GrantedListHead;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
//else keep locking for conflicts
|
//else keep locking for conflicts
|
||||||
}
|
continue;
|
||||||
else
|
}
|
||||||
{//conflict if we want share access to excl. lock OR exlc. access to shared lock
|
|
||||||
break;//FAIL
|
//we found a conflict:
|
||||||
}
|
//we want shared access to an excl. lock OR exlc. access to a shared lock
|
||||||
}
|
return FALSE;
|
||||||
EnumEntry = EnumEntry->Flink;
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (EnumEntry == &LockToc->GrantedListHead)
|
|
||||||
{//no conflict
|
|
||||||
Granted = ExAllocateFromNPagedLookasideList(&GrantedLookaside);
|
Granted = ExAllocateFromNPagedLookasideList(&GrantedLookaside);
|
||||||
|
|
||||||
|
//starting offset
|
||||||
Granted->Lock.StartingByte = *FileOffset;
|
Granted->Lock.StartingByte = *FileOffset;
|
||||||
Granted->Lock.Length = *Length;
|
Granted->Lock.Length = *Length;
|
||||||
Granted->Lock.ExclusiveLock = ExclusiveLock;
|
Granted->Lock.ExclusiveLock = ExclusiveLock;
|
||||||
Granted->Lock.Key = Key;
|
Granted->Lock.Key = Key;
|
||||||
Granted->Lock.FileObject = FileObject;
|
Granted->Lock.FileObject = FileObject;
|
||||||
Granted->Lock.Process = Process;
|
Granted->Lock.Process = Process;
|
||||||
Granted->Lock.EndingByte.QuadPart = REQUEST_END_OFF;
|
//ending offset
|
||||||
|
Granted->Lock.EndingByte = EndOffset;
|
||||||
|
Granted->UnlockContext = Context;
|
||||||
|
|
||||||
InsertHeadList(&LockToc->GrantedListHead,&Granted->ListEntry);
|
InsertHeadList(&LockToc->GrantedListHead,&Granted->ListEntry);
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
|
||||||
|
|
||||||
return FALSE;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -532,19 +568,20 @@ FASTCALL
|
||||||
FsRtlpCompletePendingLocks(
|
FsRtlpCompletePendingLocks(
|
||||||
IN PFILE_LOCK FileLock,
|
IN PFILE_LOCK FileLock,
|
||||||
IN PFILE_LOCK_TOC LockToc,
|
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
|
//walk pending list, FIFO order, try 2 complete locks
|
||||||
PLIST_ENTRY EnumEntry;
|
PLIST_ENTRY EnumEntry;
|
||||||
PIRP Irp;
|
PIRP Irp;
|
||||||
PIO_STACK_LOCATION Stack;
|
PIO_STACK_LOCATION Stack;
|
||||||
|
LIST_ENTRY CompletedListHead;
|
||||||
|
|
||||||
EnumEntry = LockToc->PendingListHead.Blink;
|
InitializeListHead(&CompletedListHead);
|
||||||
while (EnumEntry != &LockToc->PendingListHead)
|
|
||||||
|
LIST_FOR_EACH_SAFE(EnumEntry, &LockToc->PendingListHead, Irp, IRP, Tail.Overlay.ListEntry)
|
||||||
{
|
{
|
||||||
Irp = CONTAINING_RECORD(EnumEntry,IRP, Tail.Overlay.ListEntry);
|
|
||||||
|
|
||||||
Stack = IoGetCurrentIrpStackLocation(Irp);
|
Stack = IoGetCurrentIrpStackLocation(Irp);
|
||||||
if (FsRtlpAddLock(LockToc,
|
if (FsRtlpAddLock(LockToc,
|
||||||
Stack->FileObject,
|
Stack->FileObject,
|
||||||
|
@ -552,55 +589,65 @@ FsRtlpCompletePendingLocks(
|
||||||
Stack->Parameters.LockControl.Length,
|
Stack->Parameters.LockControl.Length,
|
||||||
IoGetRequestorProcess(Irp),
|
IoGetRequestorProcess(Irp),
|
||||||
Stack->Parameters.LockControl.Key,
|
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);
|
RemoveEntryList(&Irp->Tail.Overlay.ListEntry);
|
||||||
|
|
||||||
if (!IoSetCancelRoutine(Irp, NULL))
|
if (!IoSetCancelRoutine(Irp, NULL))
|
||||||
{
|
{
|
||||||
/*
|
//irp is canceled and cancelroutine will run when we release the lock
|
||||||
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.
|
|
||||||
*/
|
|
||||||
InitializeListHead(&Irp->Tail.Overlay.ListEntry);
|
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.
|
Put on completed list and complete them all afterwards.
|
||||||
This way we don't have to restart enum after each completion.
|
This way we don't have to restart enum after each completion.
|
||||||
*/
|
*/
|
||||||
Irp->IoStatus.Status = STATUS_SUCCESS;
|
InsertHeadList(&CompletedListHead, &Irp->Tail.Overlay.ListEntry);
|
||||||
Irp->IoStatus.Information = 0;
|
|
||||||
InsertHeadList(&LockToc->CompletedListHead,&Irp->Tail.Overlay.ListEntry);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
EnumEntry = EnumEntry->Blink;
|
|
||||||
}
|
KeReleaseSpinLock(&LockToc->SpinLock, *oldirql);
|
||||||
|
|
||||||
//complete irp's (if any)
|
//complete irp's (if any)
|
||||||
while (!IsListEmpty(&LockToc->CompletedListHead))
|
while (!IsListEmpty(&CompletedListHead))
|
||||||
{
|
{
|
||||||
EnumEntry = RemoveTailList(&LockToc->CompletedListHead);
|
EnumEntry = RemoveTailList(&CompletedListHead);
|
||||||
KeReleaseSpinLock(&LockToc->SpinLock, *oldirql);//fires cancel routine
|
|
||||||
Irp = CONTAINING_RECORD(EnumEntry, IRP, Tail.Overlay.ListEntry);
|
Irp = CONTAINING_RECORD(EnumEntry, IRP, Tail.Overlay.ListEntry);
|
||||||
|
|
||||||
|
Irp->IoStatus.Status = STATUS_SUCCESS;
|
||||||
|
Irp->IoStatus.Information = 0;
|
||||||
|
|
||||||
if (FileLock->CompleteLockIrpRoutine)
|
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
|
else
|
||||||
{
|
{
|
||||||
IofCompleteRequest(Irp, IO_NO_INCREMENT);
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
KeAcquireSpinLock(&LockToc->SpinLock, oldirql);
|
KeAcquireSpinLock(&LockToc->SpinLock, oldirql);
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -620,7 +667,6 @@ FsRtlpUnlockSingle(
|
||||||
IN PEPROCESS Process,
|
IN PEPROCESS Process,
|
||||||
IN ULONG Key,
|
IN ULONG Key,
|
||||||
IN PVOID Context OPTIONAL,
|
IN PVOID Context OPTIONAL,
|
||||||
IN BOOLEAN AlreadySynchronized,
|
|
||||||
IN BOOLEAN CallUnlockRoutine
|
IN BOOLEAN CallUnlockRoutine
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
|
@ -632,17 +678,15 @@ FsRtlpUnlockSingle(
|
||||||
ASSERT(FileLock);
|
ASSERT(FileLock);
|
||||||
LockToc = FileLock->LockInformation;
|
LockToc = FileLock->LockInformation;
|
||||||
|
|
||||||
if (LockToc == NULL || Length->QuadPart == 0)
|
if (LockToc == NULL)
|
||||||
{
|
{
|
||||||
return STATUS_RANGE_NOT_LOCKED;
|
return STATUS_RANGE_NOT_LOCKED;
|
||||||
}
|
}
|
||||||
|
|
||||||
KeAcquireSpinLock(&LockToc->SpinLock, &oldirql );
|
KeAcquireSpinLock(&LockToc->SpinLock, &oldirql );
|
||||||
|
|
||||||
EnumEntry = LockToc->GrantedListHead.Flink;
|
LIST_FOR_EACH_SAFE(EnumEntry, &LockToc->GrantedListHead, Granted,FILE_LOCK_GRANTED,ListEntry)
|
||||||
while (EnumEntry != &LockToc->GrantedListHead)
|
|
||||||
{
|
{
|
||||||
Granted = CONTAINING_RECORD(EnumEntry,FILE_LOCK_GRANTED,ListEntry);
|
|
||||||
|
|
||||||
//must be exact match
|
//must be exact match
|
||||||
if (FileOffset->QuadPart == Granted->Lock.StartingByte.QuadPart &&
|
if (FileOffset->QuadPart == Granted->Lock.StartingByte.QuadPart &&
|
||||||
|
@ -652,12 +696,13 @@ FsRtlpUnlockSingle(
|
||||||
Granted->Lock.Key == Key)
|
Granted->Lock.Key == Key)
|
||||||
{
|
{
|
||||||
RemoveEntryList(&Granted->ListEntry);
|
RemoveEntryList(&Granted->ListEntry);
|
||||||
FsRtlpCompletePendingLocks(FileLock, LockToc, &oldirql);
|
FsRtlpCompletePendingLocks(FileLock, LockToc, &oldirql, Context);
|
||||||
|
|
||||||
if (IsListEmpty(&LockToc->GrantedListHead))
|
if (IsListEmpty(&LockToc->GrantedListHead))
|
||||||
{
|
{
|
||||||
KeReleaseSpinLock(&LockToc->SpinLock, oldirql);
|
KeReleaseSpinLock(&LockToc->SpinLock, oldirql);
|
||||||
FsRtlAreThereCurrentFileLocks(FileLock) = FALSE;
|
|
||||||
|
FsRtlAreThereCurrentFileLocks(FileLock) = FALSE; //paged data
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -666,14 +711,13 @@ FsRtlpUnlockSingle(
|
||||||
|
|
||||||
if (FileLock->UnlockRoutine && CallUnlockRoutine)
|
if (FileLock->UnlockRoutine && CallUnlockRoutine)
|
||||||
{
|
{
|
||||||
FileLock->UnlockRoutine(Context,&Granted->Lock);
|
FileLock->UnlockRoutine(Granted->UnlockContext, &Granted->Lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
ExFreeToNPagedLookasideList(&GrantedLookaside,Granted);
|
ExFreeToNPagedLookasideList(&GrantedLookaside, Granted);
|
||||||
|
|
||||||
return STATUS_SUCCESS;
|
return STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
EnumEntry = EnumEntry->Flink;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
KeReleaseSpinLock(&LockToc->SpinLock, oldirql);
|
KeReleaseSpinLock(&LockToc->SpinLock, oldirql);
|
||||||
|
@ -710,8 +754,7 @@ FsRtlFastUnlockSingle (
|
||||||
Process,
|
Process,
|
||||||
Key,
|
Key,
|
||||||
Context,
|
Context,
|
||||||
AlreadySynchronized,
|
TRUE /* call unlock copletion routine */
|
||||||
TRUE//CallUnlockRoutine
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -747,10 +790,9 @@ FsRtlpDumpFileLocks(
|
||||||
|
|
||||||
KeAcquireSpinLock(&LockToc->SpinLock, &oldirql);
|
KeAcquireSpinLock(&LockToc->SpinLock, &oldirql);
|
||||||
|
|
||||||
EnumEntry = LockToc->GrantedListHead.Blink;
|
LIST_FOR_EACH(EnumEntry, &LockToc->GrantedListHead)
|
||||||
while ( EnumEntry != &LockToc->GrantedListHead)
|
|
||||||
{
|
{
|
||||||
Granted = CONTAINING_RECORD(EnumEntry, 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: %i, len: %i, end: %i, key: %i, proc: 0x%X, fob: 0x%X\n",
|
||||||
Granted->Lock.ExclusiveLock ? "EXCL" : "SHRD",
|
Granted->Lock.ExclusiveLock ? "EXCL" : "SHRD",
|
||||||
|
@ -762,16 +804,13 @@ FsRtlpDumpFileLocks(
|
||||||
Granted->Lock.FileObject
|
Granted->Lock.FileObject
|
||||||
);
|
);
|
||||||
|
|
||||||
EnumEntry = EnumEntry->Blink;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
DPRINT1("Dumping pending file locks, FIFO order\n");
|
DPRINT1("Dumping pending file locks, FIFO order\n");
|
||||||
|
|
||||||
EnumEntry = LockToc->PendingListHead.Blink;
|
LIST_FOR_EACH(EnumEntry, &LockToc->PendingListHead)
|
||||||
while ( EnumEntry != &LockToc->PendingListHead)
|
|
||||||
{
|
{
|
||||||
Irp = CONTAINING_RECORD(EnumEntry, IRP , Tail.Overlay.ListEntry );
|
Irp = CONTAINING_RECORD(EnumEntry, IRP , Tail.Overlay.ListEntry);
|
||||||
|
|
||||||
Stack = IoGetCurrentIrpStackLocation(Irp);
|
Stack = IoGetCurrentIrpStackLocation(Irp);
|
||||||
|
|
||||||
DPRINT1("%s, start: %i, len: %i, end: %i, key: %i, proc: 0x%X, fob: 0x%X\n",
|
DPRINT1("%s, start: %i, len: %i, end: %i, key: %i, proc: 0x%X, fob: 0x%X\n",
|
||||||
|
@ -784,7 +823,6 @@ FsRtlpDumpFileLocks(
|
||||||
Stack->FileObject
|
Stack->FileObject
|
||||||
);
|
);
|
||||||
|
|
||||||
EnumEntry = EnumEntry->Blink;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
KeReleaseSpinLock(&LockToc->SpinLock, oldirql);
|
KeReleaseSpinLock(&LockToc->SpinLock, oldirql);
|
||||||
|
@ -939,7 +977,7 @@ FsRtlPrivateLock (
|
||||||
IN BOOLEAN ExclusiveLock,
|
IN BOOLEAN ExclusiveLock,
|
||||||
OUT PIO_STATUS_BLOCK IoStatus,
|
OUT PIO_STATUS_BLOCK IoStatus,
|
||||||
IN PIRP Irp OPTIONAL,
|
IN PIRP Irp OPTIONAL,
|
||||||
IN PVOID Context,
|
IN PVOID Context OPTIONAL,
|
||||||
IN BOOLEAN AlreadySynchronized
|
IN BOOLEAN AlreadySynchronized
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
|
@ -958,8 +996,6 @@ FsRtlPrivateLock (
|
||||||
KeInitializeSpinLock(&LockToc->SpinLock);
|
KeInitializeSpinLock(&LockToc->SpinLock);
|
||||||
InitializeListHead(&LockToc->GrantedListHead);
|
InitializeListHead(&LockToc->GrantedListHead);
|
||||||
InitializeListHead(&LockToc->PendingListHead);
|
InitializeListHead(&LockToc->PendingListHead);
|
||||||
InitializeListHead(&LockToc->CompletedListHead);
|
|
||||||
InitializeListHead(&LockToc->UnlockedListHead);
|
|
||||||
}
|
}
|
||||||
ExReleaseFastMutex(&LockTocMutex);
|
ExReleaseFastMutex(&LockTocMutex);
|
||||||
}
|
}
|
||||||
|
@ -974,43 +1010,36 @@ FsRtlPrivateLock (
|
||||||
Length,
|
Length,
|
||||||
Process,
|
Process,
|
||||||
Key,
|
Key,
|
||||||
ExclusiveLock
|
ExclusiveLock,
|
||||||
|
Context
|
||||||
) )
|
) )
|
||||||
{
|
{
|
||||||
IoStatus->Status = STATUS_SUCCESS;
|
IoStatus->Status = STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
else if (Irp && !FailImmediately)
|
else if (Irp && !FailImmediately)
|
||||||
{ //failed + irp + no fail = mk. pending
|
{
|
||||||
//for our cancel routine
|
//failed + irp + no fail = make. pending
|
||||||
Irp->Tail.Overlay.DriverContext[0] = (PVOID)FileLock;
|
|
||||||
Irp->Tail.Overlay.DriverContext[1] = (PVOID)LockToc;
|
Irp->Tail.Overlay.DriverContext[3] = &LockToc->SpinLock;
|
||||||
Irp->Tail.Overlay.DriverContext[2] = Context;
|
Irp->Tail.Overlay.DriverContext[2] = Context;
|
||||||
|
|
||||||
IoSetCancelRoutine(Irp, FsRtlpFileLockCancelRoutine);
|
IoSetCancelRoutine(Irp, FsRtlpFileLockCancelRoutine);
|
||||||
|
if (Irp->Cancel && IoSetCancelRoutine(Irp, NULL))
|
||||||
if (Irp->Cancel)
|
|
||||||
{
|
{
|
||||||
//irp canceled even before we got to queue it
|
//irp was canceled
|
||||||
if (IoSetCancelRoutine(Irp, NULL))
|
KeReleaseSpinLock(&LockToc->SpinLock, oldirql);
|
||||||
{ //Cancel routine will NOT be called: cancel it here
|
|
||||||
IoStatus->Status = STATUS_CANCELLED;
|
Irp->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;
|
Irp->IoStatus.Information = 0;
|
||||||
InitializeListHead(&Irp->Tail.Overlay.ListEntry);
|
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.Status = IoStatus->Status = STATUS_PENDING;
|
||||||
Irp->IoStatus.Information = 0;
|
Irp->IoStatus.Information = 0;
|
||||||
InsertHeadList(&LockToc->PendingListHead,&Irp->Tail.Overlay.ListEntry);
|
InsertHeadList(&LockToc->PendingListHead,&Irp->Tail.Overlay.ListEntry);
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -1034,11 +1063,9 @@ FsRtlPrivateLock (
|
||||||
{
|
{
|
||||||
Irp->IoStatus.Status = IoStatus->Status;
|
Irp->IoStatus.Status = IoStatus->Status;
|
||||||
Irp->IoStatus.Information = 0;
|
Irp->IoStatus.Information = 0;
|
||||||
|
|
||||||
if (FileLock->CompleteLockIrpRoutine)
|
if (FileLock->CompleteLockIrpRoutine)
|
||||||
{ //complete irp routine
|
{
|
||||||
|
if (FileLock->CompleteLockIrpRoutine(Context,Irp)!=STATUS_SUCCESS)
|
||||||
if (!NT_SUCCESS(FileLock->CompleteLockIrpRoutine(Context,Irp)))
|
|
||||||
{
|
{
|
||||||
//CompleteLockIrpRoutine complain: revert changes
|
//CompleteLockIrpRoutine complain: revert changes
|
||||||
FsRtlpUnlockSingle( FileLock,
|
FsRtlpUnlockSingle( FileLock,
|
||||||
|
@ -1047,15 +1074,14 @@ FsRtlPrivateLock (
|
||||||
Length,
|
Length,
|
||||||
Process,
|
Process,
|
||||||
Key,
|
Key,
|
||||||
Context,
|
NULL, /* context */
|
||||||
AlreadySynchronized,
|
FALSE /* don't call unlock copletion routine */
|
||||||
FALSE//CallUnlockRoutine
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{//std irp completion
|
{
|
||||||
IofCompleteRequest(Irp, IO_NO_INCREMENT);
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1123,7 +1149,7 @@ FsRtlProcessFileLock (
|
||||||
Status = FsRtlFastUnlockAll( FileLock,
|
Status = FsRtlFastUnlockAll( FileLock,
|
||||||
Stack->FileObject,
|
Stack->FileObject,
|
||||||
IoGetRequestorProcess(Irp),
|
IoGetRequestorProcess(Irp),
|
||||||
Context);
|
Context );
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case IRP_MN_UNLOCK_ALL_BY_KEY:
|
case IRP_MN_UNLOCK_ALL_BY_KEY:
|
||||||
|
@ -1131,26 +1157,21 @@ FsRtlProcessFileLock (
|
||||||
Stack->FileObject,
|
Stack->FileObject,
|
||||||
IoGetRequestorProcess(Irp),
|
IoGetRequestorProcess(Irp),
|
||||||
Stack->Parameters.LockControl.Key,
|
Stack->Parameters.LockControl.Key,
|
||||||
Context);
|
Context );
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
Irp->IoStatus.Status = Status = STATUS_INVALID_DEVICE_REQUEST;
|
Irp->IoStatus.Status = Status = STATUS_INVALID_DEVICE_REQUEST;
|
||||||
IofCompleteRequest(Irp, IO_NO_INCREMENT);
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
Irp->IoStatus.Status = Status;
|
|
||||||
|
|
||||||
if (FileLock->CompleteLockIrpRoutine )
|
Irp->IoStatus.Status = Status;
|
||||||
{
|
Irp->IoStatus.Information = 0;
|
||||||
FileLock->CompleteLockIrpRoutine(Context,Irp);
|
|
||||||
}
|
IoCompleteRequest(Irp,IO_NO_INCREMENT);
|
||||||
else
|
|
||||||
{
|
|
||||||
IofCompleteRequest(Irp,IO_NO_INCREMENT);
|
|
||||||
}
|
|
||||||
|
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
@ -1202,28 +1223,17 @@ FsRtlUninitializeFileLock (
|
||||||
{
|
{
|
||||||
//The cancel routine will be called. When we release the lock it will complete the irp.
|
//The cancel routine will be called. When we release the lock it will complete the irp.
|
||||||
InitializeListHead(&Irp->Tail.Overlay.ListEntry);
|
InitializeListHead(&Irp->Tail.Overlay.ListEntry);
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
KeReleaseSpinLock(&LockToc->SpinLock, oldirql);
|
||||||
/*
|
|
||||||
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;
|
Irp->IoStatus.Status = STATUS_RANGE_NOT_LOCKED;
|
||||||
|
Irp->IoStatus.Information = 0;
|
||||||
if (FileLock->CompleteLockIrpRoutine)
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||||
{
|
|
||||||
FileLock->CompleteLockIrpRoutine(Irp->Tail.Overlay.DriverContext[2], Irp);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
IofCompleteRequest(Irp, IO_NO_INCREMENT);
|
|
||||||
}
|
|
||||||
|
|
||||||
KeAcquireSpinLock(&LockToc->SpinLock, &oldirql);
|
KeAcquireSpinLock(&LockToc->SpinLock, &oldirql);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
KeReleaseSpinLock(&LockToc->SpinLock, oldirql);
|
KeReleaseSpinLock(&LockToc->SpinLock, oldirql);
|
||||||
|
@ -1311,4 +1321,5 @@ FsRtlReleaseFile(
|
||||||
UNIMPLEMENTED;
|
UNIMPLEMENTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* EOF */
|
/* EOF */
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
#ifndef __INCLUDE_INTERNAL_IFS_H
|
#ifndef __INCLUDE_INTERNAL_IFS_H
|
||||||
#define __INCLUDE_INTERNAL_IFS_H
|
#define __INCLUDE_INTERNAL_IFS_H
|
||||||
/* $Id: ifs.h,v 1.6 2003/08/14 18:30:28 silverblade Exp $ */
|
/* $Id: ifs.h,v 1.7 2004/12/30 02:30:40 gdalsnes Exp $ */
|
||||||
|
|
||||||
#include <ddk/ntifs.h>
|
#include <ddk/ntifs.h>
|
||||||
#include <ntos.h>
|
#include <ntos.h>
|
||||||
|
@ -38,7 +38,7 @@ FsRtlpFastUnlockAllByKey(
|
||||||
IN PVOID Context OPTIONAL
|
IN PVOID Context OPTIONAL
|
||||||
);
|
);
|
||||||
|
|
||||||
NTSTATUS FASTCALL
|
BOOLEAN FASTCALL
|
||||||
FsRtlpAddLock(
|
FsRtlpAddLock(
|
||||||
IN PFILE_LOCK_TOC LockToc,
|
IN PFILE_LOCK_TOC LockToc,
|
||||||
IN PFILE_OBJECT FileObject,
|
IN PFILE_OBJECT FileObject,
|
||||||
|
@ -46,14 +46,16 @@ FsRtlpAddLock(
|
||||||
IN PLARGE_INTEGER Length,
|
IN PLARGE_INTEGER Length,
|
||||||
IN PEPROCESS Process,
|
IN PEPROCESS Process,
|
||||||
IN ULONG Key,
|
IN ULONG Key,
|
||||||
IN BOOLEAN ExclusiveLock
|
IN BOOLEAN ExclusiveLock,
|
||||||
|
IN PVOID UnlockContext
|
||||||
);
|
);
|
||||||
|
|
||||||
VOID FASTCALL
|
VOID FASTCALL
|
||||||
FsRtlpCompletePendingLocks(
|
FsRtlpCompletePendingLocks(
|
||||||
IN PFILE_LOCK FileLock,
|
IN PFILE_LOCK FileLock,
|
||||||
IN PFILE_LOCK_TOC LockToc,
|
IN PFILE_LOCK_TOC LockToc,
|
||||||
IN OUT PKIRQL oldirql
|
IN OUT PKIRQL oldirql,
|
||||||
|
IN PVOID Context
|
||||||
);
|
);
|
||||||
|
|
||||||
NTSTATUS FASTCALL
|
NTSTATUS FASTCALL
|
||||||
|
@ -65,7 +67,6 @@ FsRtlpUnlockSingle(
|
||||||
IN PEPROCESS Process,
|
IN PEPROCESS Process,
|
||||||
IN ULONG Key,
|
IN ULONG Key,
|
||||||
IN PVOID Context OPTIONAL,
|
IN PVOID Context OPTIONAL,
|
||||||
IN BOOLEAN AlreadySynchronized,
|
|
||||||
IN BOOLEAN CallUnlockRoutine
|
IN BOOLEAN CallUnlockRoutine
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue