542 lines
15 KiB
C
542 lines
15 KiB
C
//+----------------------------------------------------------------------------
|
||
//
|
||
// File: VOLINFO.C
|
||
//
|
||
// Contents: This module implements the volume information routines for
|
||
// Dfs called by the dispatch driver.
|
||
//
|
||
// Functions: DfsFsdQueryVolumeInformation
|
||
// DfsFspQueryVolumeInformation
|
||
// DfsCommonQueryVolumeInformation
|
||
// DfsFsdSetVolumeInformation
|
||
// DfsFspSetVolumeInformation
|
||
// DfsCommonSetVolumeInformation
|
||
//
|
||
// Notes: The Query information call is a candidate for directly
|
||
// passing through via DfsVolumePassThrough. We'll keep
|
||
// the entry point around for now as a convenient place
|
||
// for breakpointing and tracing volume information calls.
|
||
//
|
||
// History: 12 Nov 1991 AlanW Created from CDFS souce.
|
||
//
|
||
//-----------------------------------------------------------------------------
|
||
|
||
|
||
#include "dfsprocs.h"
|
||
#include "mupwml.h"
|
||
|
||
//
|
||
// The local debug trace level
|
||
//
|
||
|
||
#define Dbg (DEBUG_TRACE_VOLINFO)
|
||
|
||
//
|
||
// Local procedure prototypes
|
||
//
|
||
|
||
NTSTATUS
|
||
DfsCommonQueryVolumeInformation (
|
||
IN PIRP_CONTEXT IrpContext,
|
||
IN PIRP Irp
|
||
);
|
||
|
||
NTSTATUS
|
||
DfsCommonSetVolumeInformation (
|
||
IN PIRP_CONTEXT IrpContext,
|
||
IN PIRP Irp
|
||
);
|
||
|
||
#define DfsSetFsLabelInfo(irpc,pvcb,pbuf) (STATUS_ACCESS_DENIED)
|
||
|
||
|
||
#ifdef ALLOC_PRAGMA
|
||
#pragma alloc_text( PAGE, DfsFsdQueryVolumeInformation )
|
||
#pragma alloc_text( PAGE, DfsFspQueryVolumeInformation )
|
||
#pragma alloc_text( PAGE, DfsCommonQueryVolumeInformation )
|
||
#pragma alloc_text( PAGE, DfsFsdSetVolumeInformation )
|
||
#pragma alloc_text( PAGE, DfsFspSetVolumeInformation )
|
||
#pragma alloc_text( PAGE, DfsCommonSetVolumeInformation )
|
||
#endif // ALLOC_PRAGMA
|
||
|
||
|
||
//+-------------------------------------------------------------------
|
||
//
|
||
// Function: DfsFsdQueryVolumeInformation, public
|
||
//
|
||
// Synopsis: This routine implements the Fsd part of the
|
||
// NtQueryVolumeInformation API call.
|
||
//
|
||
// Arguments: [DeviceObject] -- Supplies the device object where the file
|
||
// being queried exists.
|
||
// [Irp] -- Supplies the Irp being processed.
|
||
//
|
||
// Returns: NTSTATUS - The FSD status for the Irp.
|
||
//
|
||
//--------------------------------------------------------------------
|
||
|
||
NTSTATUS
|
||
DfsFsdQueryVolumeInformation (
|
||
IN PDEVICE_OBJECT DeviceObject,
|
||
IN PIRP Irp
|
||
) {
|
||
NTSTATUS Status;
|
||
PIRP_CONTEXT IrpContext;
|
||
|
||
DfsDbgTrace(+1, Dbg, "DfsFsdQueryVolumeInformation: Entered\n", 0);
|
||
|
||
if (DeviceObject->DeviceType == FILE_DEVICE_MULTI_UNC_PROVIDER) {
|
||
DfsCompleteRequest( NULL, Irp, STATUS_INVALID_DEVICE_REQUEST );
|
||
DfsDbgTrace(-1, Dbg, "DfsFsdQueryVolumeInformation - Mup file\n", 0);
|
||
return( STATUS_INVALID_DEVICE_REQUEST );
|
||
}
|
||
|
||
if (DeviceObject->DeviceType == FILE_DEVICE_DFS_VOLUME) {
|
||
Status = DfsVolumePassThrough(DeviceObject, Irp);
|
||
DfsDbgTrace(-1, Dbg, "DfsFsdQueryVolumeInformation: Exit -> %08x\n",
|
||
ULongToPtr(Status) );
|
||
return Status;
|
||
}
|
||
|
||
//
|
||
// Call the common query routine, with blocking allowed if synchronous
|
||
//
|
||
|
||
FsRtlEnterFileSystem();
|
||
|
||
try {
|
||
|
||
IrpContext = DfsCreateIrpContext( Irp, CanFsdWait( Irp ) );
|
||
if (IrpContext == NULL)
|
||
ExRaiseStatus(STATUS_INSUFFICIENT_RESOURCES);
|
||
Status = DfsCommonQueryVolumeInformation( IrpContext, Irp );
|
||
|
||
} except(DfsExceptionFilter( IrpContext, GetExceptionCode(), GetExceptionInformation() )) {
|
||
|
||
//
|
||
// We had some trouble trying to perform the requested
|
||
// operation, so we'll abort the I/O request with
|
||
// the error status that we get back from the
|
||
// execption code
|
||
//
|
||
|
||
Status = DfsProcessException( IrpContext, Irp, GetExceptionCode() );
|
||
}
|
||
|
||
FsRtlExitFileSystem();
|
||
|
||
//
|
||
// And return to our caller
|
||
//
|
||
|
||
DfsDbgTrace(-1, Dbg, "DfsFsdQueryVolumeInformation: Exit -> %08x\n",
|
||
ULongToPtr(Status) );
|
||
|
||
return Status;
|
||
|
||
UNREFERENCED_PARAMETER( DeviceObject );
|
||
}
|
||
|
||
|
||
//+-------------------------------------------------------------------
|
||
//
|
||
// Function: DfsFspQueryVolumeInformation, public
|
||
//
|
||
// Synopsis: This routine implements the FSP part of the
|
||
// NtQueryVolumeInformation API call.
|
||
//
|
||
// Arguments: [IrpContext] -- the IRP_CONTEXT for the request
|
||
// [Irp] -- Supplies the Irp being processed.
|
||
//
|
||
// Returns: Nothing
|
||
//
|
||
//--------------------------------------------------------------------
|
||
|
||
VOID
|
||
DfsFspQueryVolumeInformation (
|
||
IN PIRP_CONTEXT IrpContext,
|
||
IN PIRP Irp
|
||
)
|
||
{
|
||
DfsDbgTrace(+1, Dbg, "DfsFspQueryVolumeInformation: Entered\n", 0);
|
||
|
||
//
|
||
// Call the common query routine.
|
||
//
|
||
|
||
(VOID)DfsCommonQueryVolumeInformation( IrpContext, Irp );
|
||
|
||
//
|
||
// And return to our caller
|
||
//
|
||
|
||
DfsDbgTrace(-1, Dbg, "DfsFspQueryVolumeInformation: Exit -> VOID\n", 0);
|
||
|
||
return;
|
||
}
|
||
|
||
|
||
//+-------------------------------------------------------------------
|
||
//
|
||
// Function: DfsCommonQueryVolumeInformation, private
|
||
//
|
||
// Synopsis: This is the common routine for querying volume information
|
||
// called by both the FSD and FSP threads.
|
||
//
|
||
// Arguments: [IrpContext] -- Supplies the context block for the IRP
|
||
// [Irp] -- Supplies the IRP being processed
|
||
//
|
||
// Returns: NTSTATUS - The return status for the operation
|
||
//
|
||
//--------------------------------------------------------------------
|
||
|
||
NTSTATUS
|
||
DfsCommonQueryVolumeInformation (
|
||
IN PIRP_CONTEXT IrpContext,
|
||
IN PIRP Irp
|
||
) {
|
||
NTSTATUS Status;
|
||
PIO_STACK_LOCATION IrpSp;
|
||
PIO_STACK_LOCATION NextIrpSp;
|
||
PFILE_OBJECT FileObject;
|
||
|
||
PDFS_VCB Vcb;
|
||
PDFS_FCB Fcb;
|
||
|
||
ULONG Length;
|
||
FS_INFORMATION_CLASS FsInformationClass;
|
||
PVOID Buffer;
|
||
|
||
TYPE_OF_OPEN TypeOfOpen;
|
||
|
||
//
|
||
// Get the current stack location
|
||
//
|
||
|
||
IrpSp = IoGetCurrentIrpStackLocation( Irp );
|
||
FileObject = IrpSp->FileObject;
|
||
|
||
DfsDbgTrace(+1, Dbg, "DfsCommonQueryVolumeInformation: Entered\n", 0);
|
||
DfsDbgTrace( 0, Dbg, "Irp = %08x\n", Irp );
|
||
DfsDbgTrace( 0, Dbg, "->Length = %08x\n", ULongToPtr(IrpSp->Parameters.QueryVolume.Length) );
|
||
DfsDbgTrace( 0, Dbg, "->FsInformationClass = %08x\n", IrpSp->Parameters.QueryVolume.FsInformationClass);
|
||
DfsDbgTrace( 0, Dbg, "->Buffer = %08x\n", Irp->AssociatedIrp.SystemBuffer);
|
||
|
||
//
|
||
// Reference our input parameters to make things easier
|
||
//
|
||
|
||
Length = IrpSp->Parameters.QueryVolume.Length;
|
||
FsInformationClass = IrpSp->Parameters.QueryVolume.FsInformationClass;
|
||
Buffer = Irp->AssociatedIrp.SystemBuffer;
|
||
|
||
//
|
||
// Decode the file object to get the Vcb
|
||
//
|
||
|
||
TypeOfOpen = DfsDecodeFileObject( IrpSp->FileObject, &Vcb, &Fcb);
|
||
|
||
try {
|
||
|
||
Status = STATUS_INVALID_PARAMETER;
|
||
|
||
//
|
||
// Case on the type of open.
|
||
//
|
||
|
||
switch (TypeOfOpen) {
|
||
|
||
default:
|
||
DfsDbgTrace(0, Dbg,
|
||
"DfsCommonQueryVolumeInfo: Unknown open type\n", 0);
|
||
|
||
invalid:
|
||
// NOTE: FALL THROUGH
|
||
case FilesystemDeviceOpen:
|
||
DfsCompleteRequest( IrpContext, Irp, STATUS_INVALID_DEVICE_REQUEST );
|
||
Status = STATUS_INVALID_DEVICE_REQUEST;
|
||
break;
|
||
|
||
case LogicalRootDeviceOpen:
|
||
DfsDbgTrace(0, Dbg,
|
||
"DfsCommonQueryVolumeInfo: Logical root open\n", 0);
|
||
goto invalid;
|
||
|
||
case RedirectedFileOpen:
|
||
|
||
//
|
||
// Nothing special is done base on the information class.
|
||
// We simply pass each request through to the underlying
|
||
// file system and let it handle the request.
|
||
//
|
||
|
||
//
|
||
// Copy the stack from one to the next...
|
||
//
|
||
NextIrpSp = IoGetNextIrpStackLocation(Irp);
|
||
(*NextIrpSp) = (*IrpSp);
|
||
|
||
IoSetCompletionRoutine( Irp,
|
||
NULL,
|
||
NULL,
|
||
FALSE,
|
||
FALSE,
|
||
FALSE);
|
||
|
||
//
|
||
// Call the next device in the chain
|
||
//
|
||
|
||
Status = IoCallDriver( Fcb->TargetDevice, Irp );
|
||
MUP_TRACE_ERROR_HIGH(Status, ALL_ERROR, DfsCommonQueryVolumeInformation_Error_IoCallDriver,
|
||
LOGSTATUS(Status)
|
||
LOGPTR(Irp)
|
||
LOGPTR(FileObject));
|
||
//
|
||
// The IRP will be completed by the called driver. We have
|
||
// no need for the IrpContext in the completion routine.
|
||
//
|
||
|
||
DfsDeleteIrpContext(IrpContext);
|
||
IrpContext = NULL;
|
||
Irp = NULL;
|
||
break;
|
||
}
|
||
|
||
} finally {
|
||
|
||
DfsDbgTrace(-1, Dbg, "DfsCommonQueryVolumeInformation: Exit -> %08x\n",
|
||
ULongToPtr(Status) );
|
||
}
|
||
|
||
return Status;
|
||
}
|
||
|
||
|
||
//+-------------------------------------------------------------------
|
||
//
|
||
// Function: DfsFsdSetVolumeInformation, public
|
||
//
|
||
// Synopsis: This routine implements the Fsd part of the
|
||
// NtSetVolumeInformation API call.
|
||
//
|
||
// Arguments: [DeviceObject] -- Supplies the device object where the file
|
||
// being queried exists.
|
||
// [Irp] -- Supplies the Irp being processed.
|
||
//
|
||
// Returns: NTSTATUS - The FSD status for the Irp.
|
||
//
|
||
//--------------------------------------------------------------------
|
||
|
||
NTSTATUS
|
||
DfsFsdSetVolumeInformation (
|
||
IN PDEVICE_OBJECT DeviceObject,
|
||
IN PIRP Irp
|
||
) {
|
||
NTSTATUS Status;
|
||
PIRP_CONTEXT IrpContext;
|
||
|
||
DfsDbgTrace(+1, Dbg, "DfsFsdSetVolumeInformation: Entered\n", 0);
|
||
|
||
if (DeviceObject->DeviceType == FILE_DEVICE_MULTI_UNC_PROVIDER) {
|
||
DfsCompleteRequest( NULL, Irp, STATUS_INVALID_DEVICE_REQUEST );
|
||
DfsDbgTrace(-1, Dbg, "DfsFsdSetVolumeInformation - Mup file\n", 0);
|
||
return( STATUS_INVALID_DEVICE_REQUEST );
|
||
}
|
||
|
||
if (DeviceObject->DeviceType == FILE_DEVICE_DFS_VOLUME) {
|
||
Status = DfsVolumePassThrough(DeviceObject, Irp);
|
||
DfsDbgTrace(-1, Dbg, "DfsFsdSetVolumeInformation: Exit -> %08x\n",
|
||
ULongToPtr(Status) );
|
||
return Status;
|
||
}
|
||
|
||
//
|
||
// Call the common Set routine, with blocking allowed if synchronous
|
||
//
|
||
|
||
FsRtlEnterFileSystem();
|
||
|
||
try {
|
||
|
||
IrpContext = DfsCreateIrpContext( Irp, CanFsdWait( Irp ) );
|
||
if (IrpContext == NULL)
|
||
ExRaiseStatus(STATUS_INSUFFICIENT_RESOURCES);
|
||
Status = DfsCommonSetVolumeInformation( IrpContext, Irp );
|
||
|
||
} except(DfsExceptionFilter( IrpContext, GetExceptionCode(), GetExceptionInformation() )) {
|
||
|
||
//
|
||
// We had some trouble trying to perform the requested
|
||
// operation, so we'll abort the I/O request with
|
||
// the error status that we get back from the
|
||
// execption code
|
||
//
|
||
|
||
Status = DfsProcessException( IrpContext, Irp, GetExceptionCode() );
|
||
}
|
||
|
||
FsRtlExitFileSystem();
|
||
|
||
//
|
||
// And return to our caller
|
||
//
|
||
|
||
DfsDbgTrace(-1, Dbg, "DfsFsdSetVolumeInformation: Exit -> %08x\n",
|
||
ULongToPtr(Status) );
|
||
|
||
return Status;
|
||
|
||
UNREFERENCED_PARAMETER( DeviceObject );
|
||
}
|
||
|
||
|
||
//+-------------------------------------------------------------------
|
||
//
|
||
// Function: DfsFspSetVolumeInformation, public
|
||
//
|
||
// Synopsis: This routine implements the FSP part of the
|
||
// NtSetVolumeInformation API call.
|
||
//
|
||
// Arguments: [IrpContext] -- the IRP_CONTEXT for the request
|
||
// [Irp] -- Supplies the Irp being processed.
|
||
//
|
||
// Returns: Nothing
|
||
//
|
||
//--------------------------------------------------------------------
|
||
|
||
VOID
|
||
DfsFspSetVolumeInformation (
|
||
IN PIRP_CONTEXT IrpContext,
|
||
IN PIRP Irp
|
||
)
|
||
{
|
||
DfsDbgTrace(+1, Dbg, "DfsFspSetVolumeInformation: Entered\n", 0);
|
||
|
||
//
|
||
// Call the common Set routine.
|
||
//
|
||
|
||
(VOID)DfsCommonSetVolumeInformation( IrpContext, Irp );
|
||
|
||
//
|
||
// And return to our caller
|
||
//
|
||
|
||
DfsDbgTrace(-1, Dbg, "DfsFspSetVolumeInformation: Exit -> VOID\n", 0);
|
||
|
||
return;
|
||
}
|
||
|
||
|
||
//+-------------------------------------------------------------------
|
||
//
|
||
// Function: DfsCommonSetVolumeInformation, private
|
||
//
|
||
// Synopsis: This is the common routine for Seting volume information
|
||
// called by both the FSD and FSP threads.
|
||
//
|
||
// Arguments: [IrpContext] -- Supplies the context block for the IRP
|
||
// [Irp] -- Supplies the IRP being processed
|
||
//
|
||
// Returns: NTSTATUS - The return status for the operation
|
||
//
|
||
//--------------------------------------------------------------------
|
||
|
||
NTSTATUS
|
||
DfsCommonSetVolumeInformation (
|
||
IN PIRP_CONTEXT IrpContext,
|
||
IN PIRP Irp
|
||
) {
|
||
NTSTATUS Status;
|
||
PIO_STACK_LOCATION IrpSp;
|
||
|
||
PDFS_VCB Vcb;
|
||
PDFS_FCB Fcb;
|
||
|
||
FS_INFORMATION_CLASS FsInformationClass;
|
||
PVOID Buffer;
|
||
|
||
TYPE_OF_OPEN TypeOfOpen;
|
||
|
||
//
|
||
// Get the current stack location
|
||
//
|
||
|
||
IrpSp = IoGetCurrentIrpStackLocation( Irp );
|
||
|
||
|
||
DfsDbgTrace(+1, Dbg, "DfsCommonSetVolumeInformation: Entered\n", 0);
|
||
DfsDbgTrace( 0, Dbg, "Irp = %08x\n", Irp );
|
||
DfsDbgTrace( 0, Dbg, "->Length = %08x\n", ULongToPtr(IrpSp->Parameters.SetVolume.Length) );
|
||
DfsDbgTrace( 0, Dbg, "->FsInformationClass = %08x\n", IrpSp->Parameters.SetVolume.FsInformationClass);
|
||
DfsDbgTrace( 0, Dbg, "->Buffer = %08x\n", Irp->AssociatedIrp.SystemBuffer);
|
||
|
||
//
|
||
// Reference our input parameters to make things easier
|
||
//
|
||
|
||
FsInformationClass = IrpSp->Parameters.SetVolume.FsInformationClass;
|
||
Buffer = Irp->AssociatedIrp.SystemBuffer;
|
||
|
||
//
|
||
// Decode the file object to get the Vcb
|
||
//
|
||
|
||
TypeOfOpen = DfsDecodeFileObject( IrpSp->FileObject, &Vcb, &Fcb);
|
||
|
||
try {
|
||
|
||
Status = STATUS_INVALID_PARAMETER;
|
||
|
||
//
|
||
// Case on the type of open.
|
||
//
|
||
|
||
switch (TypeOfOpen) {
|
||
|
||
default:
|
||
DfsDbgTrace(0, Dbg, "DfsCommonSetVolumeInfo: Unknown open type\n", 0);
|
||
|
||
// NOTE: FALL THROUGH
|
||
case FilesystemDeviceOpen:
|
||
Status = STATUS_INVALID_DEVICE_REQUEST;
|
||
break;
|
||
|
||
case LogicalRootDeviceOpen:
|
||
case RedirectedFileOpen:
|
||
|
||
//
|
||
// Based on the information class we'll do different actions.
|
||
// Each of the procedures that we're calling fills up the output
|
||
// buffer if possible and returns true if it successfully filled
|
||
// the buffer and false if it couldn't wait for any I/O to
|
||
// complete.
|
||
//
|
||
|
||
switch (FsInformationClass) {
|
||
|
||
case FileFsLabelInformation:
|
||
Status = DfsSetFsLabelInfo( IrpContext, Vcb, Buffer);
|
||
break;
|
||
|
||
default:
|
||
DfsDbgTrace(0, Dbg, "DfsCommonSetVolumeInfo: Unknown InformationClass\n", 0);
|
||
Status = STATUS_INVALID_DEVICE_REQUEST;
|
||
break;
|
||
}
|
||
}
|
||
|
||
} finally {
|
||
|
||
if (!AbnormalTermination()) {
|
||
DfsCompleteRequest( IrpContext, Irp, Status );
|
||
}
|
||
|
||
DfsDbgTrace(-1, Dbg, "DfsCommonSetVolumeInformation: Exit -> %08x\n",
|
||
ULongToPtr(Status) );
|
||
}
|
||
|
||
return Status;
|
||
}
|