windows-nt/Source/XPSP1/NT/base/fs/mup/fileinfo.c
2020-09-26 16:20:57 +08:00

489 lines
13 KiB
C
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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