1269 lines
32 KiB
C
1269 lines
32 KiB
C
|
/*++
|
|||
|
|
|||
|
Copyright (c) 1989 Microsoft Corporation
|
|||
|
|
|||
|
Module Name:
|
|||
|
|
|||
|
NtFastIo.c
|
|||
|
|
|||
|
Abstract:
|
|||
|
|
|||
|
This module implements NT fastio routines.
|
|||
|
|
|||
|
Author:
|
|||
|
|
|||
|
Joe Linn [JoeLinn] 9-Nov-1994
|
|||
|
|
|||
|
Revision History:
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
#include "precomp.h"
|
|||
|
#pragma hdrstop
|
|||
|
|
|||
|
//
|
|||
|
// The local debug trace level
|
|||
|
//
|
|||
|
|
|||
|
#define Dbg (DEBUG_TRACE_NTFASTIO)
|
|||
|
|
|||
|
#ifdef ALLOC_PRAGMA
|
|||
|
#pragma alloc_text(PAGE, RxFastIoRead)
|
|||
|
#pragma alloc_text(PAGE, RxFastIoWrite)
|
|||
|
#pragma alloc_text(PAGE, RxFastLock)
|
|||
|
#pragma alloc_text(PAGE, RxFastUnlockAll)
|
|||
|
#pragma alloc_text(PAGE, RxFastUnlockAllByKey)
|
|||
|
#pragma alloc_text(PAGE, RxFastUnlockSingle)
|
|||
|
#pragma alloc_text(PAGE, RxFastIoCheckIfPossible)
|
|||
|
#pragma alloc_text(PAGE, RxFastQueryBasicInfo)
|
|||
|
#pragma alloc_text(PAGE, RxFastQueryStdInfo)
|
|||
|
#endif
|
|||
|
|
|||
|
|
|||
|
//these declarations would be copied to fsrtl.h
|
|||
|
BOOLEAN
|
|||
|
FsRtlCopyRead2 (
|
|||
|
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 ULONG_PTR TopLevelIrpValue
|
|||
|
);
|
|||
|
BOOLEAN
|
|||
|
FsRtlCopyWrite2 (
|
|||
|
IN PFILE_OBJECT FileObject,
|
|||
|
IN PLARGE_INTEGER FileOffset,
|
|||
|
IN ULONG Length,
|
|||
|
IN BOOLEAN Wait,
|
|||
|
IN ULONG LockKey,
|
|||
|
IN PVOID Buffer,
|
|||
|
OUT PIO_STATUS_BLOCK IoStatus,
|
|||
|
IN PDEVICE_OBJECT DeviceObject,
|
|||
|
IN ULONG_PTR TopLevelIrpValue
|
|||
|
);
|
|||
|
|
|||
|
BOOLEAN
|
|||
|
RxFastIoRead (
|
|||
|
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
|
|||
|
)
|
|||
|
{
|
|||
|
BOOLEAN ReturnValue;
|
|||
|
|
|||
|
RX_TOPLEVELIRP_CONTEXT TopLevelContext;
|
|||
|
|
|||
|
PAGED_CODE();
|
|||
|
|
|||
|
RxDbgTrace(+1, Dbg, ("RxFastIoRead\n"));
|
|||
|
|
|||
|
RxLog(("FastRead %lx:%lx:%lx",FileObject,FileObject->FsContext,FileObject->FsContext2));
|
|||
|
RxLog(("------>> %lx@%lx %lx",Length,FileOffset->LowPart,FileOffset->HighPart));
|
|||
|
RxWmiLog(LOG,
|
|||
|
RxFastIoRead_1,
|
|||
|
LOGPTR(FileObject)
|
|||
|
LOGPTR(FileObject->FsContext)
|
|||
|
LOGPTR(FileObject->FsContext2)
|
|||
|
LOGULONG(Length)
|
|||
|
LOGULONG(FileOffset->LowPart)
|
|||
|
LOGULONG(FileOffset->HighPart));
|
|||
|
|
|||
|
ASSERT(RxIsThisTheTopLevelIrp(NULL));
|
|||
|
|
|||
|
RxInitializeTopLevelIrpContext(
|
|||
|
&TopLevelContext,
|
|||
|
((PIRP)FSRTL_FAST_IO_TOP_LEVEL_IRP),
|
|||
|
(PRDBSS_DEVICE_OBJECT)DeviceObject);
|
|||
|
|
|||
|
ReturnValue = FsRtlCopyRead2 (
|
|||
|
FileObject,
|
|||
|
FileOffset,
|
|||
|
Length,
|
|||
|
Wait,
|
|||
|
LockKey,
|
|||
|
Buffer,
|
|||
|
IoStatus,
|
|||
|
DeviceObject,
|
|||
|
(ULONG_PTR)(&TopLevelContext)
|
|||
|
);
|
|||
|
|
|||
|
RxDbgTrace(-1, Dbg, ("RxFastIoRead ReturnValue=%x\n", ReturnValue));
|
|||
|
|
|||
|
if (ReturnValue) {
|
|||
|
RxLog(
|
|||
|
("FastReadYes %lx ret %lx:%lx",
|
|||
|
FileObject->FsContext2,IoStatus->Status,IoStatus->Information));
|
|||
|
RxWmiLog(LOG,
|
|||
|
RxFastIoRead_2,
|
|||
|
LOGPTR(FileObject->FsContext2)
|
|||
|
LOGULONG(IoStatus->Status)
|
|||
|
LOGPTR(IoStatus->Information));
|
|||
|
} else {
|
|||
|
RxLog(("FastReadNo %lx",FileObject->FsContext2));
|
|||
|
RxWmiLog(LOG,
|
|||
|
RxFastIoRead_3,
|
|||
|
LOGPTR(FileObject->FsContext2));
|
|||
|
}
|
|||
|
|
|||
|
return ReturnValue;
|
|||
|
}
|
|||
|
|
|||
|
BOOLEAN
|
|||
|
RxFastIoWrite (
|
|||
|
IN PFILE_OBJECT FileObject,
|
|||
|
IN PLARGE_INTEGER FileOffset,
|
|||
|
IN ULONG Length,
|
|||
|
IN BOOLEAN Wait,
|
|||
|
IN ULONG LockKey,
|
|||
|
IN PVOID Buffer,
|
|||
|
OUT PIO_STATUS_BLOCK IoStatus,
|
|||
|
IN PDEVICE_OBJECT DeviceObject
|
|||
|
)
|
|||
|
{
|
|||
|
BOOLEAN ReturnValue;
|
|||
|
|
|||
|
RX_TOPLEVELIRP_CONTEXT TopLevelContext;
|
|||
|
|
|||
|
PSRV_OPEN SrvOpen;
|
|||
|
|
|||
|
PAGED_CODE();
|
|||
|
|
|||
|
RxDbgTrace(+1, Dbg, ("RxFastIoWrite\n"));
|
|||
|
|
|||
|
SrvOpen = ((PFOBX)(FileObject->FsContext2))->SrvOpen;
|
|||
|
if (FlagOn(SrvOpen->Flags,SRVOPEN_FLAG_DONTUSE_WRITE_CACHEING)) {
|
|||
|
//if this flag is set, we have to treat this as an unbuffered Io....sigh.
|
|||
|
RxDbgTrace(-1, Dbg, ("RxFastIoWrite DONTUSE_WRITE_CACHEING...failing\n"));
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
|
|||
|
ASSERT(RxIsThisTheTopLevelIrp(NULL));
|
|||
|
|
|||
|
RxInitializeTopLevelIrpContext(
|
|||
|
&TopLevelContext,
|
|||
|
((PIRP)FSRTL_FAST_IO_TOP_LEVEL_IRP),
|
|||
|
(PRDBSS_DEVICE_OBJECT)DeviceObject);
|
|||
|
|
|||
|
ReturnValue = FsRtlCopyWrite2 (
|
|||
|
FileObject,
|
|||
|
FileOffset,
|
|||
|
Length,
|
|||
|
Wait,
|
|||
|
LockKey,
|
|||
|
Buffer,
|
|||
|
IoStatus,
|
|||
|
DeviceObject,
|
|||
|
(ULONG_PTR)(&TopLevelContext)
|
|||
|
);
|
|||
|
|
|||
|
RxDbgTrace(-1, Dbg, ("RxFastIoWrite ReturnValue=%x\n", ReturnValue));
|
|||
|
|
|||
|
if (ReturnValue) {
|
|||
|
RxLog(
|
|||
|
("FWY %lx OLP: %lx SLP: %lx IOSB %lx:%lx",
|
|||
|
FileObject->FsContext2,
|
|||
|
FileOffset->LowPart,
|
|||
|
SrvOpen->pFcb->Header.FileSize.LowPart,
|
|||
|
IoStatus->Status,
|
|||
|
IoStatus->Information));
|
|||
|
RxWmiLog(LOG,
|
|||
|
RxFastIoWrite_1,
|
|||
|
LOGPTR(FileObject->FsContext2)
|
|||
|
LOGULONG(FileOffset->LowPart)
|
|||
|
LOGULONG(SrvOpen->pFcb->Header.FileSize.LowPart)
|
|||
|
LOGULONG(IoStatus->Status)
|
|||
|
LOGPTR(IoStatus->Information));
|
|||
|
} else {
|
|||
|
RxLog(("FastWriteNo %lx",FileObject->FsContext2));
|
|||
|
RxWmiLog(LOG,
|
|||
|
RxFastIoWrite_2,
|
|||
|
LOGPTR(FileObject->FsContext2));
|
|||
|
}
|
|||
|
|
|||
|
return ReturnValue;
|
|||
|
}
|
|||
|
|
|||
|
BOOLEAN
|
|||
|
RxFastLock (
|
|||
|
IN PFILE_OBJECT FileObject,
|
|||
|
IN PLARGE_INTEGER FileOffset,
|
|||
|
IN PLARGE_INTEGER Length,
|
|||
|
PEPROCESS ProcessId,
|
|||
|
ULONG Key,
|
|||
|
BOOLEAN FailImmediately,
|
|||
|
BOOLEAN ExclusiveLock,
|
|||
|
OUT PIO_STATUS_BLOCK IoStatus,
|
|||
|
IN PDEVICE_OBJECT DeviceObject
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This is a call back routine for doing the fast lock call.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
FileObject - Supplies the file object used in this operation
|
|||
|
|
|||
|
FileOffset - Supplies the file offset used in this operation
|
|||
|
|
|||
|
Length - Supplies the length used in this operation
|
|||
|
|
|||
|
ProcessId - Supplies the process ID used in this operation
|
|||
|
|
|||
|
Key - Supplies the key used in this operation
|
|||
|
|
|||
|
FailImmediately - Indicates if the request should fail immediately
|
|||
|
if the lock cannot be granted.
|
|||
|
|
|||
|
ExclusiveLock - Indicates if this is a request for an exclusive or
|
|||
|
shared lock
|
|||
|
|
|||
|
IoStatus - Receives the Status if this operation is successful
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
BOOLEAN - TRUE if this operation completed and FALSE if caller
|
|||
|
needs to take the long route.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
BOOLEAN Results;
|
|||
|
PFCB Fcb = (PFCB)(FileObject->FsContext); //need a macro
|
|||
|
|
|||
|
PAGED_CODE();
|
|||
|
|
|||
|
RxDbgTrace(+1, Dbg, ("RxFastLock\n", 0));
|
|||
|
|
|||
|
//
|
|||
|
// Decode the type of file object we're being asked to process and make
|
|||
|
// sure it is only a user file open.
|
|||
|
//
|
|||
|
|
|||
|
if (NodeType(Fcb) != RDBSS_NTC_STORAGE_TYPE_FILE) {
|
|||
|
|
|||
|
IoStatus->Status = STATUS_INVALID_PARAMETER;
|
|||
|
IoStatus->Information = 0;
|
|||
|
|
|||
|
RxDbgTrace(-1, Dbg, ("RxFastLock -> TRUE (RxStatus(INVALID_PARAMETER))\n", 0));
|
|||
|
return TRUE;
|
|||
|
}
|
|||
|
|
|||
|
RxDbgTrace(-1, Dbg, ("RxFastLock -> FALSE (fastlocks not yet implemented)\n", 0));
|
|||
|
return FALSE; //stuff past here has been massaged but not tested
|
|||
|
|
|||
|
//
|
|||
|
// Acquire exclusive access to the Fcb this operation can always wait; you need
|
|||
|
// the resource to synchronize with oplock breaks
|
|||
|
//
|
|||
|
|
|||
|
FsRtlEnterFileSystem();
|
|||
|
|
|||
|
ExAcquireResourceSharedLite( Fcb->Header.Resource, TRUE );
|
|||
|
|
|||
|
try {
|
|||
|
|
|||
|
//
|
|||
|
// We check whether we can proceed
|
|||
|
// based on the state of the file oplocks.
|
|||
|
//
|
|||
|
|
|||
|
if (!FsRtlOplockIsFastIoPossible( &(Fcb)->Specific.Fcb.Oplock )) {
|
|||
|
|
|||
|
try_return( Results = FALSE );
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Now call the FsRtl routine to do the actual processing of the
|
|||
|
// Lock request
|
|||
|
//
|
|||
|
|
|||
|
if (Results = FsRtlFastLock(
|
|||
|
&Fcb->Specific.Fcb.FileLock,
|
|||
|
FileObject,
|
|||
|
FileOffset,
|
|||
|
Length,
|
|||
|
ProcessId,
|
|||
|
Key,
|
|||
|
FailImmediately,
|
|||
|
ExclusiveLock,
|
|||
|
IoStatus,
|
|||
|
NULL,
|
|||
|
FALSE )) {
|
|||
|
//
|
|||
|
// Set the flag indicating if Fast I/O is possible
|
|||
|
//
|
|||
|
|
|||
|
//Fcb->Header.IsFastIoPossible = RxIsFastIoPossible( Fcb );
|
|||
|
}
|
|||
|
|
|||
|
try_exit: NOTHING;
|
|||
|
} finally {
|
|||
|
|
|||
|
DebugUnwind( RxFastLock );
|
|||
|
|
|||
|
//
|
|||
|
// Release the Fcb, and return to our caller
|
|||
|
//
|
|||
|
|
|||
|
ExReleaseResourceLite( (Fcb)->Header.Resource );
|
|||
|
|
|||
|
FsRtlExitFileSystem();
|
|||
|
|
|||
|
RxDbgTrace(-1, Dbg, ("RxFastLock -> %08lx\n", Results));
|
|||
|
}
|
|||
|
|
|||
|
return Results;
|
|||
|
}
|
|||
|
|
|||
|
BOOLEAN
|
|||
|
RxFastUnlockSingle (
|
|||
|
IN PFILE_OBJECT FileObject,
|
|||
|
IN PLARGE_INTEGER FileOffset,
|
|||
|
IN PLARGE_INTEGER Length,
|
|||
|
PEPROCESS ProcessId,
|
|||
|
ULONG Key,
|
|||
|
OUT PIO_STATUS_BLOCK IoStatus,
|
|||
|
IN PDEVICE_OBJECT DeviceObject
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This is a call back routine for doing the fast unlock single call.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
FileObject - Supplies the file object used in this operation
|
|||
|
|
|||
|
FileOffset - Supplies the file offset used in this operation
|
|||
|
|
|||
|
Length - Supplies the length used in this operation
|
|||
|
|
|||
|
ProcessId - Supplies the process ID used in this operation
|
|||
|
|
|||
|
Key - Supplies the key used in this operation
|
|||
|
|
|||
|
Status - Receives the Status if this operation is successful
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
BOOLEAN - TRUE if this operation completed and FALSE if caller
|
|||
|
needs to take the long route.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
BOOLEAN Results;
|
|||
|
PFCB Fcb = (PFCB)(FileObject->FsContext); //need macro
|
|||
|
|
|||
|
PAGED_CODE();
|
|||
|
|
|||
|
RxDbgTrace(+1, Dbg, ("RxFastUnlockSingle\n", 0));
|
|||
|
|
|||
|
IoStatus->Information = 0;
|
|||
|
|
|||
|
//
|
|||
|
// Decode the type of file object we're being asked to process and make sure
|
|||
|
// it is only a user file open
|
|||
|
//
|
|||
|
|
|||
|
if (NodeType(Fcb) != RDBSS_NTC_STORAGE_TYPE_FILE) {
|
|||
|
|
|||
|
IoStatus->Status = STATUS_INVALID_PARAMETER;
|
|||
|
|
|||
|
RxDbgTrace(-1, Dbg, ("RxFastUnlockSingle -> TRUE (RxStatus(INVALID_PARAMETER))\n", 0));
|
|||
|
return TRUE;
|
|||
|
}
|
|||
|
|
|||
|
RxDbgTrace(-1, Dbg, ("RxFastUnlockSingle -> FALSE (fastlocks not yet implemented)\n", 0));
|
|||
|
return FALSE; //stuff past here has been massaged but not tested
|
|||
|
|
|||
|
//
|
|||
|
// Acquire exclusive access to the Fcb this operation can always wait
|
|||
|
//
|
|||
|
|
|||
|
FsRtlEnterFileSystem();
|
|||
|
|
|||
|
ExAcquireResourceSharedLite( Fcb->Header.Resource, TRUE );
|
|||
|
|
|||
|
try {
|
|||
|
|
|||
|
//
|
|||
|
// We check whether we can proceed based on the state of the file oplocks.
|
|||
|
//
|
|||
|
|
|||
|
if (!FsRtlOplockIsFastIoPossible( &(Fcb)->Specific.Fcb.Oplock )) {
|
|||
|
|
|||
|
try_return( Results = FALSE );
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Now call the FsRtl routine to do the actual processing of the
|
|||
|
// Lock request. The call will always succeed.
|
|||
|
//
|
|||
|
|
|||
|
Results = TRUE;
|
|||
|
IoStatus->Status = FsRtlFastUnlockSingle(
|
|||
|
&Fcb->Specific.Fcb.FileLock,
|
|||
|
FileObject,
|
|||
|
FileOffset,
|
|||
|
Length,
|
|||
|
ProcessId,
|
|||
|
Key,
|
|||
|
NULL,
|
|||
|
FALSE );
|
|||
|
|
|||
|
//
|
|||
|
// Set the flag indicating if Fast I/O is possible
|
|||
|
//
|
|||
|
|
|||
|
//Fcb->Header.IsFastIoPossible = RxIsFastIoPossible( Fcb );
|
|||
|
|
|||
|
try_exit: NOTHING;
|
|||
|
} finally {
|
|||
|
|
|||
|
DebugUnwind( RxFastUnlockSingle );
|
|||
|
|
|||
|
//
|
|||
|
// Release the Fcb, and return to our caller
|
|||
|
//
|
|||
|
|
|||
|
ExReleaseResourceLite( (Fcb)->Header.Resource );
|
|||
|
|
|||
|
FsRtlExitFileSystem();
|
|||
|
|
|||
|
RxDbgTrace(-1, Dbg, ("RxFastUnlockSingle -> %08lx\n", Results));
|
|||
|
}
|
|||
|
|
|||
|
return Results;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
BOOLEAN
|
|||
|
RxFastUnlockAll (
|
|||
|
IN PFILE_OBJECT FileObject,
|
|||
|
PEPROCESS ProcessId,
|
|||
|
OUT PIO_STATUS_BLOCK IoStatus,
|
|||
|
IN PDEVICE_OBJECT DeviceObject
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This is a call back routine for doing the fast unlock all call.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
FileObject - Supplies the file object used in this operation
|
|||
|
|
|||
|
ProcessId - Supplies the process ID used in this operation
|
|||
|
|
|||
|
Status - Receives the Status if this operation is successful
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
BOOLEAN - TRUE if this operation completed and FALSE if caller
|
|||
|
needs to take the long route.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
BOOLEAN Results;
|
|||
|
PFCB Fcb = (PFCB)(FileObject->FsContext); //need macro
|
|||
|
|
|||
|
PAGED_CODE();
|
|||
|
|
|||
|
RxDbgTrace(+1, Dbg, ("RxFastUnlockAll\n", 0));
|
|||
|
|
|||
|
IoStatus->Information = 0;
|
|||
|
|
|||
|
//
|
|||
|
// Decode the type of file object we're being asked to process and make sure
|
|||
|
// it is only a user file open.
|
|||
|
//
|
|||
|
|
|||
|
if (NodeType(Fcb) != RDBSS_NTC_STORAGE_TYPE_FILE) {
|
|||
|
|
|||
|
IoStatus->Status = STATUS_INVALID_PARAMETER;
|
|||
|
|
|||
|
RxDbgTrace(-1, Dbg, ("RxFastUnlockAll -> TRUE (RxStatus(INVALID_PARAMETER))\n", 0));
|
|||
|
return TRUE;
|
|||
|
}
|
|||
|
|
|||
|
RxDbgTrace(-1, Dbg, ("RxFastUnlockAll -> FALSE (fastlocks not yet implemented)\n", 0));
|
|||
|
return FALSE; //stuff past here has been massaged but not tested
|
|||
|
|
|||
|
//
|
|||
|
// Acquire exclusive access to the Fcb this operation can always wait
|
|||
|
//
|
|||
|
|
|||
|
FsRtlEnterFileSystem();
|
|||
|
|
|||
|
(VOID) ExAcquireResourceSharedLite( Fcb->Header.Resource, TRUE );
|
|||
|
|
|||
|
try {
|
|||
|
|
|||
|
//
|
|||
|
// We check whether we can proceed based on the state of the file oplocks.
|
|||
|
//
|
|||
|
|
|||
|
if (!FsRtlOplockIsFastIoPossible( &(Fcb)->Specific.Fcb.Oplock )) {
|
|||
|
|
|||
|
try_return( Results = FALSE );
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Now call the FsRtl routine to do the actual processing of the
|
|||
|
// Lock request. The call will always succeed.
|
|||
|
//
|
|||
|
|
|||
|
Results = TRUE;
|
|||
|
IoStatus->Status = FsRtlFastUnlockAll(
|
|||
|
&Fcb->Specific.Fcb.FileLock,
|
|||
|
FileObject,
|
|||
|
ProcessId,
|
|||
|
NULL );
|
|||
|
|
|||
|
//
|
|||
|
// Set the flag indicating if Fast I/O is possible
|
|||
|
//
|
|||
|
|
|||
|
//Fcb->Header.IsFastIoPossible = RxIsFastIoPossible( Fcb );
|
|||
|
|
|||
|
try_exit: NOTHING;
|
|||
|
} finally {
|
|||
|
|
|||
|
DebugUnwind( RxFastUnlockAll );
|
|||
|
|
|||
|
//
|
|||
|
// Release the Fcb, and return to our caller
|
|||
|
//
|
|||
|
|
|||
|
ExReleaseResourceLite( (Fcb)->Header.Resource );
|
|||
|
|
|||
|
FsRtlExitFileSystem();
|
|||
|
|
|||
|
RxDbgTrace(-1, Dbg, ("RxFastUnlockAll -> %08lx\n", Results));
|
|||
|
}
|
|||
|
|
|||
|
return Results;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
BOOLEAN
|
|||
|
RxFastUnlockAllByKey (
|
|||
|
IN PFILE_OBJECT FileObject,
|
|||
|
PVOID ProcessId,
|
|||
|
ULONG Key,
|
|||
|
OUT PIO_STATUS_BLOCK IoStatus,
|
|||
|
IN PDEVICE_OBJECT DeviceObject
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This is a call back routine for doing the fast unlock all by key call.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
FileObject - Supplies the file object used in this operation
|
|||
|
|
|||
|
ProcessId - Supplies the process ID used in this operation
|
|||
|
|
|||
|
Key - Supplies the key used in this operation
|
|||
|
|
|||
|
Status - Receives the Status if this operation is successful
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
BOOLEAN - TRUE if this operation completed and FALSE if caller
|
|||
|
needs to take the long route.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
BOOLEAN Results;
|
|||
|
PFCB Fcb = (PFCB)(FileObject->FsContext); //need macro
|
|||
|
|
|||
|
PAGED_CODE();
|
|||
|
|
|||
|
RxDbgTrace(+1, Dbg, ("RxFastUnlockAllByKey\n", 0));
|
|||
|
|
|||
|
IoStatus->Information = 0;
|
|||
|
|
|||
|
//
|
|||
|
// Decode the type of file object we're being asked to process and make sure
|
|||
|
// it is only a user file open.
|
|||
|
//
|
|||
|
|
|||
|
if (NodeType(Fcb) != RDBSS_NTC_STORAGE_TYPE_FILE) {
|
|||
|
|
|||
|
IoStatus->Status = STATUS_INVALID_PARAMETER;
|
|||
|
|
|||
|
RxDbgTrace(-1, Dbg, ("RxFastUnlockAll -> TRUE (RxStatus(INVALID_PARAMETER))\n", 0));
|
|||
|
return TRUE;
|
|||
|
}
|
|||
|
|
|||
|
RxDbgTrace(-1, Dbg, ("RxFastUnlockAll -> FALSE (fastlocks not yet implemented)\n", 0));
|
|||
|
return FALSE; //stuff past here has been massaged but not tested
|
|||
|
|
|||
|
//
|
|||
|
// Acquire exclusive access to the Fcb this operation can always wait
|
|||
|
//
|
|||
|
|
|||
|
FsRtlEnterFileSystem();
|
|||
|
|
|||
|
(VOID) ExAcquireResourceSharedLite( Fcb->Header.Resource, TRUE );
|
|||
|
|
|||
|
try {
|
|||
|
|
|||
|
//
|
|||
|
// We check whether we can proceed based on the state of the file oplocks.
|
|||
|
//
|
|||
|
|
|||
|
if (!FsRtlOplockIsFastIoPossible( &(Fcb)->Specific.Fcb.Oplock )) {
|
|||
|
|
|||
|
try_return( Results = FALSE );
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Now call the FsRtl routine to do the actual processing of the
|
|||
|
// Lock request. The call will always succeed.
|
|||
|
//
|
|||
|
|
|||
|
Results = TRUE;
|
|||
|
IoStatus->Status = FsRtlFastUnlockAllByKey(
|
|||
|
&Fcb->Specific.Fcb.FileLock,
|
|||
|
FileObject,
|
|||
|
ProcessId,
|
|||
|
Key,
|
|||
|
NULL );
|
|||
|
|
|||
|
//
|
|||
|
// Set the flag indicating if Fast I/O is possible
|
|||
|
//
|
|||
|
|
|||
|
//Fcb->Header.IsFastIoPossible = RxIsFastIoPossible( Fcb );
|
|||
|
|
|||
|
try_exit: NOTHING;
|
|||
|
} finally {
|
|||
|
|
|||
|
DebugUnwind( RxFastUnlockAllByKey );
|
|||
|
|
|||
|
//
|
|||
|
// Release the Fcb, and return to our caller
|
|||
|
//
|
|||
|
|
|||
|
ExReleaseResourceLite( (Fcb)->Header.Resource );
|
|||
|
|
|||
|
FsRtlExitFileSystem();
|
|||
|
|
|||
|
RxDbgTrace(-1, Dbg, ("RxFastUnlockAllByKey -> %08lx\n", Results));
|
|||
|
}
|
|||
|
|
|||
|
return Results;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
#define RxLogAndReturnFalse(x) { \
|
|||
|
RxLog(("CheckFast fail %lx %s",FileObject,x)); \
|
|||
|
RxWmiLog(LOG, \
|
|||
|
RxFastIoCheckIfPossible, \
|
|||
|
LOGPTR(FileObject) \
|
|||
|
LOGARSTR(x)); \
|
|||
|
return FALSE; \
|
|||
|
}
|
|||
|
BOOLEAN
|
|||
|
RxFastIoCheckIfPossible (
|
|||
|
IN PFILE_OBJECT FileObject,
|
|||
|
IN PLARGE_INTEGER FileOffset,
|
|||
|
IN ULONG Length,
|
|||
|
IN BOOLEAN Wait,
|
|||
|
IN ULONG LockKey,
|
|||
|
IN BOOLEAN CheckForReadOperation,
|
|||
|
OUT PIO_STATUS_BLOCK IoStatus,
|
|||
|
IN PDEVICE_OBJECT DeviceObject
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine checks if fast i/o is possible for a read/write operation
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
FileObject - Supplies the file object used in the query
|
|||
|
|
|||
|
FileOffset - Supplies the starting byte offset for the read/write operation
|
|||
|
|
|||
|
Length - Supplies the length, in bytes, of the read/write operation
|
|||
|
|
|||
|
Wait - Indicates if we can wait
|
|||
|
|
|||
|
LockKey - Supplies the lock key
|
|||
|
|
|||
|
CheckForReadOperation - Indicates if this is a check for a read or write
|
|||
|
operation
|
|||
|
|
|||
|
IoStatus - Receives the status of the operation if our return value is
|
|||
|
FastIoReturnError
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
BOOLEAN - TRUE if fast I/O is possible and FALSE if the caller needs
|
|||
|
to take the long route.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
PFCB Fcb = (PFCB)(FileObject->FsContext);
|
|||
|
PFOBX Fobx = (PFOBX)(FileObject->FsContext2);
|
|||
|
PSRV_OPEN pSrvOpen = Fobx->SrvOpen;
|
|||
|
|
|||
|
LARGE_INTEGER LargeLength;
|
|||
|
|
|||
|
PAGED_CODE();
|
|||
|
|
|||
|
if (NodeType(Fcb) != RDBSS_NTC_STORAGE_TYPE_FILE) {
|
|||
|
RxLogAndReturnFalse("notfile");
|
|||
|
}
|
|||
|
|
|||
|
if (!FsRtlOplockIsFastIoPossible( &Fcb->Specific.Fcb.Oplock )) {
|
|||
|
RxLogAndReturnFalse("cnd/oplock");
|
|||
|
}
|
|||
|
|
|||
|
if (FileObject->DeletePending) {
|
|||
|
RxLogAndReturnFalse("delpend");
|
|||
|
}
|
|||
|
|
|||
|
if (Fcb->NonPaged->OutstandingAsyncWrites != 0) {
|
|||
|
RxLogAndReturnFalse("asynW");
|
|||
|
}
|
|||
|
|
|||
|
if (FlagOn(pSrvOpen->Flags,SRVOPEN_FLAG_ORPHANED)) {
|
|||
|
RxLogAndReturnFalse("srvopen orphaned");
|
|||
|
}
|
|||
|
|
|||
|
if (FlagOn(Fcb->FcbState,FCB_STATE_ORPHANED)) {
|
|||
|
RxLogAndReturnFalse("orphaned");
|
|||
|
}
|
|||
|
|
|||
|
if (BooleanFlagOn(
|
|||
|
pSrvOpen->Flags,
|
|||
|
SRVOPEN_FLAG_BUFFERING_STATE_CHANGE_PENDING)) {
|
|||
|
RxLogAndReturnFalse("buf state change");
|
|||
|
}
|
|||
|
|
|||
|
if (FlagOn(pSrvOpen->Flags,SRVOPEN_FLAG_FILE_RENAMED) ||
|
|||
|
FlagOn(pSrvOpen->Flags,SRVOPEN_FLAG_FILE_DELETED)) {
|
|||
|
RxLogAndReturnFalse("ren/del");
|
|||
|
}
|
|||
|
|
|||
|
// Ensure that all pending buffering state change requests are processed
|
|||
|
// before letting the operation through.
|
|||
|
|
|||
|
FsRtlEnterFileSystem();
|
|||
|
|
|||
|
RxProcessChangeBufferingStateRequestsForSrvOpen(pSrvOpen);
|
|||
|
|
|||
|
FsRtlExitFileSystem();
|
|||
|
|
|||
|
LargeLength.QuadPart = Length;
|
|||
|
|
|||
|
//
|
|||
|
// Based on whether this is a read or write operation we call
|
|||
|
// fsrtl check for read/write
|
|||
|
//
|
|||
|
|
|||
|
if (CheckForReadOperation) {
|
|||
|
if (!FlagOn(Fcb->FcbState,FCB_STATE_READCACHEING_ENABLED)) {
|
|||
|
RxLogAndReturnFalse("notreadC");
|
|||
|
}
|
|||
|
|
|||
|
if (!FsRtlFastCheckLockForRead(
|
|||
|
&Fcb->Specific.Fcb.FileLock,
|
|||
|
FileOffset,
|
|||
|
&LargeLength,
|
|||
|
LockKey,
|
|||
|
FileObject,
|
|||
|
PsGetCurrentProcess() )) {
|
|||
|
|
|||
|
RxLogAndReturnFalse("readlock");
|
|||
|
}
|
|||
|
|
|||
|
} else {
|
|||
|
|
|||
|
if (!FlagOn(Fcb->FcbState,FCB_STATE_WRITECACHEING_ENABLED)) {
|
|||
|
RxLogAndReturnFalse("notwriteC");
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Also check for a write-protected volume here.
|
|||
|
//
|
|||
|
|
|||
|
if (!FsRtlFastCheckLockForWrite(
|
|||
|
&Fcb->Specific.Fcb.FileLock,
|
|||
|
FileOffset,
|
|||
|
&LargeLength,
|
|||
|
LockKey,
|
|||
|
FileObject,
|
|||
|
PsGetCurrentProcess() )) {
|
|||
|
|
|||
|
RxLogAndReturnFalse("writelock");
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
// RxLog(("IoPossible %lx",FileObject));
|
|||
|
return TRUE;
|
|||
|
}
|
|||
|
|
|||
|
BOOLEAN
|
|||
|
RxFastIoDeviceControl(
|
|||
|
IN struct _FILE_OBJECT *FileObject,
|
|||
|
IN BOOLEAN Wait,
|
|||
|
IN PVOID InputBuffer OPTIONAL,
|
|||
|
IN ULONG InputBufferLength,
|
|||
|
OUT PVOID OutputBuffer OPTIONAL,
|
|||
|
IN ULONG OutputBufferLength,
|
|||
|
IN ULONG IoControlCode,
|
|||
|
OUT PIO_STATUS_BLOCK IoStatus,
|
|||
|
IN struct _DEVICE_OBJECT *DeviceObject
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine is for the fast device control call.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
FileObject - Supplies the file object used in this operation
|
|||
|
|
|||
|
Wait - Indicates if we are allowed to wait for the information
|
|||
|
|
|||
|
InputBuffer - Supplies the input buffer
|
|||
|
|
|||
|
InputBufferLength - the length of the input buffer
|
|||
|
|
|||
|
OutputBuffer - the output buffer
|
|||
|
|
|||
|
OutputBufferLength - the length of the output buffer
|
|||
|
|
|||
|
IoControlCode - the IO control code
|
|||
|
|
|||
|
IoStatus - Receives the final status of the operation
|
|||
|
|
|||
|
DeviceObject - the associated device object
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
BOOLEAN - TRUE if the operation succeeded and FALSE if the caller
|
|||
|
needs to take the long route.
|
|||
|
|
|||
|
Notes:
|
|||
|
|
|||
|
The following IO control requests are handled in the first path
|
|||
|
|
|||
|
IOCTL_LMR_ARE_FILE_OBJECTS_ON_SAME_SERVER
|
|||
|
|
|||
|
InputBuffer - pointer to the other file object
|
|||
|
|
|||
|
InputBufferLength - length in bytes of a pointer.
|
|||
|
|
|||
|
OutputBuffer - not used
|
|||
|
|
|||
|
OutputBufferLength - not used
|
|||
|
|
|||
|
IoStatus --
|
|||
|
|
|||
|
IoStatus.Status set to STATUS_SUCCESS if both the file objects are
|
|||
|
on the same server, otherwise set to STATUS_NOT_SAME_DEVICE
|
|||
|
|
|||
|
This is a kernel mode interface only.
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
BOOLEAN FastIoSucceeded;
|
|||
|
|
|||
|
switch (IoControlCode) {
|
|||
|
case IOCTL_LMR_ARE_FILE_OBJECTS_ON_SAME_SERVER :
|
|||
|
{
|
|||
|
FastIoSucceeded = TRUE;
|
|||
|
|
|||
|
try {
|
|||
|
if (InputBufferLength == sizeof(HANDLE)) {
|
|||
|
PFCB pFcb1,pFcb2;
|
|||
|
HANDLE hFile;
|
|||
|
PFILE_OBJECT pFileObject2;
|
|||
|
NTSTATUS Status;
|
|||
|
|
|||
|
pFcb1 = (PFCB)FileObject->FsContext;
|
|||
|
|
|||
|
RtlCopyMemory(
|
|||
|
&hFile,
|
|||
|
InputBuffer,
|
|||
|
sizeof(HANDLE));
|
|||
|
|
|||
|
Status = ObReferenceObjectByHandle(
|
|||
|
hFile,
|
|||
|
FILE_ANY_ACCESS,
|
|||
|
*IoFileObjectType,
|
|||
|
UserMode,
|
|||
|
&pFileObject2,
|
|||
|
NULL);
|
|||
|
|
|||
|
if ((Status == STATUS_SUCCESS)) {
|
|||
|
|
|||
|
if(pFileObject2->DeviceObject == DeviceObject) {
|
|||
|
|
|||
|
pFcb2 = (PFCB)pFileObject2->FsContext;
|
|||
|
|
|||
|
if ((pFcb2 != NULL) &&
|
|||
|
(NodeTypeIsFcb(pFcb2))) {
|
|||
|
if (pFcb1->pNetRoot->pSrvCall == pFcb2->pNetRoot->pSrvCall) {
|
|||
|
IoStatus->Status = STATUS_SUCCESS;
|
|||
|
} else {
|
|||
|
IoStatus->Status = STATUS_NOT_SAME_DEVICE;
|
|||
|
}
|
|||
|
} else {
|
|||
|
Status = STATUS_INVALID_PARAMETER;
|
|||
|
}
|
|||
|
} else {
|
|||
|
Status = STATUS_INVALID_PARAMETER;
|
|||
|
}
|
|||
|
|
|||
|
ObDereferenceObject(pFileObject2);
|
|||
|
|
|||
|
} else {
|
|||
|
IoStatus->Status = STATUS_INVALID_PARAMETER;
|
|||
|
}
|
|||
|
} else {
|
|||
|
IoStatus->Status = STATUS_INVALID_PARAMETER;
|
|||
|
}
|
|||
|
} except( EXCEPTION_EXECUTE_HANDLER ) {
|
|||
|
// The I/O request was not handled successfully, abort the I/O request with
|
|||
|
// the error status that we get back from the execption code
|
|||
|
|
|||
|
IoStatus->Status = STATUS_INVALID_PARAMETER;
|
|||
|
FastIoSucceeded = TRUE;
|
|||
|
}
|
|||
|
}
|
|||
|
break;
|
|||
|
|
|||
|
default:
|
|||
|
{
|
|||
|
FastIoSucceeded = FALSE;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
return FastIoSucceeded;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
BOOLEAN
|
|||
|
RxFastQueryBasicInfo (
|
|||
|
IN PFILE_OBJECT FileObject,
|
|||
|
IN BOOLEAN Wait,
|
|||
|
IN OUT PFILE_BASIC_INFORMATION Buffer,
|
|||
|
OUT PIO_STATUS_BLOCK IoStatus,
|
|||
|
IN PDEVICE_OBJECT DeviceObject
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine is for the fast query call for basic file information.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
FileObject - Supplies the file object used in this operation
|
|||
|
|
|||
|
Wait - Indicates if we are allowed to wait for the information
|
|||
|
|
|||
|
Buffer - Supplies the output buffer to receive the basic information
|
|||
|
|
|||
|
IoStatus - Receives the final status of the operation
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
BOOLEAN - TRUE if the operation succeeded and FALSE if the caller
|
|||
|
needs to take the long route.
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
BOOLEAN Results = FALSE;
|
|||
|
PFCB Fcb = (PFCB)(FileObject->FsContext);
|
|||
|
PFOBX Fobx = (PFOBX)(FileObject->FsContext2);
|
|||
|
NODE_TYPE_CODE TypeOfOpen = NodeType(Fcb);
|
|||
|
|
|||
|
BOOLEAN FcbAcquired = FALSE;
|
|||
|
|
|||
|
PAGED_CODE();
|
|||
|
|
|||
|
//
|
|||
|
// Determine the type of open for the input file object and only accept
|
|||
|
// the user file or directory open
|
|||
|
//
|
|||
|
|
|||
|
if ((TypeOfOpen != RDBSS_NTC_STORAGE_TYPE_FILE) &&
|
|||
|
(TypeOfOpen != RDBSS_NTC_STORAGE_TYPE_DIRECTORY)) {
|
|||
|
|
|||
|
return Results;
|
|||
|
}
|
|||
|
|
|||
|
FsRtlEnterFileSystem();
|
|||
|
|
|||
|
//
|
|||
|
// Get access to the Fcb but only if it is not the paging file
|
|||
|
//
|
|||
|
|
|||
|
if (!FlagOn( Fcb->FcbState, FCB_STATE_PAGING_FILE )) {
|
|||
|
|
|||
|
if (!ExAcquireResourceSharedLite( Fcb->Header.Resource, Wait )) {
|
|||
|
|
|||
|
FsRtlExitFileSystem();
|
|||
|
return Results;
|
|||
|
}
|
|||
|
|
|||
|
FcbAcquired = TRUE;
|
|||
|
}
|
|||
|
|
|||
|
try {
|
|||
|
|
|||
|
//
|
|||
|
// Set it to indicate that the query is a normal file.
|
|||
|
// Later we might overwrite the attribute.
|
|||
|
//
|
|||
|
|
|||
|
Buffer->FileAttributes = FILE_ATTRIBUTE_NORMAL;
|
|||
|
|
|||
|
//
|
|||
|
// If the fcb is not the root dcb then we will fill in the
|
|||
|
// buffer otherwise it is all setup for us.
|
|||
|
//
|
|||
|
|
|||
|
if (NodeType(Fcb) != RDBSS_NTC_ROOT_DCB) {
|
|||
|
|
|||
|
//
|
|||
|
// Extract the data and fill in the non zero fields of the output
|
|||
|
// buffer
|
|||
|
//
|
|||
|
|
|||
|
Buffer->LastWriteTime = Fcb->LastWriteTime;
|
|||
|
Buffer->ChangeTime = Fcb->LastChangeTime;
|
|||
|
Buffer->CreationTime = Fcb->CreationTime;
|
|||
|
Buffer->LastAccessTime = Fcb->LastAccessTime;
|
|||
|
|
|||
|
//
|
|||
|
// Zero out the field we don't support.
|
|||
|
//
|
|||
|
|
|||
|
Buffer->ChangeTime = RxLargeZero;
|
|||
|
|
|||
|
if (Fcb->Attributes != 0) {
|
|||
|
|
|||
|
Buffer->FileAttributes = Fcb->Attributes;
|
|||
|
|
|||
|
} else {
|
|||
|
|
|||
|
Buffer->FileAttributes = FILE_ATTRIBUTE_NORMAL;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
} else {
|
|||
|
|
|||
|
Buffer->FileAttributes = FILE_ATTRIBUTE_DIRECTORY;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// If the temporary flag is set, then set it in the buffer.
|
|||
|
//
|
|||
|
|
|||
|
if (FlagOn( Fcb->FcbState, FCB_STATE_TEMPORARY )) {
|
|||
|
|
|||
|
SetFlag( Buffer->FileAttributes, FILE_ATTRIBUTE_TEMPORARY );
|
|||
|
}
|
|||
|
|
|||
|
IoStatus->Status = STATUS_SUCCESS;
|
|||
|
IoStatus->Information = sizeof(FILE_BASIC_INFORMATION);
|
|||
|
|
|||
|
Results = TRUE;
|
|||
|
|
|||
|
} finally {
|
|||
|
|
|||
|
if (FcbAcquired) { ExReleaseResourceLite( Fcb->Header.Resource ); }
|
|||
|
|
|||
|
FsRtlExitFileSystem();
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// And return to our caller
|
|||
|
//
|
|||
|
|
|||
|
return Results;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
BOOLEAN
|
|||
|
RxFastQueryStdInfo (
|
|||
|
IN PFILE_OBJECT FileObject,
|
|||
|
IN BOOLEAN Wait,
|
|||
|
IN OUT PFILE_STANDARD_INFORMATION Buffer,
|
|||
|
OUT PIO_STATUS_BLOCK IoStatus,
|
|||
|
IN PDEVICE_OBJECT DeviceObject
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine is for the fast query call for standard file information.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
FileObject - Supplies the file object used in this operation
|
|||
|
|
|||
|
Wait - Indicates if we are allowed to wait for the information
|
|||
|
|
|||
|
Buffer - Supplies the output buffer to receive the basic information
|
|||
|
|
|||
|
IoStatus - Receives the final status of the operation
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
BOOLEAN - TRUE if the operation succeeded and FALSE if the caller
|
|||
|
needs to take the long route.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
BOOLEAN Results = FALSE;
|
|||
|
|
|||
|
PFCB Fcb = (PFCB)(FileObject->FsContext);
|
|||
|
PFOBX Fobx = (PFOBX)(FileObject->FsContext2);
|
|||
|
NODE_TYPE_CODE TypeOfOpen = NodeType(Fcb);
|
|||
|
|
|||
|
BOOLEAN FcbAcquired = FALSE;
|
|||
|
|
|||
|
PAGED_CODE();
|
|||
|
|
|||
|
//
|
|||
|
// Determine the type of open for the input file object and only accept
|
|||
|
// the user file or directory open
|
|||
|
//
|
|||
|
|
|||
|
if ((TypeOfOpen != RDBSS_NTC_STORAGE_TYPE_FILE) &&
|
|||
|
(TypeOfOpen != RDBSS_NTC_STORAGE_TYPE_DIRECTORY)) {
|
|||
|
|
|||
|
return Results;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Get access to the Fcb but only if it is not the paging file
|
|||
|
//
|
|||
|
|
|||
|
FsRtlEnterFileSystem();
|
|||
|
|
|||
|
if (!FlagOn( Fcb->FcbState, FCB_STATE_PAGING_FILE )) {
|
|||
|
|
|||
|
if (!ExAcquireResourceSharedLite( Fcb->Header.Resource, Wait )) {
|
|||
|
|
|||
|
FsRtlExitFileSystem();
|
|||
|
return Results;
|
|||
|
}
|
|||
|
|
|||
|
FcbAcquired = TRUE;
|
|||
|
}
|
|||
|
|
|||
|
try {
|
|||
|
|
|||
|
Buffer->NumberOfLinks = 1;
|
|||
|
Buffer->DeletePending = BooleanFlagOn( Fcb->FcbState, FCB_STATE_DELETE_ON_CLOSE );
|
|||
|
|
|||
|
//
|
|||
|
// Case on whether this is a file or a directory, and extract
|
|||
|
// the information and fill in the fcb/dcb specific parts
|
|||
|
// of the output buffer.
|
|||
|
//
|
|||
|
|
|||
|
if (NodeType(Fcb) == RDBSS_NTC_FCB) {
|
|||
|
|
|||
|
//
|
|||
|
// If we don't alread know the allocation size, we cannot look
|
|||
|
// it up in the fast path.
|
|||
|
//
|
|||
|
|
|||
|
if (Fcb->Header.AllocationSize.LowPart == 0xffffffff) {
|
|||
|
|
|||
|
try_return( Results );
|
|||
|
}
|
|||
|
|
|||
|
Buffer->AllocationSize = Fcb->Header.AllocationSize;
|
|||
|
Buffer->EndOfFile = Fcb->Header.FileSize;
|
|||
|
|
|||
|
Buffer->Directory = FALSE;
|
|||
|
|
|||
|
} else {
|
|||
|
|
|||
|
Buffer->AllocationSize = RxLargeZero;
|
|||
|
Buffer->EndOfFile = RxLargeZero;
|
|||
|
|
|||
|
Buffer->Directory = TRUE;
|
|||
|
}
|
|||
|
|
|||
|
IoStatus->Status = STATUS_SUCCESS;
|
|||
|
IoStatus->Information = sizeof(FILE_STANDARD_INFORMATION);
|
|||
|
|
|||
|
Results = TRUE;
|
|||
|
|
|||
|
try_exit: NOTHING;
|
|||
|
} finally {
|
|||
|
|
|||
|
if (FcbAcquired) { ExReleaseResourceLite( Fcb->Header.Resource ); }
|
|||
|
|
|||
|
FsRtlExitFileSystem();
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// And return to our caller
|
|||
|
//
|
|||
|
|
|||
|
return Results;
|
|||
|
}
|
|||
|
|
|||
|
|