mirror of
https://github.com/reactos/reactos.git
synced 2024-10-23 14:36:11 +00:00
1528 lines
49 KiB
C
1528 lines
49 KiB
C
/*
|
|
* COPYRIGHT: GNU GENERAL PUBLIC LICENSE VERSION 2
|
|
* PROJECT: ReiserFs file system driver for Windows NT/2000/XP/Vista.
|
|
* FILE: fileinfo.c
|
|
* PURPOSE:
|
|
* PROGRAMMER: Mark Piper, Matt Wu, Bo Brantén.
|
|
* HOMEPAGE:
|
|
* UPDATE HISTORY:
|
|
*/
|
|
|
|
/* INCLUDES *****************************************************************/
|
|
|
|
#include "rfsd.h"
|
|
|
|
/* GLOBALS ***************************************************************/
|
|
|
|
extern PRFSD_GLOBAL RfsdGlobal;
|
|
|
|
/* DEFINITIONS *************************************************************/
|
|
|
|
#ifdef ALLOC_PRAGMA
|
|
#pragma alloc_text(PAGE, RfsdQueryInformation)
|
|
#pragma alloc_text(PAGE, RfsdSetInformation)
|
|
#if !RFSD_READ_ONLY
|
|
#pragma alloc_text(PAGE, RfsdExpandFile)
|
|
#pragma alloc_text(PAGE, RfsdTruncateFile)
|
|
#pragma alloc_text(PAGE, RfsdSetDispositionInfo)
|
|
#pragma alloc_text(PAGE, RfsdSetRenameInfo)
|
|
#pragma alloc_text(PAGE, RfsdDeleteFile)
|
|
#endif // !RFSD_READ_ONLY
|
|
#endif
|
|
|
|
__drv_mustHoldCriticalRegion
|
|
NTSTATUS
|
|
RfsdQueryInformation (IN PRFSD_IRP_CONTEXT IrpContext)
|
|
{
|
|
PDEVICE_OBJECT DeviceObject;
|
|
NTSTATUS Status = STATUS_UNSUCCESSFUL;
|
|
PFILE_OBJECT FileObject;
|
|
PRFSD_VCB Vcb;
|
|
PRFSD_FCB Fcb = 0;
|
|
PRFSD_CCB Ccb;
|
|
PIRP Irp;
|
|
PIO_STACK_LOCATION IoStackLocation;
|
|
FILE_INFORMATION_CLASS FileInformationClass;
|
|
ULONG Length;
|
|
PVOID Buffer;
|
|
BOOLEAN FcbResourceAcquired = FALSE;
|
|
LONGLONG FileSize;
|
|
LONGLONG AllocationSize;
|
|
|
|
PAGED_CODE();
|
|
|
|
_SEH2_TRY {
|
|
|
|
ASSERT(IrpContext != NULL);
|
|
|
|
ASSERT((IrpContext->Identifier.Type == RFSDICX) &&
|
|
(IrpContext->Identifier.Size == sizeof(RFSD_IRP_CONTEXT)));
|
|
|
|
DeviceObject = IrpContext->DeviceObject;
|
|
|
|
//
|
|
// This request is not allowed on the main device object
|
|
//
|
|
if (DeviceObject == RfsdGlobal->DeviceObject) {
|
|
Status = STATUS_INVALID_DEVICE_REQUEST;
|
|
_SEH2_LEAVE;
|
|
}
|
|
|
|
FileObject = IrpContext->FileObject;
|
|
|
|
Fcb = (PRFSD_FCB) FileObject->FsContext;
|
|
|
|
ASSERT(Fcb != NULL);
|
|
|
|
//
|
|
// This request is not allowed on volumes
|
|
//
|
|
if (Fcb->Identifier.Type == RFSDVCB) {
|
|
Status = STATUS_INVALID_PARAMETER;
|
|
_SEH2_LEAVE;
|
|
}
|
|
|
|
ASSERT((Fcb->Identifier.Type == RFSDFCB) &&
|
|
(Fcb->Identifier.Size == sizeof(RFSD_FCB)));
|
|
|
|
Vcb = Fcb->Vcb;
|
|
|
|
/*
|
|
if ( !IsFlagOn(Fcb->Vcb->Flags, VCB_READ_ONLY) &&
|
|
!FlagOn(Fcb->Flags, FCB_PAGE_FILE))
|
|
*/
|
|
{
|
|
if (!ExAcquireResourceSharedLite(
|
|
&Fcb->MainResource,
|
|
IrpContext->IsSynchronous
|
|
)) {
|
|
|
|
Status = STATUS_PENDING;
|
|
_SEH2_LEAVE;
|
|
}
|
|
|
|
FcbResourceAcquired = TRUE;
|
|
}
|
|
|
|
Ccb = (PRFSD_CCB) FileObject->FsContext2;
|
|
|
|
ASSERT(Ccb != NULL);
|
|
|
|
ASSERT((Ccb->Identifier.Type == RFSDCCB) &&
|
|
(Ccb->Identifier.Size == sizeof(RFSD_CCB)));
|
|
|
|
Irp = IrpContext->Irp;
|
|
|
|
IoStackLocation = IoGetCurrentIrpStackLocation(Irp);
|
|
|
|
FileInformationClass =
|
|
IoStackLocation->Parameters.QueryFile.FileInformationClass;
|
|
|
|
Length = IoStackLocation->Parameters.QueryFile.Length;
|
|
|
|
Buffer = Irp->AssociatedIrp.SystemBuffer;
|
|
|
|
RtlZeroMemory(Buffer, Length);
|
|
|
|
FileSize = (LONGLONG) Fcb->Inode->i_size;
|
|
|
|
AllocationSize = CEILING_ALIGNED(FileSize, (ULONGLONG)Vcb->BlockSize);
|
|
|
|
switch (FileInformationClass) {
|
|
|
|
case FileBasicInformation:
|
|
{
|
|
PFILE_BASIC_INFORMATION FileBasicInformation;
|
|
|
|
if (Length < sizeof(FILE_BASIC_INFORMATION)) {
|
|
Status = STATUS_INFO_LENGTH_MISMATCH;
|
|
_SEH2_LEAVE;
|
|
}
|
|
|
|
FileBasicInformation = (PFILE_BASIC_INFORMATION) Buffer;
|
|
|
|
FileBasicInformation->CreationTime = RfsdSysTime(Fcb->Inode->i_ctime);
|
|
|
|
FileBasicInformation->LastAccessTime = RfsdSysTime(Fcb->Inode->i_atime);
|
|
|
|
FileBasicInformation->LastWriteTime = RfsdSysTime(Fcb->Inode->i_mtime);
|
|
|
|
FileBasicInformation->ChangeTime = RfsdSysTime(Fcb->Inode->i_mtime);
|
|
|
|
FileBasicInformation->FileAttributes = Fcb->RfsdMcb->FileAttr;
|
|
|
|
Irp->IoStatus.Information = sizeof(FILE_BASIC_INFORMATION);
|
|
Status = STATUS_SUCCESS;
|
|
_SEH2_LEAVE;
|
|
}
|
|
|
|
#if (_WIN32_WINNT >= 0x0500)
|
|
|
|
case FileAttributeTagInformation:
|
|
{
|
|
PFILE_ATTRIBUTE_TAG_INFORMATION FATI;
|
|
|
|
if (Length < sizeof(FILE_ATTRIBUTE_TAG_INFORMATION)) {
|
|
Status = STATUS_INFO_LENGTH_MISMATCH;
|
|
_SEH2_LEAVE;
|
|
}
|
|
|
|
FATI = (PFILE_ATTRIBUTE_TAG_INFORMATION) Buffer;
|
|
|
|
FATI->FileAttributes = Fcb->RfsdMcb->FileAttr;
|
|
FATI->ReparseTag = 0;
|
|
|
|
Irp->IoStatus.Information = sizeof(FILE_ATTRIBUTE_TAG_INFORMATION);
|
|
Status = STATUS_SUCCESS;
|
|
_SEH2_LEAVE;
|
|
}
|
|
#endif // (_WIN32_WINNT >= 0x0500)
|
|
|
|
case FileStandardInformation:
|
|
{
|
|
PFILE_STANDARD_INFORMATION FileStandardInformation;
|
|
|
|
if (Length < sizeof(FILE_STANDARD_INFORMATION)) {
|
|
Status = STATUS_INFO_LENGTH_MISMATCH;
|
|
_SEH2_LEAVE;
|
|
}
|
|
|
|
FileStandardInformation = (PFILE_STANDARD_INFORMATION) Buffer;
|
|
|
|
FileStandardInformation->AllocationSize.QuadPart = AllocationSize;
|
|
FileStandardInformation->EndOfFile.QuadPart = FileSize;
|
|
|
|
FileStandardInformation->NumberOfLinks = Fcb->Inode->i_links_count;
|
|
|
|
if (IsFlagOn(Fcb->Vcb->Flags, VCB_READ_ONLY))
|
|
FileStandardInformation->DeletePending = FALSE;
|
|
else
|
|
FileStandardInformation->DeletePending = IsFlagOn(Fcb->Flags, FCB_DELETE_PENDING);
|
|
|
|
if (Fcb->RfsdMcb->FileAttr & FILE_ATTRIBUTE_DIRECTORY) {
|
|
FileStandardInformation->Directory = TRUE;
|
|
} else {
|
|
FileStandardInformation->Directory = FALSE;
|
|
}
|
|
|
|
Irp->IoStatus.Information = sizeof(FILE_STANDARD_INFORMATION);
|
|
Status = STATUS_SUCCESS;
|
|
_SEH2_LEAVE;
|
|
}
|
|
|
|
case FileInternalInformation:
|
|
{
|
|
PFILE_INTERNAL_INFORMATION FileInternalInformation;
|
|
|
|
if (Length < sizeof(FILE_INTERNAL_INFORMATION)) {
|
|
Status = STATUS_INFO_LENGTH_MISMATCH;
|
|
_SEH2_LEAVE;
|
|
}
|
|
|
|
FileInternalInformation = (PFILE_INTERNAL_INFORMATION) Buffer;
|
|
|
|
// The "inode number"
|
|
FileInternalInformation->IndexNumber.LowPart = Fcb->RfsdMcb->Key.k_dir_id;
|
|
FileInternalInformation->IndexNumber.HighPart = Fcb->RfsdMcb->Key.k_objectid;
|
|
|
|
Irp->IoStatus.Information = sizeof(FILE_INTERNAL_INFORMATION);
|
|
Status = STATUS_SUCCESS;
|
|
_SEH2_LEAVE;
|
|
}
|
|
|
|
case FileEaInformation:
|
|
{
|
|
PFILE_EA_INFORMATION FileEaInformation;
|
|
|
|
if (Length < sizeof(FILE_EA_INFORMATION)) {
|
|
Status = STATUS_INFO_LENGTH_MISMATCH;
|
|
_SEH2_LEAVE;
|
|
}
|
|
|
|
FileEaInformation = (PFILE_EA_INFORMATION) Buffer;
|
|
|
|
// Romfs doesn't have any extended attributes
|
|
FileEaInformation->EaSize = 0;
|
|
|
|
Irp->IoStatus.Information = sizeof(FILE_EA_INFORMATION);
|
|
Status = STATUS_SUCCESS;
|
|
_SEH2_LEAVE;
|
|
}
|
|
|
|
case FileNameInformation:
|
|
{
|
|
PFILE_NAME_INFORMATION FileNameInformation;
|
|
|
|
if (Length < sizeof(FILE_NAME_INFORMATION) +
|
|
Fcb->RfsdMcb->ShortName.Length - sizeof(WCHAR)) {
|
|
Status = STATUS_INFO_LENGTH_MISMATCH;
|
|
_SEH2_LEAVE;
|
|
}
|
|
|
|
FileNameInformation = (PFILE_NAME_INFORMATION) Buffer;
|
|
|
|
FileNameInformation->FileNameLength = Fcb->RfsdMcb->ShortName.Length;
|
|
|
|
RtlCopyMemory(
|
|
FileNameInformation->FileName,
|
|
Fcb->RfsdMcb->ShortName.Buffer,
|
|
Fcb->RfsdMcb->ShortName.Length );
|
|
|
|
Irp->IoStatus.Information = sizeof(FILE_NAME_INFORMATION) +
|
|
Fcb->RfsdMcb->ShortName.Length - sizeof(WCHAR);
|
|
Status = STATUS_SUCCESS;
|
|
_SEH2_LEAVE;
|
|
}
|
|
|
|
case FilePositionInformation:
|
|
{
|
|
PFILE_POSITION_INFORMATION FilePositionInformation;
|
|
|
|
if (Length < sizeof(FILE_POSITION_INFORMATION)) {
|
|
Status = STATUS_INFO_LENGTH_MISMATCH;
|
|
_SEH2_LEAVE;
|
|
}
|
|
|
|
FilePositionInformation = (PFILE_POSITION_INFORMATION) Buffer;
|
|
|
|
FilePositionInformation->CurrentByteOffset =
|
|
FileObject->CurrentByteOffset;
|
|
|
|
Irp->IoStatus.Information = sizeof(FILE_POSITION_INFORMATION);
|
|
Status = STATUS_SUCCESS;
|
|
_SEH2_LEAVE;
|
|
}
|
|
|
|
case FileAllInformation:
|
|
{
|
|
PFILE_ALL_INFORMATION FileAllInformation;
|
|
PFILE_BASIC_INFORMATION FileBasicInformation;
|
|
PFILE_STANDARD_INFORMATION FileStandardInformation;
|
|
PFILE_INTERNAL_INFORMATION FileInternalInformation;
|
|
PFILE_EA_INFORMATION FileEaInformation;
|
|
PFILE_POSITION_INFORMATION FilePositionInformation;
|
|
PFILE_NAME_INFORMATION FileNameInformation;
|
|
|
|
if (Length < sizeof(FILE_ALL_INFORMATION)) {
|
|
Status = STATUS_INFO_LENGTH_MISMATCH;
|
|
_SEH2_LEAVE;
|
|
}
|
|
|
|
FileAllInformation = (PFILE_ALL_INFORMATION) Buffer;
|
|
|
|
FileBasicInformation =
|
|
&FileAllInformation->BasicInformation;
|
|
|
|
FileStandardInformation =
|
|
&FileAllInformation->StandardInformation;
|
|
|
|
FileInternalInformation =
|
|
&FileAllInformation->InternalInformation;
|
|
|
|
FileEaInformation =
|
|
&FileAllInformation->EaInformation;
|
|
|
|
FilePositionInformation =
|
|
&FileAllInformation->PositionInformation;
|
|
|
|
FileNameInformation =
|
|
&FileAllInformation->NameInformation;
|
|
|
|
FileBasicInformation->CreationTime = RfsdSysTime(Fcb->Inode->i_ctime);
|
|
|
|
FileBasicInformation->LastAccessTime = RfsdSysTime(Fcb->Inode->i_atime);
|
|
|
|
FileBasicInformation->LastWriteTime = RfsdSysTime(Fcb->Inode->i_mtime);
|
|
|
|
FileBasicInformation->ChangeTime = RfsdSysTime(Fcb->Inode->i_mtime);
|
|
|
|
FileBasicInformation->FileAttributes = Fcb->RfsdMcb->FileAttr;
|
|
|
|
FileStandardInformation->AllocationSize.QuadPart = AllocationSize;
|
|
|
|
FileStandardInformation->EndOfFile.QuadPart = FileSize;
|
|
|
|
FileStandardInformation->NumberOfLinks = Fcb->Inode->i_links_count;
|
|
|
|
if (IsFlagOn(Fcb->Vcb->Flags, VCB_READ_ONLY))
|
|
FileStandardInformation->DeletePending = FALSE;
|
|
else
|
|
FileStandardInformation->DeletePending = IsFlagOn(Fcb->Flags, FCB_DELETE_PENDING);
|
|
|
|
if (FlagOn(Fcb->RfsdMcb->FileAttr, FILE_ATTRIBUTE_DIRECTORY)) {
|
|
FileStandardInformation->Directory = TRUE;
|
|
} else {
|
|
FileStandardInformation->Directory = FALSE;
|
|
}
|
|
|
|
// The "inode number"
|
|
FileInternalInformation->IndexNumber.LowPart = Fcb->RfsdMcb->Key.k_dir_id;
|
|
FileInternalInformation->IndexNumber.HighPart = Fcb->RfsdMcb->Key.k_objectid;
|
|
|
|
// Romfs doesn't have any extended attributes
|
|
FileEaInformation->EaSize = 0;
|
|
|
|
FilePositionInformation->CurrentByteOffset =
|
|
FileObject->CurrentByteOffset;
|
|
|
|
if (Length < sizeof(FILE_ALL_INFORMATION) +
|
|
Fcb->RfsdMcb->ShortName.Length - sizeof(WCHAR)) {
|
|
Irp->IoStatus.Information = sizeof(FILE_ALL_INFORMATION);
|
|
Status = STATUS_BUFFER_OVERFLOW;
|
|
_SEH2_LEAVE;
|
|
}
|
|
|
|
FileNameInformation->FileNameLength = Fcb->RfsdMcb->ShortName.Length;
|
|
|
|
RtlCopyMemory(
|
|
FileNameInformation->FileName,
|
|
Fcb->RfsdMcb->ShortName.Buffer,
|
|
Fcb->RfsdMcb->ShortName.Length
|
|
);
|
|
|
|
Irp->IoStatus.Information = sizeof(FILE_ALL_INFORMATION) +
|
|
Fcb->RfsdMcb->ShortName.Length - sizeof(WCHAR);
|
|
Status = STATUS_SUCCESS;
|
|
_SEH2_LEAVE;
|
|
}
|
|
|
|
/*
|
|
case FileAlternateNameInformation:
|
|
{
|
|
// TODO: [ext2fsd] Handle FileAlternateNameInformation
|
|
|
|
// Here we would like to use RtlGenerate8dot3Name but I don't
|
|
// know how to use the argument PGENERATE_NAME_CONTEXT
|
|
}
|
|
*/
|
|
|
|
case FileNetworkOpenInformation:
|
|
{
|
|
PFILE_NETWORK_OPEN_INFORMATION FileNetworkOpenInformation;
|
|
|
|
if (Length < sizeof(FILE_NETWORK_OPEN_INFORMATION)) {
|
|
Status = STATUS_INFO_LENGTH_MISMATCH;
|
|
_SEH2_LEAVE;
|
|
}
|
|
|
|
FileNetworkOpenInformation =
|
|
(PFILE_NETWORK_OPEN_INFORMATION) Buffer;
|
|
|
|
FileNetworkOpenInformation->CreationTime = RfsdSysTime(Fcb->Inode->i_ctime);
|
|
|
|
FileNetworkOpenInformation->LastAccessTime = RfsdSysTime(Fcb->Inode->i_atime);
|
|
|
|
FileNetworkOpenInformation->LastWriteTime = RfsdSysTime(Fcb->Inode->i_mtime);
|
|
|
|
FileNetworkOpenInformation->ChangeTime = RfsdSysTime(Fcb->Inode->i_mtime);
|
|
|
|
FileNetworkOpenInformation->AllocationSize.QuadPart = AllocationSize;
|
|
|
|
FileNetworkOpenInformation->EndOfFile.QuadPart = FileSize;
|
|
|
|
FileNetworkOpenInformation->FileAttributes = Fcb->RfsdMcb->FileAttr;
|
|
|
|
Irp->IoStatus.Information =
|
|
sizeof(FILE_NETWORK_OPEN_INFORMATION);
|
|
Status = STATUS_SUCCESS;
|
|
_SEH2_LEAVE;
|
|
}
|
|
|
|
default:
|
|
Status = STATUS_INVALID_INFO_CLASS;
|
|
}
|
|
|
|
} _SEH2_FINALLY {
|
|
|
|
if (FcbResourceAcquired) {
|
|
ExReleaseResourceForThreadLite(
|
|
&Fcb->MainResource,
|
|
ExGetCurrentResourceThread());
|
|
}
|
|
|
|
if (!IrpContext->ExceptionInProgress) {
|
|
if (Status == STATUS_PENDING) {
|
|
RfsdQueueRequest(IrpContext);
|
|
} else {
|
|
RfsdCompleteIrpContext(IrpContext, Status);
|
|
}
|
|
}
|
|
} _SEH2_END;
|
|
|
|
return Status;
|
|
}
|
|
|
|
__drv_mustHoldCriticalRegion
|
|
NTSTATUS
|
|
RfsdSetInformation (IN PRFSD_IRP_CONTEXT IrpContext)
|
|
{
|
|
PDEVICE_OBJECT DeviceObject;
|
|
NTSTATUS Status = STATUS_UNSUCCESSFUL;
|
|
PRFSD_VCB Vcb = 0;
|
|
PFILE_OBJECT FileObject;
|
|
PRFSD_FCB Fcb = 0;
|
|
PRFSD_CCB Ccb;
|
|
PIRP Irp;
|
|
PIO_STACK_LOCATION IoStackLocation;
|
|
FILE_INFORMATION_CLASS FileInformationClass;
|
|
|
|
ULONG NotifyFilter = 0;
|
|
|
|
ULONG Length;
|
|
PVOID Buffer;
|
|
BOOLEAN FcbMainResourceAcquired = FALSE;
|
|
|
|
BOOLEAN VcbResourceAcquired = FALSE;
|
|
BOOLEAN FcbPagingIoResourceAcquired = FALSE;
|
|
|
|
PAGED_CODE();
|
|
|
|
_SEH2_TRY {
|
|
|
|
ASSERT(IrpContext != NULL);
|
|
|
|
ASSERT((IrpContext->Identifier.Type == RFSDICX) &&
|
|
(IrpContext->Identifier.Size == sizeof(RFSD_IRP_CONTEXT)));
|
|
|
|
DeviceObject = IrpContext->DeviceObject;
|
|
|
|
//
|
|
// This request is not allowed on the main device object
|
|
//
|
|
if (DeviceObject == RfsdGlobal->DeviceObject) {
|
|
Status = STATUS_INVALID_DEVICE_REQUEST;
|
|
_SEH2_LEAVE;
|
|
}
|
|
|
|
Vcb = (PRFSD_VCB) DeviceObject->DeviceExtension;
|
|
|
|
ASSERT(Vcb != NULL);
|
|
|
|
ASSERT((Vcb->Identifier.Type == RFSDVCB) &&
|
|
(Vcb->Identifier.Size == sizeof(RFSD_VCB)));
|
|
|
|
ASSERT(IsMounted(Vcb));
|
|
|
|
FileObject = IrpContext->FileObject;
|
|
|
|
Fcb = (PRFSD_FCB) FileObject->FsContext;
|
|
|
|
ASSERT(Fcb != NULL);
|
|
|
|
//
|
|
// This request is not allowed on volumes
|
|
//
|
|
if (Fcb->Identifier.Type == RFSDVCB) {
|
|
DbgBreak();
|
|
|
|
Status = STATUS_INVALID_PARAMETER;
|
|
_SEH2_LEAVE;
|
|
}
|
|
|
|
ASSERT((Fcb->Identifier.Type == RFSDFCB) &&
|
|
(Fcb->Identifier.Size == sizeof(RFSD_FCB)));
|
|
|
|
if (IsFlagOn(Fcb->Flags, FCB_FILE_DELETED)) {
|
|
Status = STATUS_FILE_DELETED;
|
|
_SEH2_LEAVE;
|
|
}
|
|
|
|
Ccb = (PRFSD_CCB) FileObject->FsContext2;
|
|
|
|
ASSERT(Ccb != NULL);
|
|
|
|
ASSERT((Ccb->Identifier.Type == RFSDCCB) &&
|
|
(Ccb->Identifier.Size == sizeof(RFSD_CCB)));
|
|
|
|
Irp = IrpContext->Irp;
|
|
|
|
IoStackLocation = IoGetCurrentIrpStackLocation(Irp);
|
|
|
|
FileInformationClass =
|
|
IoStackLocation->Parameters.SetFile.FileInformationClass;
|
|
|
|
Length = IoStackLocation->Parameters.SetFile.Length;
|
|
|
|
Buffer = Irp->AssociatedIrp.SystemBuffer;
|
|
|
|
if (IsFlagOn(Vcb->Flags, VCB_READ_ONLY)) {
|
|
|
|
if (FileInformationClass == FileDispositionInformation ||
|
|
FileInformationClass == FileRenameInformation ||
|
|
FileInformationClass == FileLinkInformation) {
|
|
|
|
#ifdef _MSC_VER
|
|
#pragma prefast( suppress: 28137, "by design" )
|
|
#endif
|
|
if (!ExAcquireResourceExclusiveLite(
|
|
&Vcb->MainResource,
|
|
IrpContext->IsSynchronous )) {
|
|
|
|
Status = STATUS_PENDING;
|
|
_SEH2_LEAVE;
|
|
}
|
|
|
|
VcbResourceAcquired = TRUE;
|
|
}
|
|
|
|
} else if (!FlagOn(Fcb->Flags, FCB_PAGE_FILE)) {
|
|
|
|
#ifdef _MSC_VER
|
|
#pragma prefast( suppress: 28137, "by design" )
|
|
#endif
|
|
if (!ExAcquireResourceExclusiveLite(
|
|
&Fcb->MainResource,
|
|
IrpContext->IsSynchronous )) {
|
|
Status = STATUS_PENDING;
|
|
_SEH2_LEAVE;
|
|
}
|
|
|
|
FcbMainResourceAcquired = TRUE;
|
|
}
|
|
|
|
if (IsFlagOn(Vcb->Flags, VCB_READ_ONLY)) {
|
|
|
|
if (FileInformationClass != FilePositionInformation) {
|
|
Status = STATUS_MEDIA_WRITE_PROTECTED;
|
|
_SEH2_LEAVE;
|
|
}
|
|
}
|
|
|
|
if (FileInformationClass == FileDispositionInformation ||
|
|
FileInformationClass == FileRenameInformation ||
|
|
FileInformationClass == FileLinkInformation ||
|
|
FileInformationClass == FileAllocationInformation ||
|
|
FileInformationClass == FileEndOfFileInformation) {
|
|
|
|
#ifdef _MSC_VER
|
|
#pragma prefast( suppress: 28137, "by design" )
|
|
#endif
|
|
if (!ExAcquireResourceExclusiveLite(
|
|
&Fcb->PagingIoResource,
|
|
IrpContext->IsSynchronous )) {
|
|
Status = STATUS_PENDING;
|
|
_SEH2_LEAVE;
|
|
}
|
|
|
|
FcbPagingIoResourceAcquired = TRUE;
|
|
}
|
|
|
|
/*
|
|
if (FileInformationClass != FileDispositionInformation
|
|
&& FlagOn(Fcb->Flags, FCB_DELETE_PENDING))
|
|
{
|
|
Status = STATUS_DELETE_PENDING;
|
|
_SEH2_LEAVE;
|
|
}
|
|
*/
|
|
switch (FileInformationClass) {
|
|
|
|
#if !RFSD_READ_ONLY
|
|
#if 0
|
|
case FileBasicInformation:
|
|
{
|
|
PFILE_BASIC_INFORMATION FBI = (PFILE_BASIC_INFORMATION) Buffer;
|
|
PRFSD_INODE RfsdInode = Fcb->Inode;
|
|
|
|
if (FBI->CreationTime.QuadPart) {
|
|
RfsdInode->i_ctime = (ULONG)(RfsdInodeTime(FBI->CreationTime));
|
|
}
|
|
|
|
if (FBI->LastAccessTime.QuadPart) {
|
|
RfsdInode->i_atime = (ULONG)(RfsdInodeTime(FBI->LastAccessTime));
|
|
}
|
|
|
|
if (FBI->LastWriteTime.QuadPart) {
|
|
RfsdInode->i_mtime = (ULONG)(RfsdInodeTime(FBI->LastWriteTime));
|
|
}
|
|
|
|
if (IsFlagOn(FBI->FileAttributes, FILE_ATTRIBUTE_READONLY)) {
|
|
RfsdSetReadOnly(Fcb->Inode->i_mode);
|
|
SetFlag(Fcb->RfsdMcb->FileAttr, FILE_ATTRIBUTE_READONLY);
|
|
} else {
|
|
RfsdSetWritable(Fcb->Inode->i_mode);
|
|
ClearFlag(Fcb->RfsdMcb->FileAttr, FILE_ATTRIBUTE_READONLY);
|
|
}
|
|
|
|
if(RfsdSaveInode(IrpContext, Vcb, Fcb->RfsdMcb->Inode, RfsdInode)) {
|
|
Status = STATUS_SUCCESS;
|
|
}
|
|
|
|
if (FBI->FileAttributes & FILE_ATTRIBUTE_TEMPORARY) {
|
|
SetFlag(FileObject->Flags, FO_TEMPORARY_FILE);
|
|
} else {
|
|
ClearFlag(FileObject->Flags, FO_TEMPORARY_FILE);
|
|
}
|
|
|
|
NotifyFilter = FILE_NOTIFY_CHANGE_ATTRIBUTES |
|
|
FILE_NOTIFY_CHANGE_CREATION |
|
|
FILE_NOTIFY_CHANGE_LAST_ACCESS |
|
|
FILE_NOTIFY_CHANGE_LAST_WRITE ;
|
|
|
|
Status = STATUS_SUCCESS;
|
|
}
|
|
|
|
break;
|
|
|
|
case FileAllocationInformation:
|
|
{
|
|
PFILE_ALLOCATION_INFORMATION FAI = (PFILE_ALLOCATION_INFORMATION)Buffer;
|
|
|
|
if (FlagOn(Fcb->RfsdMcb->FileAttr, FILE_ATTRIBUTE_DIRECTORY)) {
|
|
Status = STATUS_INVALID_DEVICE_REQUEST;
|
|
_SEH2_LEAVE;
|
|
}
|
|
|
|
if ( FAI->AllocationSize.QuadPart ==
|
|
Fcb->Header.AllocationSize.QuadPart) {
|
|
|
|
Status = STATUS_SUCCESS;
|
|
|
|
} else if ( FAI->AllocationSize.QuadPart >
|
|
Fcb->Header.AllocationSize.QuadPart ) {
|
|
|
|
Status = RfsdExpandFile(
|
|
IrpContext,
|
|
Vcb, Fcb,
|
|
&(FAI->AllocationSize));
|
|
|
|
if (NT_SUCCESS(Status)) {
|
|
|
|
RfsdSaveInode( IrpContext,
|
|
Vcb,
|
|
Fcb->RfsdMcb->Inode,
|
|
Fcb->Inode );
|
|
}
|
|
|
|
} else {
|
|
|
|
if (MmCanFileBeTruncated(&(Fcb->SectionObject), &(FAI->AllocationSize))) {
|
|
|
|
LARGE_INTEGER EndOfFile;
|
|
|
|
EndOfFile.QuadPart = FAI->AllocationSize.QuadPart +
|
|
(LONGLONG)(Vcb->BlockSize - 1);
|
|
|
|
Status = RfsdTruncateFile(IrpContext, Vcb, Fcb, &(EndOfFile));
|
|
|
|
if (NT_SUCCESS(Status)) {
|
|
|
|
if ( FAI->AllocationSize.QuadPart <
|
|
Fcb->Header.FileSize.QuadPart) {
|
|
Fcb->Header.FileSize.QuadPart =
|
|
FAI->AllocationSize.QuadPart;
|
|
}
|
|
|
|
RfsdSaveInode( IrpContext,
|
|
Vcb,
|
|
Fcb->RfsdMcb->Inode,
|
|
Fcb->Inode);
|
|
}
|
|
|
|
} else {
|
|
|
|
Status = STATUS_USER_MAPPED_FILE;
|
|
_SEH2_LEAVE;
|
|
}
|
|
}
|
|
|
|
if (NT_SUCCESS(Status)) {
|
|
|
|
CcSetFileSizes(FileObject,
|
|
(PCC_FILE_SIZES)(&(Fcb->Header.AllocationSize)));
|
|
SetFlag(FileObject->Flags, FO_FILE_MODIFIED);
|
|
|
|
NotifyFilter = FILE_NOTIFY_CHANGE_SIZE |
|
|
FILE_NOTIFY_CHANGE_LAST_WRITE ;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case FileEndOfFileInformation:
|
|
{
|
|
PFILE_END_OF_FILE_INFORMATION FEOFI = (PFILE_END_OF_FILE_INFORMATION) Buffer;
|
|
|
|
BOOLEAN CacheInitialized = FALSE;
|
|
|
|
if (IsDirectory(Fcb)) {
|
|
Status = STATUS_INVALID_DEVICE_REQUEST;
|
|
_SEH2_LEAVE;
|
|
}
|
|
|
|
if (FEOFI->EndOfFile.HighPart != 0) {
|
|
Status = STATUS_INVALID_PARAMETER;
|
|
_SEH2_LEAVE;
|
|
}
|
|
|
|
|
|
if (IoStackLocation->Parameters.SetFile.AdvanceOnly) {
|
|
Status = STATUS_SUCCESS;
|
|
_SEH2_LEAVE;
|
|
}
|
|
|
|
if ((FileObject->SectionObjectPointer->DataSectionObject != NULL) &&
|
|
(FileObject->SectionObjectPointer->SharedCacheMap == NULL) &&
|
|
!FlagOn(Irp->Flags, IRP_PAGING_IO)) {
|
|
|
|
ASSERT( !FlagOn( FileObject->Flags, FO_CLEANUP_COMPLETE ) );
|
|
|
|
CcInitializeCacheMap(
|
|
FileObject,
|
|
(PCC_FILE_SIZES)&(Fcb->Header.AllocationSize),
|
|
FALSE,
|
|
&(RfsdGlobal->CacheManagerNoOpCallbacks),
|
|
Fcb );
|
|
|
|
CacheInitialized = TRUE;
|
|
}
|
|
|
|
if ( FEOFI->EndOfFile.QuadPart ==
|
|
Fcb->Header.AllocationSize.QuadPart) {
|
|
|
|
Status = STATUS_SUCCESS;
|
|
|
|
} else if ( FEOFI->EndOfFile.QuadPart >
|
|
Fcb->Header.AllocationSize.QuadPart) {
|
|
|
|
LARGE_INTEGER FileSize = Fcb->Header.FileSize;
|
|
|
|
Status = RfsdExpandFile(IrpContext, Vcb, Fcb, &(FEOFI->EndOfFile));
|
|
|
|
if (NT_SUCCESS(Status)) {
|
|
|
|
Fcb->Header.FileSize.QuadPart = FEOFI->EndOfFile.QuadPart;
|
|
|
|
Fcb->Inode->i_size = FEOFI->EndOfFile.QuadPart;
|
|
|
|
Fcb->Header.ValidDataLength.QuadPart =
|
|
(LONGLONG)(0x7fffffffffffffff);
|
|
|
|
RfsdSaveInode( IrpContext,
|
|
Vcb,
|
|
Fcb->RfsdMcb->Inode,
|
|
Fcb->Inode);
|
|
|
|
|
|
CcSetFileSizes(FileObject,
|
|
(PCC_FILE_SIZES)(&(Fcb->Header.AllocationSize)));
|
|
|
|
SetFlag(FileObject->Flags, FO_FILE_MODIFIED);
|
|
|
|
RfsdZeroHoles( IrpContext,
|
|
Vcb, FileObject,
|
|
FileSize.QuadPart,
|
|
Fcb->Header.AllocationSize.QuadPart -
|
|
FileSize.QuadPart );
|
|
|
|
NotifyFilter = FILE_NOTIFY_CHANGE_SIZE |
|
|
FILE_NOTIFY_CHANGE_LAST_WRITE ;
|
|
|
|
}
|
|
} else {
|
|
|
|
if (MmCanFileBeTruncated(&(Fcb->SectionObject), &(FEOFI->EndOfFile))) {
|
|
|
|
LARGE_INTEGER EndOfFile = FEOFI->EndOfFile;
|
|
|
|
EndOfFile.QuadPart = EndOfFile.QuadPart +
|
|
(LONGLONG)(Vcb->BlockSize - 1);
|
|
|
|
Status = RfsdTruncateFile(IrpContext, Vcb, Fcb, &(EndOfFile));
|
|
|
|
if (NT_SUCCESS(Status)) {
|
|
|
|
Fcb->Header.FileSize.QuadPart = FEOFI->EndOfFile.QuadPart;
|
|
Fcb->Inode->i_size = FEOFI->EndOfFile.QuadPart;
|
|
|
|
RfsdSaveInode( IrpContext,
|
|
Vcb,
|
|
Fcb->RfsdMcb->Inode,
|
|
Fcb->Inode);
|
|
|
|
CcSetFileSizes(FileObject,
|
|
(PCC_FILE_SIZES)(&(Fcb->Header.AllocationSize)));
|
|
|
|
SetFlag(FileObject->Flags, FO_FILE_MODIFIED);
|
|
|
|
NotifyFilter = FILE_NOTIFY_CHANGE_SIZE |
|
|
FILE_NOTIFY_CHANGE_LAST_WRITE ;
|
|
}
|
|
|
|
} else {
|
|
|
|
Status = STATUS_USER_MAPPED_FILE;
|
|
_SEH2_LEAVE;
|
|
}
|
|
}
|
|
}
|
|
|
|
break;
|
|
|
|
case FileDispositionInformation:
|
|
{
|
|
PFILE_DISPOSITION_INFORMATION FDI = (PFILE_DISPOSITION_INFORMATION)Buffer;
|
|
|
|
Status = RfsdSetDispositionInfo(IrpContext, Vcb, Fcb, FDI->DeleteFile);
|
|
}
|
|
|
|
break;
|
|
|
|
case FileRenameInformation:
|
|
{
|
|
Status = RfsdSetRenameInfo(IrpContext, Vcb, Fcb);
|
|
}
|
|
|
|
break;
|
|
#endif // 0
|
|
#endif // !RFSD_READ_ONLY
|
|
|
|
//
|
|
// This is the only set file information request supported on read
|
|
// only file systems
|
|
//
|
|
case FilePositionInformation:
|
|
{
|
|
PFILE_POSITION_INFORMATION FilePositionInformation;
|
|
|
|
if (Length < sizeof(FILE_POSITION_INFORMATION)) {
|
|
Status = STATUS_INVALID_PARAMETER;
|
|
_SEH2_LEAVE;
|
|
}
|
|
|
|
FilePositionInformation = (PFILE_POSITION_INFORMATION) Buffer;
|
|
|
|
if ((FlagOn(FileObject->Flags, FO_NO_INTERMEDIATE_BUFFERING)) &&
|
|
(FilePositionInformation->CurrentByteOffset.LowPart &
|
|
DeviceObject->AlignmentRequirement) ) {
|
|
Status = STATUS_INVALID_PARAMETER;
|
|
_SEH2_LEAVE;
|
|
}
|
|
|
|
FileObject->CurrentByteOffset =
|
|
FilePositionInformation->CurrentByteOffset;
|
|
|
|
Status = STATUS_SUCCESS;
|
|
_SEH2_LEAVE;
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
Status = STATUS_INVALID_INFO_CLASS;
|
|
}
|
|
|
|
} _SEH2_FINALLY {
|
|
|
|
if (FcbPagingIoResourceAcquired) {
|
|
ExReleaseResourceForThreadLite(
|
|
&Fcb->PagingIoResource,
|
|
ExGetCurrentResourceThread() );
|
|
}
|
|
|
|
if (NT_SUCCESS(Status) && (NotifyFilter != 0)) {
|
|
RfsdNotifyReportChange(
|
|
IrpContext,
|
|
Vcb,
|
|
Fcb,
|
|
NotifyFilter,
|
|
FILE_ACTION_MODIFIED );
|
|
|
|
}
|
|
|
|
if (FcbMainResourceAcquired) {
|
|
ExReleaseResourceForThreadLite(
|
|
&Fcb->MainResource,
|
|
ExGetCurrentResourceThread() );
|
|
}
|
|
|
|
if (VcbResourceAcquired) {
|
|
ExReleaseResourceForThreadLite(
|
|
&Vcb->MainResource,
|
|
ExGetCurrentResourceThread() );
|
|
}
|
|
|
|
if (!IrpContext->ExceptionInProgress) {
|
|
if (Status == STATUS_PENDING) {
|
|
RfsdQueueRequest(IrpContext);
|
|
} else {
|
|
RfsdCompleteIrpContext(IrpContext, Status);
|
|
}
|
|
}
|
|
} _SEH2_END;
|
|
|
|
return Status;
|
|
}
|
|
|
|
#if !RFSD_READ_ONLY
|
|
|
|
NTSTATUS
|
|
RfsdExpandFile( PRFSD_IRP_CONTEXT IrpContext,
|
|
PRFSD_VCB Vcb, PRFSD_FCB Fcb,
|
|
PLARGE_INTEGER AllocationSize)
|
|
{
|
|
ULONG dwRet = 0;
|
|
NTSTATUS Status = STATUS_SUCCESS;
|
|
|
|
PAGED_CODE();
|
|
|
|
if (AllocationSize->QuadPart <= Fcb->Header.AllocationSize.QuadPart) {
|
|
return Status;
|
|
}
|
|
|
|
if (((LONGLONG)SUPER_BLOCK->s_free_blocks_count) * Vcb->BlockSize <=
|
|
(AllocationSize->QuadPart - Fcb->Header.AllocationSize.QuadPart) ) {
|
|
RfsdPrint((DBG_ERROR, "RfsdExpandFile: There is no enough disk space available.\n"));
|
|
return STATUS_DISK_FULL;
|
|
}
|
|
|
|
while (NT_SUCCESS(Status) && (AllocationSize->QuadPart > Fcb->Header.AllocationSize.QuadPart)) {
|
|
Status = RfsdExpandInode(IrpContext, Vcb, Fcb, &dwRet);
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
NTSTATUS
|
|
RfsdTruncateFile( PRFSD_IRP_CONTEXT IrpContext,
|
|
PRFSD_VCB Vcb, PRFSD_FCB Fcb,
|
|
PLARGE_INTEGER AllocationSize)
|
|
{
|
|
NTSTATUS Status = STATUS_SUCCESS;
|
|
|
|
PAGED_CODE();
|
|
|
|
while (NT_SUCCESS(Status) && (AllocationSize->QuadPart <
|
|
Fcb->Header.AllocationSize.QuadPart)) {
|
|
Status= RfsdTruncateInode(IrpContext, Vcb, Fcb);
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
NTSTATUS
|
|
RfsdSetDispositionInfo(
|
|
PRFSD_IRP_CONTEXT IrpContext,
|
|
PRFSD_VCB Vcb,
|
|
PRFSD_FCB Fcb,
|
|
BOOLEAN bDelete)
|
|
{
|
|
PIRP Irp = IrpContext->Irp;
|
|
PIO_STACK_LOCATION IrpSp;
|
|
|
|
PAGED_CODE();
|
|
|
|
IrpSp = IoGetCurrentIrpStackLocation(Irp);
|
|
|
|
RfsdPrint((DBG_INFO, "RfsdSetDispositionInfo: bDelete=%x\n", bDelete));
|
|
|
|
if (bDelete) {
|
|
|
|
RfsdPrint((DBG_INFO, "RfsdSetDispositionInformation: MmFlushImageSection on %s.\n",
|
|
Fcb->AnsiFileName.Buffer));
|
|
|
|
if (!MmFlushImageSection( &Fcb->SectionObject,
|
|
MmFlushForDelete )) {
|
|
return STATUS_CANNOT_DELETE;
|
|
}
|
|
|
|
if (RFSD_IS_ROOT_KEY(Fcb->RfsdMcb->Key)) {
|
|
return STATUS_CANNOT_DELETE;
|
|
}
|
|
|
|
if (IsDirectory(Fcb)) {
|
|
if (!RfsdIsDirectoryEmpty(Vcb, Fcb)) {
|
|
return STATUS_DIRECTORY_NOT_EMPTY;
|
|
}
|
|
}
|
|
|
|
SetFlag(Fcb->Flags, FCB_DELETE_PENDING);
|
|
IrpSp->FileObject->DeletePending = TRUE;
|
|
|
|
if (IsDirectory(Fcb)) {
|
|
FsRtlNotifyFullChangeDirectory( Vcb->NotifySync,
|
|
&Vcb->NotifyList,
|
|
Fcb,
|
|
NULL,
|
|
FALSE,
|
|
FALSE,
|
|
0,
|
|
NULL,
|
|
NULL,
|
|
NULL );
|
|
}
|
|
|
|
} else {
|
|
|
|
ClearFlag(Fcb->Flags, FCB_DELETE_PENDING);
|
|
IrpSp->FileObject->DeletePending = FALSE;
|
|
}
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
NTSTATUS
|
|
RfsdSetRenameInfo(
|
|
PRFSD_IRP_CONTEXT IrpContext,
|
|
PRFSD_VCB Vcb,
|
|
PRFSD_FCB Fcb )
|
|
{
|
|
PRFSD_FCB TargetDcb;
|
|
PRFSD_MCB TargetMcb;
|
|
|
|
PRFSD_MCB Mcb;
|
|
RFSD_INODE Inode;
|
|
|
|
UNICODE_STRING FileName;
|
|
|
|
NTSTATUS Status;
|
|
|
|
PIRP Irp;
|
|
PIO_STACK_LOCATION IrpSp;
|
|
|
|
PFILE_OBJECT FileObject;
|
|
PFILE_OBJECT TargetObject;
|
|
BOOLEAN ReplaceIfExists;
|
|
|
|
BOOLEAN bMove = FALSE;
|
|
|
|
PFILE_RENAME_INFORMATION FRI;
|
|
|
|
PAGED_CODE();
|
|
#if 0
|
|
if (Fcb->RfsdMcb->Inode == RFSD_ROOT_INO) {
|
|
Status = STATUS_INVALID_PARAMETER;
|
|
goto errorout;
|
|
}
|
|
|
|
Irp = IrpContext->Irp;
|
|
IrpSp = IoGetCurrentIrpStackLocation(Irp);
|
|
|
|
FileObject = IrpSp->FileObject;
|
|
TargetObject = IrpSp->Parameters.SetFile.FileObject;
|
|
ReplaceIfExists = IrpSp->Parameters.SetFile.ReplaceIfExists;
|
|
|
|
FRI = (PFILE_RENAME_INFORMATION)Irp->AssociatedIrp.SystemBuffer;
|
|
|
|
if (TargetObject == NULL) {
|
|
|
|
UNICODE_STRING NewName;
|
|
|
|
NewName.Buffer = FRI->FileName;
|
|
NewName.MaximumLength = NewName.Length = (USHORT)FRI->FileNameLength;
|
|
|
|
while (NewName.Length > 0 && NewName.Buffer[NewName.Length/2 - 1] == L'\\') {
|
|
NewName.Buffer[NewName.Length/2 - 1] = 0;
|
|
NewName.Length -= 2;
|
|
}
|
|
|
|
while (NewName.Length > 0 && NewName.Buffer[NewName.Length/2 - 1] != L'\\') {
|
|
NewName.Length -= 2;
|
|
}
|
|
|
|
NewName.Buffer = (USHORT *)((UCHAR *)NewName.Buffer + NewName.Length);
|
|
NewName.Length = (USHORT)(FRI->FileNameLength - NewName.Length);
|
|
|
|
FileName = NewName;
|
|
|
|
TargetDcb = NULL;
|
|
TargetMcb = Fcb->RfsdMcb->Parent;
|
|
|
|
if (FileName.Length >= RFSD_NAME_LEN*sizeof(USHORT)) {
|
|
Status = STATUS_OBJECT_NAME_INVALID;
|
|
goto errorout;
|
|
}
|
|
|
|
} else {
|
|
|
|
TargetDcb = (PRFSD_FCB)(TargetObject->FsContext);
|
|
|
|
if (!TargetDcb || TargetDcb->Vcb != Vcb) {
|
|
|
|
DbgBreak();
|
|
|
|
Status = STATUS_INVALID_PARAMETER;
|
|
goto errorout;
|
|
}
|
|
|
|
TargetMcb = TargetDcb->RfsdMcb;
|
|
|
|
FileName = TargetObject->FileName;
|
|
}
|
|
|
|
if (FsRtlDoesNameContainWildCards(&FileName)) {
|
|
Status = STATUS_OBJECT_NAME_INVALID;
|
|
goto errorout;
|
|
}
|
|
|
|
if (TargetMcb->Inode == Fcb->RfsdMcb->Parent->Inode) {
|
|
if (FsRtlAreNamesEqual( &FileName,
|
|
&(Fcb->RfsdMcb->ShortName),
|
|
FALSE,
|
|
NULL )) {
|
|
Status = STATUS_SUCCESS;
|
|
goto errorout;
|
|
}
|
|
} else {
|
|
bMove = TRUE;
|
|
}
|
|
|
|
TargetDcb = TargetMcb->RfsdFcb;
|
|
|
|
if (!TargetDcb)
|
|
TargetDcb = RfsdCreateFcbFromMcb(Vcb, TargetMcb);
|
|
|
|
if ((TargetMcb->Inode != Fcb->RfsdMcb->Parent->Inode) &&
|
|
(Fcb->RfsdMcb->Parent->RfsdFcb == NULL) ) {
|
|
RfsdCreateFcbFromMcb(Vcb, Fcb->RfsdMcb->Parent);
|
|
}
|
|
|
|
if (!TargetDcb || !(Fcb->RfsdMcb->Parent->RfsdFcb)) {
|
|
Status = STATUS_UNSUCCESSFUL;
|
|
|
|
goto errorout;
|
|
}
|
|
|
|
Mcb = NULL;
|
|
Status = RfsdLookupFileName(
|
|
Vcb,
|
|
&FileName,
|
|
TargetMcb,
|
|
&Mcb,
|
|
&Inode );
|
|
|
|
if (NT_SUCCESS(Status)) {
|
|
|
|
if ( (!ReplaceIfExists) ||
|
|
(IsFlagOn(Mcb->FileAttr, FILE_ATTRIBUTE_DIRECTORY)) ||
|
|
(IsFlagOn(Mcb->FileAttr, FILE_ATTRIBUTE_READONLY))) {
|
|
Status = STATUS_OBJECT_NAME_COLLISION;
|
|
goto errorout;
|
|
}
|
|
|
|
if (ReplaceIfExists) {
|
|
Status = STATUS_NOT_IMPLEMENTED;
|
|
goto errorout;
|
|
}
|
|
}
|
|
|
|
if (IsDirectory(Fcb)) {
|
|
|
|
Status = RfsdRemoveEntry( IrpContext, Vcb,
|
|
Fcb->RfsdMcb->Parent->RfsdFcb,
|
|
RFSD_FT_DIR,
|
|
Fcb->RfsdMcb->Inode );
|
|
|
|
if (!NT_SUCCESS(Status)) {
|
|
DbgBreak();
|
|
|
|
goto errorout;
|
|
}
|
|
|
|
Status = RfsdAddEntry( IrpContext, Vcb,
|
|
TargetDcb,
|
|
RFSD_FT_DIR,
|
|
Fcb->RfsdMcb->Inode,
|
|
&FileName );
|
|
|
|
if (!NT_SUCCESS(Status)) {
|
|
|
|
DbgBreak();
|
|
|
|
RfsdAddEntry( IrpContext, Vcb,
|
|
Fcb->RfsdMcb->Parent->RfsdFcb,
|
|
RFSD_FT_DIR,
|
|
Fcb->RfsdMcb->Inode,
|
|
&Fcb->RfsdMcb->ShortName );
|
|
|
|
goto errorout;
|
|
}
|
|
|
|
if( !RfsdSaveInode( IrpContext,
|
|
Vcb,
|
|
TargetMcb->Inode,
|
|
TargetDcb->Inode)) {
|
|
Status = STATUS_UNSUCCESSFUL;
|
|
|
|
DbgBreak();
|
|
|
|
goto errorout;
|
|
}
|
|
|
|
if( !RfsdSaveInode( IrpContext,
|
|
Vcb,
|
|
Fcb->RfsdMcb->Parent->Inode,
|
|
Fcb->RfsdMcb->Parent->RfsdFcb->Inode)) {
|
|
|
|
Status = STATUS_UNSUCCESSFUL;
|
|
|
|
DbgBreak();
|
|
|
|
goto errorout;
|
|
}
|
|
|
|
Status = RfsdSetParentEntry( IrpContext, Vcb, Fcb,
|
|
Fcb->RfsdMcb->Parent->Inode,
|
|
TargetDcb->RfsdMcb->Inode );
|
|
|
|
|
|
if (!NT_SUCCESS(Status)) {
|
|
DbgBreak();
|
|
goto errorout;
|
|
}
|
|
|
|
} else {
|
|
|
|
Status = RfsdRemoveEntry( IrpContext, Vcb,
|
|
Fcb->RfsdMcb->Parent->RfsdFcb,
|
|
RFSD_FT_REG_FILE,
|
|
Fcb->RfsdMcb->Inode );
|
|
if (!NT_SUCCESS(Status)) {
|
|
DbgBreak();
|
|
goto errorout;
|
|
}
|
|
|
|
Status = RfsdAddEntry( IrpContext,
|
|
Vcb, TargetDcb,
|
|
RFSD_FT_REG_FILE,
|
|
Fcb->RfsdMcb->Inode,
|
|
&FileName );
|
|
|
|
if (!NT_SUCCESS(Status)) {
|
|
|
|
DbgBreak();
|
|
|
|
RfsdAddEntry( IrpContext, Vcb,
|
|
Fcb->RfsdMcb->Parent->RfsdFcb,
|
|
RFSD_FT_REG_FILE,
|
|
Fcb->RfsdMcb->Inode,
|
|
&Fcb->RfsdMcb->ShortName );
|
|
|
|
goto errorout;
|
|
}
|
|
}
|
|
|
|
if (NT_SUCCESS(Status)) {
|
|
|
|
if (Fcb->RfsdMcb->ShortName.MaximumLength < (FileName.Length + 2)) {
|
|
|
|
ExFreePool(Fcb->RfsdMcb->ShortName.Buffer);
|
|
Fcb->RfsdMcb->ShortName.Buffer =
|
|
ExAllocatePoolWithTag(PagedPool, FileName.Length + 2, RFSD_POOL_TAG);
|
|
|
|
if (!Fcb->RfsdMcb->ShortName.Buffer) {
|
|
Status = STATUS_INSUFFICIENT_RESOURCES;
|
|
goto errorout;
|
|
}
|
|
|
|
Fcb->RfsdMcb->ShortName.MaximumLength = FileName.Length + 2;
|
|
}
|
|
|
|
{
|
|
RtlZeroMemory( Fcb->RfsdMcb->ShortName.Buffer,
|
|
Fcb->RfsdMcb->ShortName.MaximumLength);
|
|
|
|
RtlCopyMemory( Fcb->RfsdMcb->ShortName.Buffer,
|
|
FileName.Buffer, FileName.Length);
|
|
|
|
Fcb->RfsdMcb->ShortName.Length = FileName.Length;
|
|
}
|
|
|
|
#if DBG
|
|
|
|
Fcb->AnsiFileName.Length = (USHORT)
|
|
RfsdUnicodeToOEMSize(&FileName) + 1;
|
|
|
|
if (Fcb->AnsiFileName.MaximumLength < FileName.Length) {
|
|
ExFreePool(Fcb->AnsiFileName.Buffer);
|
|
|
|
Fcb->AnsiFileName.Buffer =
|
|
ExAllocatePoolWithTag(PagedPool, Fcb->AnsiFileName.Length + 1, RFSD_POOL_TAG);
|
|
|
|
if (!Fcb->AnsiFileName.Buffer) {
|
|
Status = STATUS_INSUFFICIENT_RESOURCES;
|
|
goto errorout;
|
|
}
|
|
|
|
RtlZeroMemory( Fcb->AnsiFileName.Buffer,
|
|
Fcb->AnsiFileName.Length + 1);
|
|
Fcb->AnsiFileName.MaximumLength =
|
|
Fcb->AnsiFileName.Length + 1;
|
|
}
|
|
|
|
RfsdUnicodeToOEM( &(Fcb->AnsiFileName),
|
|
&FileName );
|
|
|
|
#endif
|
|
|
|
if (bMove) {
|
|
|
|
RfsdNotifyReportChange(
|
|
IrpContext,
|
|
Vcb,
|
|
Fcb,
|
|
(IsDirectory(Fcb) ?
|
|
FILE_NOTIFY_CHANGE_DIR_NAME :
|
|
FILE_NOTIFY_CHANGE_FILE_NAME ),
|
|
FILE_ACTION_REMOVED);
|
|
|
|
} else {
|
|
|
|
RfsdNotifyReportChange(
|
|
IrpContext,
|
|
Vcb,
|
|
Fcb,
|
|
(IsDirectory(Fcb) ?
|
|
FILE_NOTIFY_CHANGE_DIR_NAME :
|
|
FILE_NOTIFY_CHANGE_FILE_NAME ),
|
|
FILE_ACTION_RENAMED_OLD_NAME);
|
|
|
|
}
|
|
|
|
RfsdDeleteMcbNode(Vcb, Fcb->RfsdMcb->Parent, Fcb->RfsdMcb);
|
|
RfsdAddMcbNode(Vcb, TargetMcb, Fcb->RfsdMcb);
|
|
|
|
if (bMove) {
|
|
|
|
RfsdNotifyReportChange(
|
|
IrpContext,
|
|
Vcb,
|
|
Fcb,
|
|
(IsDirectory(Fcb) ?
|
|
FILE_NOTIFY_CHANGE_DIR_NAME :
|
|
FILE_NOTIFY_CHANGE_FILE_NAME ),
|
|
FILE_ACTION_ADDED);
|
|
} else {
|
|
|
|
RfsdNotifyReportChange(
|
|
IrpContext,
|
|
Vcb,
|
|
Fcb,
|
|
(IsDirectory(Fcb) ?
|
|
FILE_NOTIFY_CHANGE_DIR_NAME :
|
|
FILE_NOTIFY_CHANGE_FILE_NAME ),
|
|
FILE_ACTION_RENAMED_NEW_NAME );
|
|
|
|
}
|
|
}
|
|
|
|
errorout:
|
|
#endif // 0
|
|
return 0;//Status;
|
|
}
|
|
|
|
NTSTATUS
|
|
RfsdDeleteFile(
|
|
PRFSD_IRP_CONTEXT IrpContext,
|
|
PRFSD_VCB Vcb,
|
|
PRFSD_FCB Fcb )
|
|
{
|
|
BOOLEAN bRet = FALSE;
|
|
LARGE_INTEGER AllocationSize;
|
|
PRFSD_FCB Dcb = NULL;
|
|
NTSTATUS Status = STATUS_SUCCESS;
|
|
|
|
PAGED_CODE();
|
|
#if 0
|
|
RfsdPrint((DBG_INFO, "RfsdDeleteFile: File %S (%xh) will be deleted!\n",
|
|
Fcb->RfsdMcb->ShortName.Buffer, Fcb->RfsdMcb->Inode));
|
|
|
|
if (IsFlagOn(Fcb->Flags, FCB_FILE_DELETED)) {
|
|
return Status;
|
|
}
|
|
|
|
if (FlagOn(Fcb->RfsdMcb->FileAttr, FILE_ATTRIBUTE_DIRECTORY)) {
|
|
if (!RfsdIsDirectoryEmpty(Vcb, Fcb)) {
|
|
ClearFlag(Fcb->Flags, FCB_DELETE_PENDING);
|
|
|
|
return STATUS_DIRECTORY_NOT_EMPTY;
|
|
}
|
|
}
|
|
|
|
RfsdPrint((DBG_INFO, "RfsdDeleteFile: RFSDSB->S_FREE_BLOCKS = %xh .\n",
|
|
Vcb->SuperBlock->s_free_blocks_count));
|
|
|
|
if (IsDirectory(Fcb)) {
|
|
if (Fcb->Inode->i_links_count <= 2) {
|
|
} else {
|
|
Status = STATUS_CANNOT_DELETE;
|
|
}
|
|
} else {
|
|
if (Fcb->Inode->i_links_count <= 1) {
|
|
} else {
|
|
Status = STATUS_CANNOT_DELETE;
|
|
}
|
|
}
|
|
|
|
if (!NT_SUCCESS(Status)) {
|
|
DbgBreak();
|
|
return Status;
|
|
}
|
|
|
|
if (Fcb->RfsdMcb->Parent->RfsdFcb) {
|
|
|
|
Status = RfsdRemoveEntry(
|
|
IrpContext, Vcb,
|
|
Fcb->RfsdMcb->Parent->RfsdFcb,
|
|
(FlagOn(Fcb->RfsdMcb->FileAttr, FILE_ATTRIBUTE_DIRECTORY) ?
|
|
RFSD_FT_DIR : RFSD_FT_REG_FILE),
|
|
Fcb->RfsdMcb->Inode);
|
|
} else {
|
|
|
|
Dcb = RfsdCreateFcbFromMcb(Vcb, Fcb->RfsdMcb->Parent);
|
|
if (Dcb) {
|
|
Status = RfsdRemoveEntry(
|
|
IrpContext, Vcb, Dcb,
|
|
(FlagOn(Fcb->RfsdMcb->FileAttr, FILE_ATTRIBUTE_DIRECTORY) ?
|
|
RFSD_FT_DIR : RFSD_FT_REG_FILE),
|
|
Fcb->RfsdMcb->Inode);
|
|
}
|
|
}
|
|
|
|
if (NT_SUCCESS(Status)) {
|
|
|
|
LARGE_INTEGER SysTime;
|
|
KeQuerySystemTime(&SysTime);
|
|
|
|
AllocationSize.QuadPart = (LONGLONG)0;
|
|
|
|
Status = RfsdTruncateFile(IrpContext, Vcb, Fcb, &AllocationSize);
|
|
|
|
//
|
|
// Update the inode's data length . It should be ZERO if succeeds.
|
|
//
|
|
|
|
if (Fcb->Header.FileSize.QuadPart > Fcb->Header.AllocationSize.QuadPart) {
|
|
|
|
Fcb->Header.FileSize.QuadPart = Fcb->Header.AllocationSize.QuadPart;
|
|
Fcb->Inode->i_size = Fcb->Header.AllocationSize.QuadPart;
|
|
}
|
|
|
|
Fcb->Inode->i_links_count = 0;
|
|
|
|
RfsdSaveInode(IrpContext, Vcb, Fcb->RfsdMcb->Inode, Fcb->Inode);
|
|
|
|
if (IsDirectory(Fcb)) {
|
|
bRet = RfsdFreeInode(IrpContext, Vcb, Fcb->RfsdMcb->Inode, RFSD_FT_DIR);
|
|
} else {
|
|
bRet = RfsdFreeInode(IrpContext, Vcb, Fcb->RfsdMcb->Inode, RFSD_FT_REG_FILE);
|
|
}
|
|
|
|
SetFlag(Fcb->Flags, FCB_FILE_DELETED);
|
|
RfsdDeleteMcbNode(Vcb, Fcb->RfsdMcb->Parent, Fcb->RfsdMcb);
|
|
|
|
} else {
|
|
DbgBreak();
|
|
RfsdSaveInode(IrpContext, Vcb, Fcb->RfsdMcb->Inode, Fcb->Inode);
|
|
}
|
|
|
|
RfsdPrint((DBG_INFO, "RfsdDeleteFile: Succeed... RFSDSB->S_FREE_BLOCKS = %xh .\n",
|
|
Vcb->SuperBlock->s_free_blocks_count));
|
|
#endif // 0
|
|
return Status;
|
|
}
|
|
|
|
#endif // !RFSD_READ_ONLY
|