mirror of
https://github.com/reactos/reactos.git
synced 2025-08-04 20:56:04 +00:00
-Added some file locking improvements. (Thanks to Gunnar Andr� Dalsnes)
svn path=/trunk/; revision=4064
This commit is contained in:
parent
1fb967f911
commit
ca34b94db6
2 changed files with 877 additions and 810 deletions
|
@ -1,4 +1,4 @@
|
|||
/* $Id: filelock.c,v 1.6 2002/11/13 06:01:11 robd Exp $
|
||||
/* $Id: filelock.c,v 1.7 2003/01/25 15:52:43 hbirr Exp $
|
||||
*
|
||||
* reactos/ntoskrnl/fs/filelock.c
|
||||
*
|
||||
|
@ -10,14 +10,11 @@
|
|||
#define NDEBUG
|
||||
#include <internal/debug.h>
|
||||
|
||||
//#define TAG_LOCK TAG('F','l','c','k')
|
||||
|
||||
/*
|
||||
NOTE:
|
||||
I'm not using resource syncronization here, since
|
||||
FsRtlFastCheckLockForRead/FsRtlFastCheckLockForWrite
|
||||
can be running at any IRQL. Therefore I also have used
|
||||
nonpaged memory for the lists.
|
||||
I'm not using resource syncronization here, since FsRtlFastCheckLockForRead/Write
|
||||
are allowed to be called at DISPATCH_LEVEL. Must therefore use nonpaged memory for
|
||||
the lists.
|
||||
*/
|
||||
|
||||
#define LOCK_START_OFF(Lock) ((Lock).StartingByte.QuadPart)
|
||||
|
@ -26,9 +23,9 @@ nonpaged memory for the lists.
|
|||
#define REQUEST_END_OFF ((FileOffset->QuadPart) + (Length->QuadPart) - 1)
|
||||
|
||||
FAST_MUTEX LockTocMutex;
|
||||
NPAGED_LOOKASIDE_LIST PendingLookaside;
|
||||
NPAGED_LOOKASIDE_LIST GrantedLookaside;
|
||||
NPAGED_LOOKASIDE_LIST LockTocLookaside;
|
||||
PAGED_LOOKASIDE_LIST LockLookaside;
|
||||
|
||||
/**********************************************************************
|
||||
* NAME PRIVATE
|
||||
|
@ -57,11 +54,11 @@ FsRtlpInitFileLockingImplementation(VOID)
|
|||
0
|
||||
);
|
||||
|
||||
ExInitializeNPagedLookasideList( &PendingLookaside,
|
||||
ExInitializePagedLookasideList( &LockLookaside,
|
||||
NULL,
|
||||
NULL,
|
||||
0,
|
||||
sizeof(FILE_LOCK_PENDING),
|
||||
sizeof(FILE_LOCK),
|
||||
IFS_POOL_TAG,
|
||||
0
|
||||
);
|
||||
|
@ -69,74 +66,52 @@ FsRtlpInitFileLockingImplementation(VOID)
|
|||
ExInitializeFastMutex(&LockTocMutex);
|
||||
}
|
||||
|
||||
|
||||
/**********************************************************************
|
||||
* NAME PRIVATE
|
||||
* FsRtlpPendingFileLockCancelRoutine
|
||||
* FsRtlpFileLockCancelRoutine
|
||||
*
|
||||
*/
|
||||
VOID
|
||||
STDCALL
|
||||
FsRtlpPendingFileLockCancelRoutine(
|
||||
FsRtlpFileLockCancelRoutine(
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PIRP Irp
|
||||
)
|
||||
{
|
||||
KIRQL oldIrql;
|
||||
PFILE_LOCK FileLock;
|
||||
PFILE_LOCK_TOC LockToc;
|
||||
PFILE_LOCK_PENDING Pending;
|
||||
PLIST_ENTRY EnumEntry;
|
||||
PKSPIN_LOCK SpinLock;
|
||||
PCOMPLETE_LOCK_IRP_ROUTINE CompleteLockIrpRoutine;
|
||||
|
||||
IoReleaseCancelSpinLock(Irp->CancelIrql); //don't need this for private queue cancelation
|
||||
//don't need this since we have our own sync. protecting irp cancellation
|
||||
IoReleaseCancelSpinLock(Irp->CancelIrql);
|
||||
|
||||
FileLock = (PVOID)Irp->IoStatus.Information;
|
||||
assert(FileLock);
|
||||
LockToc = FileLock->LockInformation;
|
||||
if (LockToc == NULL)
|
||||
return;
|
||||
SpinLock = &((PFILE_LOCK_TOC)Irp->Tail.Overlay.DriverContext[1])->SpinLock;
|
||||
|
||||
KeAcquireSpinLock(&LockToc->SpinLock, &oldIrql);
|
||||
KeAcquireSpinLock(SpinLock, &oldIrql);
|
||||
RemoveEntryList(&Irp->Tail.Overlay.ListEntry);
|
||||
KeReleaseSpinLock(SpinLock, oldIrql);
|
||||
|
||||
EnumEntry = LockToc->PendingListHead.Flink;
|
||||
while (EnumEntry != &LockToc->PendingListHead) {
|
||||
Pending = CONTAINING_RECORD(EnumEntry, FILE_LOCK_PENDING , ListEntry );
|
||||
|
||||
if (Pending->Irp == Irp){
|
||||
RemoveEntryList(&Pending->ListEntry);
|
||||
KeReleaseSpinLock(&LockToc->SpinLock, oldIrql);
|
||||
Irp->IoStatus.Status = STATUS_CANCELLED;
|
||||
|
||||
if (FileLock->CompleteLockIrpRoutine )
|
||||
FileLock->CompleteLockIrpRoutine(Pending->Context,Irp);
|
||||
CompleteLockIrpRoutine = ((PFILE_LOCK)Irp->Tail.Overlay.DriverContext[0])->CompleteLockIrpRoutine;
|
||||
if (CompleteLockIrpRoutine)
|
||||
{
|
||||
CompleteLockIrpRoutine(Irp->Tail.Overlay.DriverContext[2], Irp);
|
||||
}
|
||||
else
|
||||
{
|
||||
IofCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
|
||||
ExFreeToNPagedLookasideList(&PendingLookaside,Pending);
|
||||
return;
|
||||
}
|
||||
EnumEntry = EnumEntry->Flink;
|
||||
}
|
||||
|
||||
/*
|
||||
didn't find irp in list, so someone else must have completed it
|
||||
while we were waiting for the spinlock
|
||||
*/
|
||||
KeReleaseSpinLock(&LockToc->SpinLock, oldIrql);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**********************************************************************
|
||||
* NAME PRIVATE
|
||||
* FsRtlpCheckLockForReadOrWriteAccess
|
||||
*
|
||||
*/
|
||||
BOOLEAN
|
||||
STDCALL
|
||||
FASTCALL
|
||||
FsRtlpCheckLockForReadOrWriteAccess(
|
||||
IN PFILE_LOCK FileLock,
|
||||
IN PLARGE_INTEGER FileOffset,
|
||||
|
@ -155,46 +130,50 @@ FsRtlpCheckLockForReadOrWriteAccess(
|
|||
assert(FileLock);
|
||||
LockToc = FileLock->LockInformation;
|
||||
|
||||
if (LockToc == NULL || Length->QuadPart == 0) {
|
||||
if (LockToc == NULL || Length->QuadPart == 0)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
KeAcquireSpinLock(&LockToc->SpinLock, &oldirql);
|
||||
|
||||
EnumEntry = LockToc->GrantedListHead.Flink;
|
||||
while ( EnumEntry != &LockToc->GrantedListHead){
|
||||
|
||||
while ( EnumEntry != &LockToc->GrantedListHead)
|
||||
{
|
||||
Granted = CONTAINING_RECORD(EnumEntry, FILE_LOCK_GRANTED , ListEntry );
|
||||
//if overlapping
|
||||
if(!(REQUEST_START_OFF > LOCK_END_OFF(Granted->Lock) ||
|
||||
REQUEST_END_OFF < LOCK_START_OFF(Granted->Lock))) {
|
||||
|
||||
REQUEST_END_OFF < LOCK_START_OFF(Granted->Lock)))
|
||||
{
|
||||
//No read conflict if (shared lock) OR (exclusive + our lock)
|
||||
//No write conflict if exclusive lock AND our lock
|
||||
if ((Read && !Granted->Lock.ExclusiveLock) ||
|
||||
(Granted->Lock.ExclusiveLock &&
|
||||
Granted->Lock.Process == Process &&
|
||||
Granted->Lock.FileObject == FileObject &&
|
||||
Granted->Lock.Key == Key ) ) {
|
||||
|
||||
//AND if lock surround read region, stop searching and grant
|
||||
Granted->Lock.Key == Key ) )
|
||||
{
|
||||
//AND if lock surround request region, stop searching and grant
|
||||
if (REQUEST_START_OFF >= LOCK_START_OFF(Granted->Lock) &&
|
||||
REQUEST_END_OFF <= LOCK_END_OFF(Granted->Lock)){
|
||||
|
||||
EnumEntry = &LockToc->GrantedListHead;//success
|
||||
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);
|
||||
|
||||
if (EnumEntry == &LockToc->GrantedListHead) { //no conflict
|
||||
if (EnumEntry == &LockToc->GrantedListHead)
|
||||
{ //no conflict
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
@ -328,7 +307,7 @@ FsRtlFastCheckLockForWrite (
|
|||
*
|
||||
*/
|
||||
NTSTATUS
|
||||
STDCALL
|
||||
FASTCALL
|
||||
FsRtlpFastUnlockAllByKey(
|
||||
IN PFILE_LOCK FileLock,
|
||||
IN PFILE_OBJECT FileObject,
|
||||
|
@ -344,56 +323,76 @@ FsRtlpFastUnlockAllByKey(
|
|||
PFILE_LOCK_GRANTED Granted;
|
||||
BOOLEAN Unlock = FALSE;
|
||||
//must make local copy since FILE_LOCK struct is allowed to be paged
|
||||
BOOLEAN GotUnlockRoutine;
|
||||
PUNLOCK_ROUTINE GotUnlockRoutine;
|
||||
|
||||
assert(FileLock);
|
||||
LockToc = FileLock->LockInformation;
|
||||
|
||||
if (LockToc == NULL)
|
||||
{
|
||||
return STATUS_RANGE_NOT_LOCKED;
|
||||
}
|
||||
|
||||
GotUnlockRoutine = FileLock->UnlockRoutine ? TRUE : FALSE;
|
||||
GotUnlockRoutine = FileLock->UnlockRoutine;
|
||||
KeAcquireSpinLock(&LockToc->SpinLock, &oldirql);
|
||||
|
||||
EnumEntry = LockToc->GrantedListHead.Flink;
|
||||
while ( EnumEntry != &LockToc->GrantedListHead ) {
|
||||
|
||||
while (EnumEntry != &LockToc->GrantedListHead )
|
||||
{
|
||||
Granted = CONTAINING_RECORD(EnumEntry,FILE_LOCK_GRANTED, ListEntry);
|
||||
EnumEntry = EnumEntry->Flink;
|
||||
|
||||
if (Granted->Lock.Process == Process &&
|
||||
Granted->Lock.FileObject == FileObject &&
|
||||
(!UseKey || (UseKey && Granted->Lock.Key == Key)) ){
|
||||
|
||||
(!UseKey || (UseKey && Granted->Lock.Key == Key)) )
|
||||
{
|
||||
RemoveEntryList(&Granted->ListEntry);
|
||||
Unlock = TRUE;
|
||||
|
||||
if (GotUnlockRoutine) {
|
||||
if (GotUnlockRoutine)
|
||||
{
|
||||
/*
|
||||
Put on unlocked list and call unlock routine for them afterwards.
|
||||
This way we don't have to restart enum after each call
|
||||
*/
|
||||
InsertHeadList(&LockToc->UnlockedListHead,&Granted->ListEntry);
|
||||
}
|
||||
else
|
||||
{
|
||||
ExFreeToNPagedLookasideList(&GrantedLookaside,Granted);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (Unlock)
|
||||
{
|
||||
//call unlock routine for each unlocked lock (if any)
|
||||
while (!IsListEmpty(&LockToc->UnlockedListHead))
|
||||
{
|
||||
EnumEntry = RemoveTailList(&LockToc->UnlockedListHead);
|
||||
Granted = CONTAINING_RECORD(EnumEntry,FILE_LOCK_GRANTED, ListEntry);
|
||||
KeReleaseSpinLock(&LockToc->SpinLock, oldirql);
|
||||
FileLock->UnlockRoutine(Context,&Granted->Lock);
|
||||
ExFreeToNPagedLookasideList(&GrantedLookaside,Granted);
|
||||
KeAcquireSpinLock(&LockToc->SpinLock, &oldirql);
|
||||
EnumEntry = LockToc->GrantedListHead.Flink; //restart
|
||||
continue;
|
||||
}
|
||||
|
||||
ExFreeToNPagedLookasideList(&GrantedLookaside,Granted);
|
||||
}
|
||||
}
|
||||
//NOTE: holding spinlock while calling this
|
||||
FsRtlpCompletePendingLocks(FileLock, LockToc, &oldirql);
|
||||
|
||||
if (Unlock){
|
||||
FsRtlpTryCompletePendingLocks(FileLock,LockToc,NULL);
|
||||
}
|
||||
|
||||
KeReleaseSpinLock(&LockToc->SpinLock, oldirql);
|
||||
|
||||
if (Unlock) {
|
||||
if (IsListEmpty(&LockToc->GrantedListHead))
|
||||
{
|
||||
KeReleaseSpinLock(&LockToc->SpinLock, oldirql);
|
||||
FsRtlAreThereCurrentFileLocks(FileLock) = FALSE;
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
KeReleaseSpinLock(&LockToc->SpinLock, oldirql);
|
||||
}
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
KeReleaseSpinLock(&LockToc->SpinLock, oldirql);
|
||||
return STATUS_RANGE_NOT_LOCKED;
|
||||
}
|
||||
|
||||
|
@ -453,7 +452,7 @@ FsRtlFastUnlockAllByKey (
|
|||
* Spinlock held at entry !!
|
||||
*/
|
||||
NTSTATUS
|
||||
STDCALL
|
||||
FASTCALL
|
||||
FsRtlpAddLock(
|
||||
IN PFILE_LOCK_TOC LockToc,
|
||||
IN PFILE_OBJECT FileObject,
|
||||
|
@ -468,35 +467,35 @@ FsRtlpAddLock(
|
|||
PFILE_LOCK_GRANTED Granted;
|
||||
|
||||
EnumEntry = LockToc->GrantedListHead.Flink;
|
||||
while (EnumEntry != &LockToc->GrantedListHead) {
|
||||
|
||||
while (EnumEntry != &LockToc->GrantedListHead)
|
||||
{
|
||||
Granted = CONTAINING_RECORD(EnumEntry,FILE_LOCK_GRANTED, ListEntry);
|
||||
//if overlapping
|
||||
if(!(REQUEST_START_OFF > LOCK_END_OFF(Granted->Lock) ||
|
||||
REQUEST_END_OFF < LOCK_START_OFF(Granted->Lock))) {
|
||||
|
||||
REQUEST_END_OFF < LOCK_START_OFF(Granted->Lock)))
|
||||
{
|
||||
//never conflict if shared lock and we want to add a shared lock
|
||||
if (!Granted->Lock.ExclusiveLock &&
|
||||
!ExclusiveLock) {
|
||||
|
||||
if (!Granted->Lock.ExclusiveLock && !ExclusiveLock)
|
||||
{
|
||||
//AND if lock surround region, stop searching and insert lock
|
||||
if (REQUEST_START_OFF >= LOCK_START_OFF(Granted->Lock) &&
|
||||
REQUEST_END_OFF <= LOCK_END_OFF(Granted->Lock)){
|
||||
|
||||
REQUEST_END_OFF <= LOCK_END_OFF(Granted->Lock))
|
||||
{
|
||||
EnumEntry = &LockToc->GrantedListHead;
|
||||
break;
|
||||
}
|
||||
//else keep locking for conflicts
|
||||
}
|
||||
else //conflict if we want share access to excl. lock OR exlc. access to shared lock
|
||||
else
|
||||
{//conflict if we want share access to excl. lock OR exlc. access to shared lock
|
||||
break;//FAIL
|
||||
}
|
||||
|
||||
}
|
||||
EnumEntry = EnumEntry->Flink;
|
||||
}
|
||||
|
||||
if (EnumEntry == &LockToc->GrantedListHead) {//no conflict
|
||||
|
||||
if (EnumEntry == &LockToc->GrantedListHead)
|
||||
{//no conflict
|
||||
Granted = ExAllocateFromNPagedLookasideList(&GrantedLookaside);
|
||||
|
||||
Granted->Lock.StartingByte = *FileOffset;
|
||||
|
@ -519,14 +518,14 @@ FsRtlpAddLock(
|
|||
|
||||
/**********************************************************************
|
||||
* NAME PRIVATE
|
||||
* FsRtlpTryCompletePendingLocks
|
||||
* FsRtlpCompletePendingLocks
|
||||
*
|
||||
* NOTE
|
||||
* Spinlock held at entry !!
|
||||
*/
|
||||
VOID
|
||||
STDCALL
|
||||
FsRtlpTryCompletePendingLocks(
|
||||
FASTCALL
|
||||
FsRtlpCompletePendingLocks(
|
||||
IN PFILE_LOCK FileLock,
|
||||
IN PFILE_LOCK_TOC LockToc,
|
||||
IN OUT PKIRQL oldirql
|
||||
|
@ -534,49 +533,70 @@ FsRtlpTryCompletePendingLocks(
|
|||
{
|
||||
//walk pending list, FIFO order, try 2 complete locks
|
||||
PLIST_ENTRY EnumEntry;
|
||||
PFILE_LOCK_PENDING Pending;
|
||||
PIRP Irp;
|
||||
PIO_STACK_LOCATION Stack;
|
||||
|
||||
EnumEntry = LockToc->PendingListHead.Blink;
|
||||
while (EnumEntry != &LockToc->PendingListHead) {
|
||||
|
||||
Pending = CONTAINING_RECORD(EnumEntry, FILE_LOCK_PENDING,ListEntry);
|
||||
|
||||
Stack = IoGetCurrentIrpStackLocation(Pending->Irp);
|
||||
while (EnumEntry != &LockToc->PendingListHead)
|
||||
{
|
||||
Irp = CONTAINING_RECORD(EnumEntry,IRP, Tail.Overlay.ListEntry);
|
||||
|
||||
Stack = IoGetCurrentIrpStackLocation(Irp);
|
||||
if (FsRtlpAddLock(LockToc,
|
||||
Stack->FileObject,//correct?
|
||||
Stack->FileObject,
|
||||
&Stack->Parameters.LockControl.ByteOffset,
|
||||
Stack->Parameters.LockControl.Length,
|
||||
IoGetRequestorProcess(Pending->Irp),
|
||||
IoGetRequestorProcess(Irp),
|
||||
Stack->Parameters.LockControl.Key,
|
||||
Stack->Flags & SL_EXCLUSIVE_LOCK
|
||||
) ) {
|
||||
) )
|
||||
{
|
||||
RemoveEntryList(&Irp->Tail.Overlay.ListEntry);
|
||||
|
||||
RemoveEntryList(&Pending->ListEntry);
|
||||
|
||||
IoSetCancelRoutine(Pending->Irp, NULL);
|
||||
if (!IoSetCancelRoutine(Irp, NULL))
|
||||
{
|
||||
/*
|
||||
Irp could be cancelled and the cancel routine may or may not have been called,
|
||||
waiting there for our spinlock.
|
||||
But it doesn't matter because it will not find the IRP in the list.
|
||||
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.
|
||||
*/
|
||||
KeReleaseSpinLock(&LockToc->SpinLock, *oldirql);//fires cancel routine
|
||||
Pending->Irp->IoStatus.Status = STATUS_SUCCESS;
|
||||
|
||||
if (FileLock->CompleteLockIrpRoutine)
|
||||
FileLock->CompleteLockIrpRoutine(Pending->Context,Pending->Irp);
|
||||
InitializeListHead(&Irp->Tail.Overlay.ListEntry);
|
||||
}
|
||||
else
|
||||
IofCompleteRequest(Pending->Irp, IO_NO_INCREMENT);
|
||||
{
|
||||
/*
|
||||
Cancel routine will NOT be called, canceled or not.
|
||||
|
||||
ExFreeToNPagedLookasideList(&PendingLookaside,Pending);
|
||||
KeAcquireSpinLock(&LockToc->SpinLock, oldirql);
|
||||
//restart, something migth have happend to our list
|
||||
EnumEntry = LockToc->PendingListHead.Blink;
|
||||
continue;
|
||||
Put on completed list and complete them all afterwards.
|
||||
This way we don't have to restart enum after each completion.
|
||||
*/
|
||||
Irp->IoStatus.Status = STATUS_SUCCESS;
|
||||
Irp->IoStatus.Information = 0;
|
||||
InsertHeadList(&LockToc->CompletedListHead,&Irp->Tail.Overlay.ListEntry);
|
||||
}
|
||||
}
|
||||
EnumEntry = EnumEntry->Blink;
|
||||
}
|
||||
|
||||
//complete irp's (if any)
|
||||
while (!IsListEmpty(&LockToc->CompletedListHead))
|
||||
{
|
||||
EnumEntry = RemoveTailList(&LockToc->CompletedListHead);
|
||||
KeReleaseSpinLock(&LockToc->SpinLock, *oldirql);//fires cancel routine
|
||||
Irp = CONTAINING_RECORD(EnumEntry, IRP, Tail.Overlay.ListEntry);
|
||||
|
||||
if (FileLock->CompleteLockIrpRoutine)
|
||||
{
|
||||
FileLock->CompleteLockIrpRoutine(Irp->Tail.Overlay.DriverContext[2], Irp);
|
||||
}
|
||||
else
|
||||
{
|
||||
IofCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
}
|
||||
|
||||
KeAcquireSpinLock(&LockToc->SpinLock, oldirql);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
@ -587,7 +607,7 @@ FsRtlpTryCompletePendingLocks(
|
|||
*
|
||||
*/
|
||||
NTSTATUS
|
||||
STDCALL
|
||||
FASTCALL
|
||||
FsRtlpUnlockSingle(
|
||||
IN PFILE_LOCK FileLock,
|
||||
IN PFILE_OBJECT FileObject,
|
||||
|
@ -608,14 +628,16 @@ FsRtlpUnlockSingle(
|
|||
assert(FileLock);
|
||||
LockToc = FileLock->LockInformation;
|
||||
|
||||
if (LockToc == NULL)
|
||||
if (LockToc == NULL || Length->QuadPart == 0)
|
||||
{
|
||||
return STATUS_RANGE_NOT_LOCKED;
|
||||
}
|
||||
|
||||
KeAcquireSpinLock(&LockToc->SpinLock, &oldirql );
|
||||
|
||||
EnumEntry = LockToc->GrantedListHead.Flink;
|
||||
while (EnumEntry != &LockToc->GrantedListHead) {
|
||||
|
||||
while (EnumEntry != &LockToc->GrantedListHead)
|
||||
{
|
||||
Granted = CONTAINING_RECORD(EnumEntry,FILE_LOCK_GRANTED,ListEntry);
|
||||
|
||||
//must be exact match
|
||||
|
@ -623,24 +645,29 @@ FsRtlpUnlockSingle(
|
|||
Length->QuadPart == Granted->Lock.Length.QuadPart &&
|
||||
Granted->Lock.Process == Process &&
|
||||
Granted->Lock.FileObject == FileObject &&
|
||||
Granted->Lock.Key == Key) {
|
||||
|
||||
Granted->Lock.Key == Key)
|
||||
{
|
||||
RemoveEntryList(&Granted->ListEntry);
|
||||
FsRtlpCompletePendingLocks(FileLock, LockToc, &oldirql);
|
||||
|
||||
FsRtlpTryCompletePendingLocks(FileLock, LockToc,NULL);
|
||||
|
||||
if (IsListEmpty(&LockToc->GrantedListHead))
|
||||
{
|
||||
KeReleaseSpinLock(&LockToc->SpinLock, oldirql);
|
||||
FsRtlAreThereCurrentFileLocks(FileLock) = FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
KeReleaseSpinLock(&LockToc->SpinLock, oldirql);
|
||||
}
|
||||
|
||||
if (FileLock->UnlockRoutine && CallUnlockRoutine)
|
||||
{
|
||||
FileLock->UnlockRoutine(Context,&Granted->Lock);
|
||||
}
|
||||
|
||||
ExFreeToNPagedLookasideList(&GrantedLookaside,Granted);
|
||||
|
||||
if (IsListEmpty(&LockToc->GrantedListHead))
|
||||
FsRtlAreThereCurrentFileLocks(FileLock) = FALSE;
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
|
||||
}
|
||||
EnumEntry = EnumEntry->Flink;
|
||||
}
|
||||
|
@ -687,25 +714,26 @@ FsRtlFastUnlockSingle (
|
|||
* NAME EXPORTED
|
||||
* FsRtlpDumpFileLocks
|
||||
*
|
||||
* NOTE: used for testing and debugging
|
||||
*/
|
||||
VOID
|
||||
STDCALL
|
||||
FASTCALL
|
||||
FsRtlpDumpFileLocks(
|
||||
IN PFILE_LOCK FileLock
|
||||
)
|
||||
{
|
||||
//100% OK
|
||||
KIRQL oldirql;
|
||||
PFILE_LOCK_TOC LockToc;
|
||||
PFILE_LOCK_GRANTED Granted;
|
||||
PFILE_LOCK_PENDING Pending;
|
||||
PIRP Irp;
|
||||
PLIST_ENTRY EnumEntry;
|
||||
PIO_STACK_LOCATION Stack;
|
||||
|
||||
assert(FileLock);
|
||||
LockToc = FileLock->LockInformation;
|
||||
|
||||
if (LockToc == NULL) {
|
||||
if (LockToc == NULL)
|
||||
{
|
||||
DPRINT1("No file locks\n");
|
||||
return;
|
||||
}
|
||||
|
@ -715,8 +743,8 @@ FsRtlpDumpFileLocks(
|
|||
KeAcquireSpinLock(&LockToc->SpinLock, &oldirql);
|
||||
|
||||
EnumEntry = LockToc->GrantedListHead.Blink;
|
||||
while ( EnumEntry != &LockToc->GrantedListHead){
|
||||
|
||||
while ( EnumEntry != &LockToc->GrantedListHead)
|
||||
{
|
||||
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",
|
||||
|
@ -735,11 +763,11 @@ FsRtlpDumpFileLocks(
|
|||
DPRINT1("Dumping pending file locks, FIFO order\n");
|
||||
|
||||
EnumEntry = LockToc->PendingListHead.Blink;
|
||||
while ( EnumEntry != &LockToc->PendingListHead){
|
||||
while ( EnumEntry != &LockToc->PendingListHead)
|
||||
{
|
||||
Irp = CONTAINING_RECORD(EnumEntry, IRP , Tail.Overlay.ListEntry );
|
||||
|
||||
Pending = CONTAINING_RECORD(EnumEntry, FILE_LOCK_PENDING , ListEntry );
|
||||
|
||||
Stack = IoGetCurrentIrpStackLocation(Pending->Irp);
|
||||
Stack = IoGetCurrentIrpStackLocation(Irp);
|
||||
|
||||
DPRINT1("%s, start: %i, len: %i, end: %i, key: %i, proc: 0x%X, fob: 0x%X\n",
|
||||
(Stack->Flags & SL_EXCLUSIVE_LOCK) ? "EXCL" : "SHRD",
|
||||
|
@ -747,7 +775,7 @@ FsRtlpDumpFileLocks(
|
|||
Stack->Parameters.LockControl.Length->QuadPart,
|
||||
Stack->Parameters.LockControl.ByteOffset.QuadPart + Stack->Parameters.LockControl.Length->QuadPart - 1,
|
||||
Stack->Parameters.LockControl.Key,
|
||||
IoGetRequestorProcess(Pending->Irp),
|
||||
IoGetRequestorProcess(Irp),
|
||||
Stack->FileObject
|
||||
);
|
||||
|
||||
|
@ -776,7 +804,7 @@ FsRtlGetNextFileLock (
|
|||
{
|
||||
/*
|
||||
Messy enumeration of granted locks.
|
||||
What our last ptr. in LastReturnedLock points at, might have been free between
|
||||
What our last ptr. in LastReturnedLock points at, might have been freed between
|
||||
calls, so we have to scan thru the list every time, searching for our last lock.
|
||||
If it's not there anymore, restart the enumeration...
|
||||
*/
|
||||
|
@ -792,7 +820,9 @@ FsRtlGetNextFileLock (
|
|||
assert(FileLock);
|
||||
LockToc = FileLock->LockInformation;
|
||||
if (LockToc == NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
LocalLastReturnedLock = FileLock->LastReturnedLock;
|
||||
|
||||
|
@ -802,8 +832,10 @@ restart:;
|
|||
|
||||
EnumEntry = LockToc->GrantedListHead.Flink;
|
||||
|
||||
if (Restart){
|
||||
if (EnumEntry != &LockToc->GrantedListHead){
|
||||
if (Restart)
|
||||
{
|
||||
if (EnumEntry != &LockToc->GrantedListHead)
|
||||
{
|
||||
Granted = CONTAINING_RECORD(EnumEntry,FILE_LOCK_GRANTED,ListEntry);
|
||||
LocalLastReturnedLockInfo = Granted->Lock;
|
||||
KeReleaseSpinLock(&LockToc->SpinLock,oldirql);
|
||||
|
@ -812,21 +844,24 @@ restart:;
|
|||
FileLock->LastReturnedLock = EnumEntry;
|
||||
return &FileLock->LastReturnedLockInfo;
|
||||
}
|
||||
else {
|
||||
else
|
||||
{
|
||||
KeReleaseSpinLock(&LockToc->SpinLock,oldirql);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
//else: continue enum
|
||||
while (EnumEntry != &LockToc->GrantedListHead) {
|
||||
|
||||
while (EnumEntry != &LockToc->GrantedListHead)
|
||||
{
|
||||
//found previous lock?
|
||||
if (EnumEntry == LocalLastReturnedLock) {
|
||||
if (EnumEntry == LocalLastReturnedLock)
|
||||
{
|
||||
FoundPrevious = TRUE;
|
||||
//get next
|
||||
EnumEntry = EnumEntry->Flink;
|
||||
if (EnumEntry != &LockToc->GrantedListHead){
|
||||
if (EnumEntry != &LockToc->GrantedListHead)
|
||||
{
|
||||
Granted = CONTAINING_RECORD(EnumEntry,FILE_LOCK_GRANTED,ListEntry);
|
||||
LocalLastReturnedLockInfo = Granted->Lock;
|
||||
KeReleaseSpinLock(&LockToc->SpinLock,oldirql);
|
||||
|
@ -840,7 +875,8 @@ restart:;
|
|||
EnumEntry = EnumEntry->Flink;
|
||||
}
|
||||
|
||||
if (!FoundPrevious) {
|
||||
if (!FoundPrevious)
|
||||
{
|
||||
//got here? uh no, didn't find our last lock..must have been freed...restart
|
||||
Restart = TRUE;
|
||||
goto restart;
|
||||
|
@ -891,7 +927,7 @@ FsRtlPrivateLock (
|
|||
IN PLARGE_INTEGER Length,
|
||||
IN PEPROCESS Process,
|
||||
IN ULONG Key,
|
||||
IN BOOLEAN FailImmediately, //meaningless for fast io
|
||||
IN BOOLEAN FailImmediately, //seems meaningless for fast io
|
||||
IN BOOLEAN ExclusiveLock,
|
||||
OUT PIO_STATUS_BLOCK IoStatus,
|
||||
IN PIRP Irp OPTIONAL,
|
||||
|
@ -901,18 +937,21 @@ FsRtlPrivateLock (
|
|||
{
|
||||
PFILE_LOCK_TOC LockToc;
|
||||
KIRQL oldirql;
|
||||
PFILE_LOCK_PENDING Pending;
|
||||
|
||||
assert(FileLock);
|
||||
if (FileLock->LockInformation == NULL) {
|
||||
if (FileLock->LockInformation == NULL)
|
||||
{
|
||||
ExAcquireFastMutex(&LockTocMutex);
|
||||
//still NULL?
|
||||
if (FileLock->LockInformation == NULL){
|
||||
if (FileLock->LockInformation == NULL)
|
||||
{
|
||||
FileLock->LockInformation = ExAllocateFromNPagedLookasideList(&LockTocLookaside);
|
||||
LockToc = FileLock->LockInformation;
|
||||
KeInitializeSpinLock(&LockToc->SpinLock);
|
||||
InitializeListHead(&LockToc->PendingListHead);
|
||||
InitializeListHead(&LockToc->GrantedListHead);
|
||||
InitializeListHead(&LockToc->PendingListHead);
|
||||
InitializeListHead(&LockToc->CompletedListHead);
|
||||
InitializeListHead(&LockToc->UnlockedListHead);
|
||||
}
|
||||
ExReleaseFastMutex(&LockTocMutex);
|
||||
}
|
||||
|
@ -920,7 +959,7 @@ FsRtlPrivateLock (
|
|||
LockToc = FileLock->LockInformation;
|
||||
KeAcquireSpinLock(&LockToc->SpinLock, &oldirql);
|
||||
|
||||
//try add new lock
|
||||
//try add new lock (while holding spin lock)
|
||||
if (FsRtlpAddLock(LockToc,
|
||||
FileObject,
|
||||
FileOffset,
|
||||
|
@ -928,52 +967,71 @@ FsRtlPrivateLock (
|
|||
Process,
|
||||
Key,
|
||||
ExclusiveLock
|
||||
) ) {
|
||||
|
||||
) )
|
||||
{
|
||||
IoStatus->Status = STATUS_SUCCESS;
|
||||
}
|
||||
else if (Irp && !FailImmediately) { //failed + irp + no fail = mk. pending
|
||||
else if (Irp && !FailImmediately)
|
||||
{ //failed + irp + no fail = mk. pending
|
||||
//for our cancel routine
|
||||
Irp->Tail.Overlay.DriverContext[0] = (PVOID)FileLock;
|
||||
Irp->Tail.Overlay.DriverContext[1] = (PVOID)LockToc;
|
||||
Irp->Tail.Overlay.DriverContext[2] = Context;
|
||||
|
||||
Irp->IoStatus.Information = (DWORD)FileLock;//for our cancel routine
|
||||
IoSetCancelRoutine(Irp, FsRtlpPendingFileLockCancelRoutine);
|
||||
IoSetCancelRoutine(Irp, FsRtlpFileLockCancelRoutine);
|
||||
|
||||
if (Irp->Cancel) {
|
||||
IoSetCancelRoutine(Irp, NULL);
|
||||
/*
|
||||
Irp was canceled and the cancel routine may or may not have been called,
|
||||
waiting there for our spinlock.
|
||||
But it doesn't matter since it will not find the IRP in the list.
|
||||
*/
|
||||
if (Irp->Cancel)
|
||||
{
|
||||
//irp canceled even before we got to queue it
|
||||
if (IoSetCancelRoutine(Irp, NULL))
|
||||
{ //Cancel routine will NOT be called: cancel it here
|
||||
IoStatus->Status = STATUS_CANCELLED;
|
||||
}
|
||||
else { //not cancelled: queue irp
|
||||
IoMarkIrpPending(Irp);
|
||||
Pending = ExAllocateFromNPagedLookasideList(&PendingLookaside);
|
||||
Pending->Context = Context;
|
||||
Pending->Irp = Irp;
|
||||
IoStatus->Status = STATUS_PENDING;
|
||||
InsertHeadList(&LockToc->PendingListHead,&Pending->ListEntry);
|
||||
else
|
||||
{ //Cancel routine WILL be called. When we release the lock it will complete the irp
|
||||
//Return pending since we are not completing the irp here
|
||||
Irp->IoStatus.Status = IoStatus->Status = STATUS_PENDING;
|
||||
Irp->IoStatus.Information = 0;
|
||||
InitializeListHead(&Irp->Tail.Overlay.ListEntry);
|
||||
}
|
||||
|
||||
}
|
||||
else {
|
||||
else
|
||||
{ //not cancelled: queue irp
|
||||
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 (Irp && (IoStatus->Status != STATUS_PENDING)) {
|
||||
if (FileLock->CompleteLockIrpRoutine)
|
||||
{ //complete irp routine
|
||||
|
||||
if (FileLock->CompleteLockIrpRoutine) { //complete irp routine
|
||||
|
||||
if (!NT_SUCCESS(FileLock->CompleteLockIrpRoutine(Context,Irp))) {
|
||||
if (!NT_SUCCESS(FileLock->CompleteLockIrpRoutine(Context,Irp)))
|
||||
{
|
||||
//CompleteLockIrpRoutine complain: revert changes
|
||||
FsRtlpUnlockSingle( FileLock,
|
||||
FileObject,
|
||||
|
@ -987,16 +1045,15 @@ FsRtlPrivateLock (
|
|||
);
|
||||
}
|
||||
}
|
||||
else {//std irp completion
|
||||
else
|
||||
{//std irp completion
|
||||
IofCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//NOTE: only fast io care about this return value
|
||||
if (IoStatus->Status == STATUS_SUCCESS || FailImmediately)
|
||||
return TRUE;
|
||||
|
||||
return FALSE;
|
||||
//NOTE: only fast io seems to care about this return value
|
||||
return (IoStatus->Status == STATUS_SUCCESS || FailImmediately);
|
||||
|
||||
}
|
||||
|
||||
|
@ -1021,9 +1078,10 @@ FsRtlProcessFileLock (
|
|||
|
||||
assert(FileLock);
|
||||
Stack = IoGetCurrentIrpStackLocation(Irp);
|
||||
Irp->IoStatus.Information = 0;
|
||||
|
||||
switch(Stack->MinorFunction){
|
||||
|
||||
switch(Stack->MinorFunction)
|
||||
{
|
||||
case IRP_MN_LOCK:
|
||||
//ret: BOOLEAN
|
||||
FsRtlPrivateLock( FileLock,
|
||||
|
@ -1077,9 +1135,13 @@ FsRtlProcessFileLock (
|
|||
Irp->IoStatus.Status = Status;
|
||||
|
||||
if (FileLock->CompleteLockIrpRoutine )
|
||||
{
|
||||
FileLock->CompleteLockIrpRoutine(Context,Irp);
|
||||
}
|
||||
else
|
||||
{
|
||||
IofCompleteRequest(Irp,IO_NO_INCREMENT);
|
||||
}
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
@ -1097,66 +1159,70 @@ FsRtlUninitializeFileLock (
|
|||
)
|
||||
{
|
||||
PFILE_LOCK_TOC LockToc;
|
||||
PFILE_LOCK_PENDING Pending;
|
||||
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);
|
||||
|
||||
//unlock and free granted locks
|
||||
EnumEntry = LockToc->GrantedListHead.Flink;
|
||||
while (EnumEntry != &LockToc->GrantedListHead) {
|
||||
|
||||
//remove and free granted locks
|
||||
while (!IsListEmpty(&LockToc->GrantedListHead))
|
||||
{
|
||||
EnumEntry = RemoveTailList(&LockToc->GrantedListHead);
|
||||
Granted = CONTAINING_RECORD(EnumEntry, FILE_LOCK_GRANTED, ListEntry);
|
||||
EnumEntry = EnumEntry->Flink;
|
||||
|
||||
RemoveEntryList(&Granted->ListEntry);
|
||||
ExFreeToNPagedLookasideList(&GrantedLookaside, Granted);
|
||||
}
|
||||
|
||||
//complete pending locks
|
||||
EnumEntry = LockToc->PendingListHead.Flink;
|
||||
while (EnumEntry != &LockToc->PendingListHead) {
|
||||
//remove, complete and free all pending locks
|
||||
while (!IsListEmpty(&LockToc->PendingListHead))
|
||||
{
|
||||
EnumEntry = RemoveTailList(&LockToc->PendingListHead);
|
||||
Irp = CONTAINING_RECORD(EnumEntry, IRP, Tail.Overlay.ListEntry);
|
||||
|
||||
Pending = CONTAINING_RECORD(EnumEntry,FILE_LOCK_PENDING, ListEntry);
|
||||
RemoveEntryList(&Pending->ListEntry);
|
||||
|
||||
IoSetCancelRoutine(Pending->Irp, NULL);
|
||||
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);
|
||||
}
|
||||
else
|
||||
{
|
||||
/*
|
||||
Irp could be cancelled and the cancel routine may or may not have been called,
|
||||
waiting there for our spinlock.
|
||||
But it doesn't matter because it will not find the IRP in the list.
|
||||
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
|
||||
|
||||
Pending->Irp->IoStatus.Status = STATUS_RANGE_NOT_LOCKED;
|
||||
Irp->IoStatus.Status = STATUS_RANGE_NOT_LOCKED;
|
||||
|
||||
if (FileLock->CompleteLockIrpRoutine)
|
||||
FileLock->CompleteLockIrpRoutine(Pending->Context,Pending->Irp);
|
||||
{
|
||||
FileLock->CompleteLockIrpRoutine(Irp->Tail.Overlay.DriverContext[2], Irp);
|
||||
}
|
||||
else
|
||||
IofCompleteRequest(Pending->Irp, IO_NO_INCREMENT);
|
||||
|
||||
ExFreeToNPagedLookasideList(&PendingLookaside,Pending);
|
||||
{
|
||||
IofCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
}
|
||||
|
||||
KeAcquireSpinLock(&LockToc->SpinLock, &oldirql);
|
||||
//restart, something migth have happend to our list
|
||||
EnumEntry = LockToc->PendingListHead.Flink;
|
||||
}
|
||||
}
|
||||
|
||||
KeReleaseSpinLock(&LockToc->SpinLock, oldirql);
|
||||
|
||||
ExFreeToNPagedLookasideList(&LockTocLookaside, LockToc);
|
||||
|
||||
FsRtlAreThereCurrentFileLocks(FileLock) = FALSE;
|
||||
FileLock->LockInformation = NULL;
|
||||
|
||||
ExFreeToNPagedLookasideList(&LockTocLookaside, LockToc);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
@ -1178,7 +1244,7 @@ FsRtlAllocateFileLock (
|
|||
{
|
||||
PFILE_LOCK FileLock;
|
||||
|
||||
FileLock = ExAllocatePoolWithTag(PagedPool,sizeof(FILE_LOCK),IFS_POOL_TAG);
|
||||
FileLock = ExAllocateFromPagedLookasideList(&LockLookaside);
|
||||
|
||||
FsRtlInitializeFileLock(FileLock,
|
||||
CompleteLockIrpRoutine,
|
||||
|
@ -1204,8 +1270,9 @@ FsRtlFreeFileLock(
|
|||
)
|
||||
{
|
||||
assert(FileLock);
|
||||
|
||||
FsRtlUninitializeFileLock(FileLock);
|
||||
ExFreePool(FileLock);
|
||||
ExFreeToPagedLookasideList(&LockLookaside, FileLock);
|
||||
}
|
||||
|
||||
/* EOF */
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
#ifndef __INCLUDE_INTERNAL_IFS_H
|
||||
#define __INCLUDE_INTERNAL_IFS_H
|
||||
/* $Id: ifs.h,v 1.4 2002/11/13 06:01:11 robd Exp $ */
|
||||
/* $Id: ifs.h,v 1.5 2003/01/25 15:52:43 hbirr Exp $ */
|
||||
|
||||
#include <ddk/ntifs.h>
|
||||
|
||||
|
@ -11,12 +11,12 @@ VOID STDCALL
|
|||
FsRtlpInitFileLockingImplementation(VOID);
|
||||
|
||||
VOID STDCALL
|
||||
FsRtlpPendingFileLockCancelRoutine(
|
||||
FsRtlpFileLockCancelRoutine(
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PIRP Irp
|
||||
);
|
||||
|
||||
BOOLEAN STDCALL
|
||||
BOOLEAN FASTCALL
|
||||
FsRtlpCheckLockForReadOrWriteAccess(
|
||||
IN PFILE_LOCK FileLock,
|
||||
IN PLARGE_INTEGER FileOffset,
|
||||
|
@ -27,7 +27,7 @@ FsRtlpCheckLockForReadOrWriteAccess(
|
|||
IN BOOLEAN Read
|
||||
);
|
||||
|
||||
NTSTATUS STDCALL
|
||||
NTSTATUS FASTCALL
|
||||
FsRtlpFastUnlockAllByKey(
|
||||
IN PFILE_LOCK FileLock,
|
||||
IN PFILE_OBJECT FileObject,
|
||||
|
@ -37,7 +37,7 @@ FsRtlpFastUnlockAllByKey(
|
|||
IN PVOID Context OPTIONAL
|
||||
);
|
||||
|
||||
NTSTATUS STDCALL
|
||||
NTSTATUS FASTCALL
|
||||
FsRtlpAddLock(
|
||||
IN PFILE_LOCK_TOC LockToc,
|
||||
IN PFILE_OBJECT FileObject,
|
||||
|
@ -48,14 +48,14 @@ FsRtlpAddLock(
|
|||
IN BOOLEAN ExclusiveLock
|
||||
);
|
||||
|
||||
VOID STDCALL
|
||||
FsRtlpTryCompletePendingLocks(
|
||||
VOID FASTCALL
|
||||
FsRtlpCompletePendingLocks(
|
||||
IN PFILE_LOCK FileLock,
|
||||
IN PFILE_LOCK_TOC LockToc,
|
||||
IN OUT PKIRQL oldirql
|
||||
);
|
||||
|
||||
NTSTATUS STDCALL
|
||||
NTSTATUS FASTCALL
|
||||
FsRtlpUnlockSingle(
|
||||
IN PFILE_LOCK FileLock,
|
||||
IN PFILE_OBJECT FileObject,
|
||||
|
@ -68,7 +68,7 @@ FsRtlpUnlockSingle(
|
|||
IN BOOLEAN CallUnlockRoutine
|
||||
);
|
||||
|
||||
VOID STDCALL
|
||||
VOID FASTCALL
|
||||
FsRtlpDumpFileLocks(
|
||||
IN PFILE_LOCK FileLock
|
||||
);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue