finfo.c
来自「ReactOS是一些高手根据Windows XP的内核编写出的类XP。内核实现机」· C语言 代码 · 共 940 行 · 第 1/2 页
C
940 行
/*
* 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;
}
static NTSTATUS
VfatGetAllInformation(PFILE_OBJECT FileObject,
PVFATFCB Fcb,
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?