//+---------------------------------------------------------------------------- // // 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; }