|
|
//+-------------------------------------------------------------------------
//
// Copyright (C) 1992, Microsoft Corporation.
//
// File: FILEINFO.C
//
// Contents: This module implements the File Information routines for
// Dfs called by the dispatch driver.
//
// Functions: DfsFsdSetInformation - FSD entry point for NtSetInformationFile
// DfsFspSetInformation - FSP entry point for NtSetInformationFile
// DfsCommonSetInformation - Implement SetInformationFile for DFS
// DfsSetRenameInfo - Takes care of rename restrictions.
// DfsSetDispositionInfo - Enforces Deletion of StgId restrictions.
//
// Notes: No query information routines are presently used.
// These requests are passed directly through to a redirected
// file (if one exists).
//
// History: 30 Jun 1992 AlanW Created from FastFAT source.
// 09 Feb 1994 SudK Added Rename/Delete restrictions.
//
//--------------------------------------------------------------------------
#include "dfsprocs.h"
#include "dnr.h"
#include "mupwml.h"
//
// The local debug trace level
//
#define Dbg (DEBUG_TRACE_FILEINFO)
//
// Local procedure prototypes
//
NTSTATUS DfsCommonSetInformation ( IN PIRP_CONTEXT IrpContext, IN PIRP Irp );
NTSTATUS DfsSetDispositionInfo ( IN PIRP Irp );
NTSTATUS DfsSetRenameInfo ( IN PIRP Irp, IN PDFS_VCB Vcb, IN PDFS_FCB Fcb );
#ifdef ALLOC_PRAGMA
#pragma alloc_text ( PAGE, DfsFsdQueryInformation )
#pragma alloc_text ( PAGE, DfsFsdSetInformation )
#pragma alloc_text ( PAGE, DfsFspSetInformation )
#pragma alloc_text ( PAGE, DfsCommonSetInformation )
#pragma alloc_text ( PAGE, DfsSetDispositionInfo )
#pragma alloc_text ( PAGE, DfsSetRenameInfo )
#endif // ALLOC_PRAGMA
//+----------------------------------------------------------------------------
//
// Function: DfsFsdQueryInformation, public
//
// Synopsis: This routine implements the FSD part of the
// NtQueryInformationFile API call
//
// Arguments: [DeviceObject] -- Supplies the volume device object where
// the file being queried exists.
// [Irp] -- Supplies the Irp being processed
//
// Returns: NTSTATUS - The FSD status for the Irp.
//
//-----------------------------------------------------------------------------
NTSTATUS DfsFsdQueryInformation ( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) { NTSTATUS Status = STATUS_SUCCESS; PIO_STACK_LOCATION IrpSp; FILE_INFORMATION_CLASS FileInformationClass; PFILE_NAME_INFORMATION FileNameInfo; UNICODE_STRING FileNameToUse; ULONG BufferLength, BytesToCopy; PFILE_OBJECT FileObject; TYPE_OF_OPEN TypeOfOpen; PDFS_VCB Vcb; PDFS_FCB Fcb; BOOLEAN completeIrp;
ASSERT(ARGUMENT_PRESENT(DeviceObject)); ASSERT(ARGUMENT_PRESENT(Irp));
DfsDbgTrace(+1, Dbg, "DfsFsdQueryInformation - Entered\n", 0);
IrpSp = IoGetCurrentIrpStackLocation( Irp );
FileInformationClass = IrpSp->Parameters.QueryFile.FileInformationClass;
DfsDbgTrace(0, Dbg, "InfoLevel = %d\n", FileInformationClass);
if (DeviceObject->DeviceType == FILE_DEVICE_MULTI_UNC_PROVIDER || DeviceObject->DeviceType == FILE_DEVICE_DFS_FILE_SYSTEM) {
DfsCompleteRequest( NULL, Irp, STATUS_INVALID_DEVICE_REQUEST );
DfsDbgTrace(-1, Dbg, "DfsFsdQueryInformation - Mup/File System\n", 0);
return( STATUS_INVALID_DEVICE_REQUEST );
}
ASSERT( DeviceObject->DeviceType == FILE_DEVICE_DFS );
if (FileInformationClass != FileNameInformation && FileInformationClass != FileAlternateNameInformation) {
Status = DfsVolumePassThrough(DeviceObject, Irp);
DfsDbgTrace(-1, Dbg, "DfsFsdQueryInformation: Exit -> %08lx\n", ULongToPtr(Status) );
return Status;
}
FileObject = IrpSp->FileObject;
//
// Decode the file object. Remember that there need not be an Fcb always.
//
TypeOfOpen = DfsDecodeFileObject( FileObject, &Vcb, &Fcb);
if (Fcb != NULL) {
completeIrp = TRUE;
switch (TypeOfOpen) {
default: //
// We cannot get info on a device open
//
Status = STATUS_INVALID_PARAMETER;
break;
case RedirectedFileOpen: case UnknownOpen:
FileNameInfo = (PFILE_NAME_INFORMATION) Irp->AssociatedIrp.SystemBuffer;
BufferLength = IrpSp->Parameters.QueryFile.Length;
if (FileInformationClass == FileAlternateNameInformation) FileNameToUse = Fcb->AlternateFileName; else FileNameToUse = Fcb->FullFileName;
if (BufferLength < sizeof(FILE_NAME_INFORMATION)) {
Status = STATUS_INVALID_PARAMETER;
}
if (FileNameToUse.Length == 0) {
ASSERT(FileInformationClass == FileAlternateNameInformation);
Status = DfsVolumePassThrough(DeviceObject, Irp);
completeIrp = FALSE;
} else { BufferLength -= FIELD_OFFSET(FILE_NAME_INFORMATION, FileName[0]);
if (BufferLength < FileNameToUse.Length) { BytesToCopy = BufferLength; Status = STATUS_BUFFER_OVERFLOW; BufferLength = 0; } else { BytesToCopy = FileNameToUse.Length; BufferLength -= BytesToCopy; } FileNameInfo->FileNameLength = FileNameToUse.Length;
if (BytesToCopy > 0) { RtlCopyMemory( (PVOID) &FileNameInfo->FileName, (PVOID) FileNameToUse.Buffer, BytesToCopy); }
Irp->IoStatus.Information = IrpSp->Parameters.QueryFile.Length - BufferLength; }
break; }
if (completeIrp) DfsCompleteRequest( NULL, Irp, Status );
} else {
Status = STATUS_INVALID_PARAMETER; DfsCompleteRequest( NULL, Irp, Status );
}
//
// And return to our caller
//
DfsDbgTrace(-1, Dbg, "DfsFsdQueryInformation -> %08lx\n", ULongToPtr(Status) );
return Status;
}
//+-------------------------------------------------------------------
//
// Function: DfsFsdSetInformation, public
//
// Synopsis: This routine implements the FSD part of the
// NtSetInformationFile API call.
//
// Arguments: [DeviceObject] -- Supplies the volume device object where
// the file being set exists.
// [Irp] -- Supplies the Irp being processed.
//
// Returns: NTSTATUS - The FSD status for the Irp.
//
//--------------------------------------------------------------------
NTSTATUS DfsFsdSetInformation ( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp ) { NTSTATUS Status; PIRP_CONTEXT IrpContext = NULL; ASSERT(ARGUMENT_PRESENT(DeviceObject)); ASSERT(ARGUMENT_PRESENT(Irp));
DfsDbgTrace(+1, Dbg, "DfsFsdSetInformation\n", 0);
//
// 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 = DfsCommonSetInformation( 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, "DfsFsdSetInformation -> %08lx\n", ULongToPtr(Status) );
UNREFERENCED_PARAMETER( DeviceObject );
return Status; }
//+-------------------------------------------------------------------
//
// Function: DfsFspSetInformation, public
//
// Synopsis: This routine implements the FSP part of the
// NtSetInformationFile API call.
//
// Arguments: [IrpContext] -- The IRP_CONTEXT record for the operation
// [Irp] -- Supplies the Irp being processed.
//
// Returns: Nothing
//
//--------------------------------------------------------------------
VOID DfsFspSetInformation ( IN PIRP_CONTEXT IrpContext, IN PIRP Irp ) { DfsDbgTrace(+1, Dbg, "DfsFspSetInformation\n", 0);
//
// Call the common set routine. The Fsp is always allowed to block
//
(VOID)DfsCommonSetInformation( IrpContext, Irp );
//
// And return to our caller
//
DfsDbgTrace(-1, Dbg, "DfsFspSetInformation -> VOID\n", 0);
return; }
//+-------------------------------------------------------------------
//
// Function: DfsCommonSetInformation, private
//
// Synopsis: This is the common routine for setting file information called
// by both the FSD and FSP threads.
//
// Arguments: [Irp] -- Supplies the Irp being processed
//
// Returns: NTSTATUS - The return status for the operation
//
//--------------------------------------------------------------------
//
NTSTATUS DfsCommonSetInformation ( IN PIRP_CONTEXT IrpContext, IN PIRP Irp ) { NTSTATUS Status = STATUS_SUCCESS;
PIO_STACK_LOCATION IrpSp; PIO_STACK_LOCATION NextIrpSp;
PFILE_OBJECT FileObject; FILE_INFORMATION_CLASS FileInformationClass; PDEVICE_OBJECT Vdo, DeviceObject;
TYPE_OF_OPEN TypeOfOpen; PDFS_VCB Vcb; PDFS_FCB Fcb;
//
// Get the current stack location
//
IrpSp = IoGetCurrentIrpStackLocation( Irp );
DfsDbgTrace(+1, Dbg, "DfsCommonSetInformation...\n", 0); DfsDbgTrace( 0, Dbg, "Irp = %08lx\n", Irp); DfsDbgTrace( 0, Dbg, "->Length = %08lx\n", ULongToPtr(IrpSp->Parameters.SetFile.Length) ); DfsDbgTrace( 0, Dbg, "->FileInformationClass = %08lx\n", IrpSp->Parameters.SetFile.FileInformationClass); DfsDbgTrace( 0, Dbg, "->ReplaceFileObject = %08lx\n", IrpSp->Parameters.SetFile.FileObject); DfsDbgTrace( 0, Dbg, "->ReplaceIfExists = %08lx\n", IrpSp->Parameters.SetFile.ReplaceIfExists); DfsDbgTrace( 0, Dbg, "->Buffer = %08lx\n", Irp->AssociatedIrp.SystemBuffer);
//
// Reference our input parameters to make things easier
//
FileInformationClass = IrpSp->Parameters.SetFile.FileInformationClass; FileObject = IrpSp->FileObject; DeviceObject = IrpSp->DeviceObject;
if (DeviceObject->DeviceType == FILE_DEVICE_MULTI_UNC_PROVIDER) { DfsCompleteRequest( IrpContext, Irp, STATUS_INVALID_DEVICE_REQUEST ); DfsDbgTrace(-1, Dbg, "DfsCommonSetInformation - Mup file\n", 0); return( STATUS_INVALID_DEVICE_REQUEST ); }
//
// Decode the file object. Remember that there need not be an Fcb always.
//
TypeOfOpen = DfsDecodeFileObject( FileObject, &Vcb, &Fcb);
//
// Set this handle as having modified the file
//
FileObject->Flags |= FO_FILE_MODIFIED;
try {
//
// Case on the type of open we're dealing with
//
switch (TypeOfOpen) {
default:
//
// We cannot set info on a device open
//
try_return( Status = STATUS_INVALID_PARAMETER );
case RedirectedFileOpen: case UnknownOpen:
break;
}
if (Fcb == NULL) try_return( Status = STATUS_INVALID_PARAMETER );
//
// 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, DfsCommonSetInformation_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;
try_exit: NOTHING;
} finally {
DebugUnwind( DfsCommonSetInformation );
if (!AbnormalTermination()) {
DfsCompleteRequest( IrpContext, Irp, Status );
}
DfsDbgTrace(-1, Dbg, "DfsCommonSetInformation -> %08lx\n", ULongToPtr(Status) ); }
return Status; }
|