finfo.c

来自「winNT技术操作系统,国外开放的原代码和LIUX一样」· C语言 代码 · 共 933 行 · 第 1/2 页

C
933
字号
/*
 * COPYRIGHT:        See COPYING in the top level directory
 * PROJECT:          ReactOS kernel
 * FILE:             drivers/fs/vfat/finfo.c
 * PURPOSE:          VFAT Filesystem
 * PROGRAMMER:       Jason Filby (jasonfilby@yahoo.com)
 *                   Herve Poussineau (reactos@poussine.freesurf.fr)
 *
 */

/* INCLUDES *****************************************************************/

#define NDEBUG
#include "vfat.h"

/* GLOBALS ******************************************************************/

const char* FileInformationClassNames[] =
{
  "??????",
  "FileDirectoryInformation",
  "FileFullDirectoryInformation",
  "FileBothDirectoryInformation",
  "FileBasicInformation",
  "FileStandardInformation",
  "FileInternalInformation",
  "FileEaInformation",
  "FileAccessInformation",
  "FileNameInformation",
  "FileRenameInformation",
  "FileLinkInformation",
  "FileNamesInformation",
  "FileDispositionInformation",
  "FilePositionInformation",
  "FileFullEaInformation",
  "FileModeInformation",
  "FileAlignmentInformation",
  "FileAllInformation",
  "FileAllocationInformation",
  "FileEndOfFileInformation",
  "FileAlternateNameInformation",
  "FileStreamInformation",
  "FilePipeInformation",
  "FilePipeLocalInformation",
  "FilePipeRemoteInformation",
  "FileMailslotQueryInformation",
  "FileMailslotSetInformation",
  "FileCompressionInformation",
  "FileObjectIdInformation",
  "FileCompletionInformation",
  "FileMoveClusterInformation",
  "FileQuotaInformation",
  "FileReparsePointInformation",
  "FileNetworkOpenInformation",
  "FileAttributeTagInformation",
  "FileTrackingInformation",
  "FileIdBothDirectoryInformation",
  "FileIdFullDirectoryInformation",
  "FileValidDataLengthInformation",
  "FileShortNameInformation",
  "FileMaximumInformation"
};

/* FUNCTIONS ****************************************************************/

static NTSTATUS
VfatGetStandardInformation(PVFATFCB FCB,
			   PFILE_STANDARD_INFORMATION StandardInfo,
			   PULONG BufferLength)
/*
 * FUNCTION: Retrieve the standard file information
 */
{

  if (*BufferLength < sizeof(FILE_STANDARD_INFORMATION))
    return STATUS_BUFFER_OVERFLOW;

  /* PRECONDITION */
  ASSERT(StandardInfo != NULL);
  ASSERT(FCB != NULL);

  if (vfatFCBIsDirectory(FCB))
    {
      StandardInfo->AllocationSize.QuadPart = 0;
      StandardInfo->EndOfFile.QuadPart = 0;
      StandardInfo->Directory = TRUE;
    }
  else
    {
      StandardInfo->AllocationSize = FCB->RFCB.AllocationSize;
      StandardInfo->EndOfFile = FCB->RFCB.FileSize;
      StandardInfo->Directory = FALSE;
    }
  StandardInfo->NumberOfLinks = 0;
  StandardInfo->DeletePending = FCB->Flags & FCB_DELETE_PENDING ? TRUE : FALSE;

  *BufferLength -= sizeof(FILE_STANDARD_INFORMATION);
  return(STATUS_SUCCESS);
}

static NTSTATUS
VfatSetPositionInformation(PFILE_OBJECT FileObject,
			   PFILE_POSITION_INFORMATION PositionInfo)
{
  DPRINT ("FsdSetPositionInformation()\n");

  DPRINT ("PositionInfo %x\n", PositionInfo);
  DPRINT ("Setting position %d\n", PositionInfo->CurrentByteOffset.u.LowPart);

  FileObject->CurrentByteOffset.QuadPart =
    PositionInfo->CurrentByteOffset.QuadPart;

  return (STATUS_SUCCESS);
}

static NTSTATUS
VfatGetPositionInformation(PFILE_OBJECT FileObject,
			   PVFATFCB FCB,
			   PDEVICE_OBJECT DeviceObject,
			   PFILE_POSITION_INFORMATION PositionInfo,
			   PULONG BufferLength)
{
  DPRINT ("VfatGetPositionInformation()\n");

  if (*BufferLength < sizeof(FILE_POSITION_INFORMATION))
    return STATUS_BUFFER_OVERFLOW;

  PositionInfo->CurrentByteOffset.QuadPart =
    FileObject->CurrentByteOffset.QuadPart;

  DPRINT("Getting position %I64x\n",
	 PositionInfo->CurrentByteOffset.QuadPart);

  *BufferLength -= sizeof(FILE_POSITION_INFORMATION);
  return(STATUS_SUCCESS);
}

static NTSTATUS
VfatSetBasicInformation(PFILE_OBJECT FileObject,
			PVFATFCB FCB,
			PDEVICE_EXTENSION DeviceExt,
			PFILE_BASIC_INFORMATION BasicInfo)
{
  DPRINT("VfatSetBasicInformation()\n");

  ASSERT(NULL != FileObject);
  ASSERT(NULL != FCB);
  ASSERT(NULL != DeviceExt);
  ASSERT(NULL != BasicInfo);
  /* Check volume label bit */
  ASSERT(0 == (*FCB->Attributes & 0x08));

  if (FCB->Flags & FCB_IS_FATX_ENTRY)
  {
    FsdSystemTimeToDosDateTime(DeviceExt,
                             &BasicInfo->CreationTime,
                             &FCB->entry.FatX.CreationDate,
                             &FCB->entry.FatX.CreationTime);
    FsdSystemTimeToDosDateTime(DeviceExt,
                             &BasicInfo->LastAccessTime,
                             &FCB->entry.FatX.AccessDate,
                             &FCB->entry.FatX.AccessTime);
    FsdSystemTimeToDosDateTime(DeviceExt,
                             &BasicInfo->LastWriteTime,
                             &FCB->entry.FatX.UpdateDate,
                             &FCB->entry.FatX.UpdateTime);
  }
  else
  {
    FsdSystemTimeToDosDateTime(DeviceExt,
                             &BasicInfo->CreationTime,
                             &FCB->entry.Fat.CreationDate,
                             &FCB->entry.Fat.CreationTime);
    FsdSystemTimeToDosDateTime(DeviceExt,
                             &BasicInfo->LastAccessTime,
                             &FCB->entry.Fat.AccessDate,
                             NULL);
    FsdSystemTimeToDosDateTime(DeviceExt,
                             &BasicInfo->LastWriteTime,
                             &FCB->entry.Fat.UpdateDate,
                             &FCB->entry.Fat.UpdateTime);
  }

  *FCB->Attributes = (unsigned char)((*FCB->Attributes &
                       (FILE_ATTRIBUTE_DIRECTORY | 0x48)) |
                      (BasicInfo->FileAttributes &
                       (FILE_ATTRIBUTE_ARCHIVE |
                        FILE_ATTRIBUTE_SYSTEM |
                        FILE_ATTRIBUTE_HIDDEN |
                        FILE_ATTRIBUTE_READONLY)));
  DPRINT("Setting attributes 0x%02x\n", *FCB->Attributes);

  VfatUpdateEntry(FCB);

  return(STATUS_SUCCESS);
}

static NTSTATUS
VfatGetBasicInformation(PFILE_OBJECT FileObject,
			PVFATFCB FCB,
			PDEVICE_OBJECT DeviceObject,
			PFILE_BASIC_INFORMATION BasicInfo,
			PULONG BufferLength)
{
  PDEVICE_EXTENSION DeviceExt;
  DPRINT("VfatGetBasicInformation()\n");

  DeviceExt = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension;

  if (*BufferLength < sizeof(FILE_BASIC_INFORMATION))
    return STATUS_BUFFER_OVERFLOW;

  if (FCB->Flags & FCB_IS_FATX_ENTRY)
  {
    FsdDosDateTimeToSystemTime(DeviceExt,
			     FCB->entry.FatX.CreationDate,
			     FCB->entry.FatX.CreationTime,
			     &BasicInfo->CreationTime);
    FsdDosDateTimeToSystemTime(DeviceExt,
			     FCB->entry.FatX.AccessDate,
			     FCB->entry.FatX.AccessTime,
			     &BasicInfo->LastAccessTime);
    FsdDosDateTimeToSystemTime(DeviceExt,
			     FCB->entry.FatX.UpdateDate,
			     FCB->entry.FatX.UpdateTime,
			     &BasicInfo->LastWriteTime);
    BasicInfo->ChangeTime = BasicInfo->LastWriteTime;
  }
  else
  {
    FsdDosDateTimeToSystemTime(DeviceExt,
			     FCB->entry.Fat.CreationDate,
			     FCB->entry.Fat.CreationTime,
			     &BasicInfo->CreationTime);
    FsdDosDateTimeToSystemTime(DeviceExt,
			     FCB->entry.Fat.AccessDate,
			     0,
			     &BasicInfo->LastAccessTime);
    FsdDosDateTimeToSystemTime(DeviceExt,
			     FCB->entry.Fat.UpdateDate,
			     FCB->entry.Fat.UpdateTime,
			     &BasicInfo->LastWriteTime);
    BasicInfo->ChangeTime = BasicInfo->LastWriteTime;
  }

  BasicInfo->FileAttributes = *FCB->Attributes & 0x3f;
  /* Synthesize FILE_ATTRIBUTE_NORMAL */
  if (0 == (BasicInfo->FileAttributes & (FILE_ATTRIBUTE_DIRECTORY |
                                         FILE_ATTRIBUTE_ARCHIVE |
                                         FILE_ATTRIBUTE_SYSTEM |
                                         FILE_ATTRIBUTE_HIDDEN |
                                         FILE_ATTRIBUTE_READONLY)))
  {
    DPRINT("Synthesizing FILE_ATTRIBUTE_NORMAL\n");
    BasicInfo->FileAttributes |= FILE_ATTRIBUTE_NORMAL;
  }
  DPRINT("Getting attributes 0x%02x\n", BasicInfo->FileAttributes);

  *BufferLength -= sizeof(FILE_BASIC_INFORMATION);
  return(STATUS_SUCCESS);
}


static NTSTATUS
VfatSetDispositionInformation(PFILE_OBJECT FileObject,
			      PVFATFCB FCB,
			      PDEVICE_OBJECT DeviceObject,
			      PFILE_DISPOSITION_INFORMATION DispositionInfo)
{
#ifdef DBG
   PDEVICE_EXTENSION DeviceExt = DeviceObject->DeviceExtension;
#endif

   DPRINT ("FsdSetDispositionInformation()\n");

   ASSERT(DeviceExt != NULL);
   ASSERT(DeviceExt->FatInfo.BytesPerCluster != 0);
   ASSERT(FCB != NULL);

   if (!DispositionInfo->DeleteFile)
   {
      /* undelete the file */
      FCB->Flags &= ~FCB_DELETE_PENDING;
      FileObject->DeletePending = FALSE;
      return STATUS_SUCCESS;
   }

   if (FCB->Flags & FCB_DELETE_PENDING)
   {
      /* stream already marked for deletion. just update the file object */
      FileObject->DeletePending = TRUE;
      return STATUS_SUCCESS;
   }

   if (*FCB->Attributes & FILE_ATTRIBUTE_READONLY)
   {
      return STATUS_CANNOT_DELETE;
   }

   if (vfatFCBIsRoot(FCB) ||
     (FCB->LongNameU.Length == sizeof(WCHAR) && FCB->LongNameU.Buffer[0] == L'.') ||
     (FCB->LongNameU.Length == 2 * sizeof(WCHAR) && FCB->LongNameU.Buffer[0] == L'.' && FCB->LongNameU.Buffer[1] == L'.'))
   {
      // we cannot delete a '.', '..' or the root directory
      return STATUS_ACCESS_DENIED;
   }


   if (!MmFlushImageSection (FileObject->SectionObjectPointer, MmFlushForDelete))
   {
      /* can't delete a file if its mapped into a process */

      DPRINT("MmFlushImageSection returned FALSE\n");
      return STATUS_CANNOT_DELETE;
   }

   if (vfatFCBIsDirectory(FCB) && !VfatIsDirectoryEmpty(FCB))
   {
      /* can't delete a non-empty directory */

      return STATUS_DIRECTORY_NOT_EMPTY;
   }

   /* all good */
   FCB->Flags |= FCB_DELETE_PENDING;
   FileObject->DeletePending = TRUE;

   return STATUS_SUCCESS;
}

static NTSTATUS
VfatGetNameInformation(PFILE_OBJECT FileObject,
		       PVFATFCB FCB,
		       PDEVICE_OBJECT DeviceObject,
		       PFILE_NAME_INFORMATION NameInfo,
		       PULONG BufferLength)
/*
 * FUNCTION: Retrieve the file name information
 */
{
  ASSERT(NameInfo != NULL);
  ASSERT(FCB != NULL);

  NameInfo->FileNameLength = FCB->PathNameU.Length;
  if (*BufferLength < FIELD_OFFSET(FILE_NAME_INFORMATION, FileName[0]) + FCB->PathNameU.Length)
    return STATUS_BUFFER_OVERFLOW;

  RtlCopyMemory(NameInfo->FileName, FCB->PathNameU.Buffer, FCB->PathNameU.Length);

  *BufferLength -= (FIELD_OFFSET(FILE_NAME_INFORMATION, FileName[0]) + FCB->PathNameU.Length);

  return STATUS_SUCCESS;
}

static NTSTATUS
VfatGetInternalInformation(PVFATFCB Fcb,
			   PFILE_INTERNAL_INFORMATION InternalInfo,
			   PULONG BufferLength)
{
  ASSERT(InternalInfo);
  ASSERT(Fcb);

  if (*BufferLength < sizeof(FILE_INTERNAL_INFORMATION))
    return STATUS_BUFFER_OVERFLOW;
  // FIXME: get a real index, that can be used in a create operation
  InternalInfo->IndexNumber.QuadPart = 0;
  *BufferLength -= sizeof(FILE_INTERNAL_INFORMATION);
  return STATUS_SUCCESS;
}


static NTSTATUS
VfatGetNetworkOpenInformation(PVFATFCB Fcb,
			      PDEVICE_EXTENSION DeviceExt,
			      PFILE_NETWORK_OPEN_INFORMATION NetworkInfo,
			      PULONG BufferLength)
/*
 * FUNCTION: Retrieve the file network open information
 */
{
  ASSERT(NetworkInfo);
  ASSERT(Fcb);

  if (*BufferLength < sizeof(FILE_NETWORK_OPEN_INFORMATION))
    return(STATUS_BUFFER_OVERFLOW);

  if (Fcb->Flags & FCB_IS_FATX_ENTRY)
  {
    FsdDosDateTimeToSystemTime(DeviceExt,
			     Fcb->entry.FatX.CreationDate,
			     Fcb->entry.FatX.CreationTime,
			     &NetworkInfo->CreationTime);
    FsdDosDateTimeToSystemTime(DeviceExt,
			     Fcb->entry.FatX.AccessDate,
			     Fcb->entry.FatX.AccessTime,
			     &NetworkInfo->LastAccessTime);
    FsdDosDateTimeToSystemTime(DeviceExt,
			     Fcb->entry.FatX.UpdateDate,
			     Fcb->entry.FatX.UpdateTime,
			     &NetworkInfo->LastWriteTime);
    NetworkInfo->ChangeTime.QuadPart = NetworkInfo->LastWriteTime.QuadPart;
  }
  else
  {
    FsdDosDateTimeToSystemTime(DeviceExt,
			     Fcb->entry.Fat.CreationDate,
			     Fcb->entry.Fat.CreationTime,
			     &NetworkInfo->CreationTime);
    FsdDosDateTimeToSystemTime(DeviceExt,
			     Fcb->entry.Fat.AccessDate,
			     0,
			     &NetworkInfo->LastAccessTime);
    FsdDosDateTimeToSystemTime(DeviceExt,
			     Fcb->entry.Fat.UpdateDate,
			     Fcb->entry.Fat.UpdateTime,
			     &NetworkInfo->LastWriteTime);
    NetworkInfo->ChangeTime.QuadPart = NetworkInfo->LastWriteTime.QuadPart;
  }
  if (vfatFCBIsDirectory(Fcb))
    {
      NetworkInfo->EndOfFile.QuadPart = 0L;
      NetworkInfo->AllocationSize.QuadPart = 0L;
    }
  else
    {
      NetworkInfo->AllocationSize = Fcb->RFCB.AllocationSize;
      NetworkInfo->EndOfFile = Fcb->RFCB.FileSize;
    }
  NetworkInfo->FileAttributes = *Fcb->Attributes & 0x3f;
  /* Synthesize FILE_ATTRIBUTE_NORMAL */
  if (0 == (NetworkInfo->FileAttributes & (FILE_ATTRIBUTE_DIRECTORY |
                                           FILE_ATTRIBUTE_ARCHIVE |
                                           FILE_ATTRIBUTE_SYSTEM |
                                           FILE_ATTRIBUTE_HIDDEN |
                                           FILE_ATTRIBUTE_READONLY)))
  {
    DPRINT("Synthesizing FILE_ATTRIBUTE_NORMAL\n");
    NetworkInfo->FileAttributes |= FILE_ATTRIBUTE_NORMAL;
  }

  *BufferLength -= sizeof(FILE_NETWORK_OPEN_INFORMATION);
  return STATUS_SUCCESS;
}


static NTSTATUS
VfatGetEaInformation(PFILE_OBJECT FileObject,
		     PVFATFCB Fcb,
		     PDEVICE_OBJECT DeviceObject,
		     PFILE_EA_INFORMATION Info,
		     PULONG BufferLength)
{
    PDEVICE_EXTENSION DeviceExt = DeviceObject->DeviceExtension;

    /* FIXME - use SEH to access the buffer! */
    Info->EaSize = 0;
    *BufferLength -= sizeof(*Info);
    if (DeviceExt->FatInfo.FatType == FAT12 ||
        DeviceExt->FatInfo.FatType == FAT16)
    {
        /* FIXME */
        DPRINT1("VFAT: FileEaInformation not implemented!\n");
    }
    return STATUS_SUCCESS;
}


⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?