📄 dirctl.c
字号:
/*
* FFS File System Driver for Windows
*
* dirctl.c
*
* 2004.5.6 ~
*
* Lee Jae-Hong, http://www.pyrasis.com
*
* See License.txt
*
*/
#include "ntifs.h"
#include "ffsdrv.h"
/* Globals */
extern PFFS_GLOBAL FFSGlobal;
/* Definitions */
#ifdef ALLOC_PRAGMA
#pragma alloc_text(PAGE, FFSGetInfoLength)
#pragma alloc_text(PAGE, FFSProcessDirEntry)
#pragma alloc_text(PAGE, FFSQueryDirectory)
#pragma alloc_text(PAGE, FFSNotifyChangeDirectory)
#pragma alloc_text(PAGE, FFSDirectoryControl)
#pragma alloc_text(PAGE, FFSIsDirectoryEmpty)
#endif
ULONG
FFSGetInfoLength(
IN FILE_INFORMATION_CLASS FileInformationClass)
{
switch (FileInformationClass)
{
case FileDirectoryInformation:
return sizeof(FILE_DIRECTORY_INFORMATION);
break;
case FileFullDirectoryInformation:
return sizeof(FILE_FULL_DIR_INFORMATION);
break;
case FileBothDirectoryInformation:
return sizeof(FILE_BOTH_DIR_INFORMATION);
break;
case FileNamesInformation:
return sizeof(FILE_NAMES_INFORMATION);
break;
default:
break;
}
return 0;
}
ULONG
FFSProcessDirEntry(
IN PFFS_VCB Vcb,
IN FILE_INFORMATION_CLASS FileInformationClass,
IN ULONG in,
IN PVOID Buffer,
IN ULONG UsedLength,
IN ULONG Length,
IN ULONG FileIndex,
IN PUNICODE_STRING pName,
IN BOOLEAN Single)
{
FFSv1_INODE dinode1;
FFSv2_INODE dinode2;
PFILE_DIRECTORY_INFORMATION FDI;
PFILE_FULL_DIR_INFORMATION FFI;
PFILE_BOTH_DIR_INFORMATION FBI;
PFILE_NAMES_INFORMATION FNI;
ULONG InfoLength = 0;
ULONG NameLength = 0;
ULONG dwBytes = 0;
NameLength = pName->Length;
if (!in)
{
FFSPrint((DBG_ERROR, "FFSPricessDirEntry: ffs_dir_entry is empty.\n"));
return 0;
}
InfoLength = FFSGetInfoLength(FileInformationClass);
if (!InfoLength || InfoLength + NameLength - sizeof(WCHAR) > Length)
{
FFSPrint((DBG_INFO, "FFSPricessDirEntry: Buffer is not enough.\n"));
return 0;
}
if (FS_VERSION == 1)
{
if(!FFSv1LoadInode(Vcb, in, &dinode1))
{
FFSPrint((DBG_ERROR, "FFSPricessDirEntry: Loading inode %xh error.\n", in));
FFSBreakPoint();
return 0;
}
}
else
{
if(!FFSv2LoadInode(Vcb, in, &dinode2))
{
FFSPrint((DBG_ERROR, "FFSPricessDirEntry: Loading inode %xh error.\n", in));
FFSBreakPoint();
return 0;
}
}
switch(FileInformationClass)
{
case FileDirectoryInformation:
FDI = (PFILE_DIRECTORY_INFORMATION) ((PUCHAR)Buffer + UsedLength);
if (!Single)
FDI->NextEntryOffset = InfoLength + NameLength - sizeof(WCHAR);
else
FDI->NextEntryOffset = 0;
FDI->FileIndex = FileIndex;
if (FS_VERSION == 1)
{
FDI->CreationTime = FFSSysTime(dinode1.di_ctime);
FDI->LastAccessTime = FFSSysTime(dinode1.di_atime);
FDI->LastWriteTime = FFSSysTime(dinode1.di_mtime);
FDI->ChangeTime = FFSSysTime(dinode1.di_mtime);
FDI->EndOfFile.QuadPart = dinode1.di_size;
FDI->AllocationSize.QuadPart = dinode1.di_size;
FDI->FileAttributes = FILE_ATTRIBUTE_NORMAL;
if (FlagOn(Vcb->Flags, VCB_READ_ONLY) || FFSIsReadOnly(dinode1.di_mode))
{
SetFlag(FDI->FileAttributes, FILE_ATTRIBUTE_READONLY);
}
if ((dinode1.di_mode & IFMT) == IFDIR)
FDI->FileAttributes |= FILE_ATTRIBUTE_DIRECTORY;
FDI->FileNameLength = NameLength;
RtlCopyMemory(FDI->FileName, pName->Buffer, NameLength);
dwBytes = InfoLength + NameLength - sizeof(WCHAR);
break;
}
else
{
FDI->CreationTime = FFSSysTime((ULONG)dinode2.di_ctime);
FDI->LastAccessTime = FFSSysTime((ULONG)dinode2.di_atime);
FDI->LastWriteTime = FFSSysTime((ULONG)dinode2.di_mtime);
FDI->ChangeTime = FFSSysTime((ULONG)dinode2.di_mtime);
FDI->EndOfFile.QuadPart = dinode2.di_size;
FDI->AllocationSize.QuadPart = dinode2.di_size;
FDI->FileAttributes = FILE_ATTRIBUTE_NORMAL;
if (FlagOn(Vcb->Flags, VCB_READ_ONLY) || FFSIsReadOnly(dinode2.di_mode))
{
SetFlag(FDI->FileAttributes, FILE_ATTRIBUTE_READONLY);
}
if ((dinode2.di_mode & IFMT) == IFDIR)
FDI->FileAttributes |= FILE_ATTRIBUTE_DIRECTORY;
FDI->FileNameLength = NameLength;
RtlCopyMemory(FDI->FileName, pName->Buffer, NameLength);
dwBytes = InfoLength + NameLength - sizeof(WCHAR);
break;
}
case FileFullDirectoryInformation:
FFI = (PFILE_FULL_DIR_INFORMATION) ((PUCHAR)Buffer + UsedLength);
if (!Single)
FFI->NextEntryOffset = InfoLength + NameLength - sizeof(WCHAR);
else
FFI->NextEntryOffset = 0;
FFI->FileIndex = FileIndex;
if (FS_VERSION == 1)
{
FFI->CreationTime = FFSSysTime(dinode1.di_ctime);
FFI->LastAccessTime = FFSSysTime(dinode1.di_atime);
FFI->LastWriteTime = FFSSysTime(dinode1.di_mtime);
FFI->ChangeTime = FFSSysTime(dinode1.di_mtime);
FFI->EndOfFile.QuadPart = dinode1.di_size;
FFI->AllocationSize.QuadPart = dinode1.di_size;
FFI->FileAttributes = FILE_ATTRIBUTE_NORMAL;
if (IsFlagOn(Vcb->Flags, VCB_READ_ONLY) || FFSIsReadOnly(dinode1.di_mode))
{
SetFlag(FFI->FileAttributes, FILE_ATTRIBUTE_READONLY);
}
if ((dinode1.di_mode & IFMT) == IFDIR)
FFI->FileAttributes |= FILE_ATTRIBUTE_DIRECTORY;
FFI->FileNameLength = NameLength;
RtlCopyMemory(FFI->FileName, pName->Buffer, NameLength);
dwBytes = InfoLength + NameLength - sizeof(WCHAR);
break;
}
else
{
FFI->CreationTime = FFSSysTime((ULONG)dinode2.di_ctime);
FFI->LastAccessTime = FFSSysTime((ULONG)dinode2.di_atime);
FFI->LastWriteTime = FFSSysTime((ULONG)dinode2.di_mtime);
FFI->ChangeTime = FFSSysTime((ULONG)dinode2.di_mtime);
FFI->EndOfFile.QuadPart = dinode2.di_size;
FFI->AllocationSize.QuadPart = dinode2.di_size;
FFI->FileAttributes = FILE_ATTRIBUTE_NORMAL;
if (IsFlagOn(Vcb->Flags, VCB_READ_ONLY) || FFSIsReadOnly(dinode2.di_mode))
{
SetFlag(FFI->FileAttributes, FILE_ATTRIBUTE_READONLY);
}
if ((dinode2.di_mode & IFMT) == IFDIR)
FFI->FileAttributes |= FILE_ATTRIBUTE_DIRECTORY;
FFI->FileNameLength = NameLength;
RtlCopyMemory(FFI->FileName, pName->Buffer, NameLength);
dwBytes = InfoLength + NameLength - sizeof(WCHAR);
break;
}
case FileBothDirectoryInformation:
FBI = (PFILE_BOTH_DIR_INFORMATION) ((PUCHAR)Buffer + UsedLength);
if (!Single)
FBI->NextEntryOffset = InfoLength + NameLength - sizeof(WCHAR);
else
FBI->NextEntryOffset = 0;
if (FS_VERSION == 1)
{
FBI->CreationTime = FFSSysTime(dinode1.di_ctime);
FBI->LastAccessTime = FFSSysTime(dinode1.di_atime);
FBI->LastWriteTime = FFSSysTime(dinode1.di_mtime);
FBI->ChangeTime = FFSSysTime(dinode1.di_mtime);
FBI->FileIndex = FileIndex;
FBI->EndOfFile.QuadPart = dinode1.di_size;
FBI->AllocationSize.QuadPart = dinode1.di_size;
FBI->FileAttributes = FILE_ATTRIBUTE_NORMAL;
if (FlagOn(Vcb->Flags, VCB_READ_ONLY) || FFSIsReadOnly(dinode1.di_mode))
{
SetFlag(FBI->FileAttributes, FILE_ATTRIBUTE_READONLY);
}
if ((dinode1.di_mode & IFMT) == IFDIR)
FBI->FileAttributes |= FILE_ATTRIBUTE_DIRECTORY;
FBI->FileNameLength = NameLength;
RtlCopyMemory(FBI->FileName, pName->Buffer, NameLength);
dwBytes = InfoLength + NameLength - sizeof(WCHAR);
break;
}
else
{
FBI->CreationTime = FFSSysTime((ULONG)dinode2.di_ctime);
FBI->LastAccessTime = FFSSysTime((ULONG)dinode2.di_atime);
FBI->LastWriteTime = FFSSysTime((ULONG)dinode2.di_mtime);
FBI->ChangeTime = FFSSysTime((ULONG)dinode2.di_mtime);
FBI->FileIndex = FileIndex;
FBI->EndOfFile.QuadPart = dinode2.di_size;
FBI->AllocationSize.QuadPart = dinode2.di_size;
FBI->FileAttributes = FILE_ATTRIBUTE_NORMAL;
if (FlagOn(Vcb->Flags, VCB_READ_ONLY) || FFSIsReadOnly(dinode2.di_mode))
{
SetFlag(FBI->FileAttributes, FILE_ATTRIBUTE_READONLY);
}
if ((dinode2.di_mode & IFMT) == IFDIR)
FBI->FileAttributes |= FILE_ATTRIBUTE_DIRECTORY;
FBI->FileNameLength = NameLength;
RtlCopyMemory(FBI->FileName, pName->Buffer, NameLength);
dwBytes = InfoLength + NameLength - sizeof(WCHAR);
break;
}
case FileNamesInformation:
FNI = (PFILE_NAMES_INFORMATION) ((PUCHAR)Buffer + UsedLength);
if (!Single)
FNI->NextEntryOffset = InfoLength + NameLength - sizeof(WCHAR);
else
FNI->NextEntryOffset = 0;
FNI->FileNameLength = NameLength;
RtlCopyMemory(FNI->FileName, pName->Buffer, NameLength);
dwBytes = InfoLength + NameLength - sizeof(WCHAR);
break;
default:
break;
}
return dwBytes;
}
NTSTATUS
FFSQueryDirectory(
IN PFFS_IRP_CONTEXT IrpContext)
{
PDEVICE_OBJECT DeviceObject;
NTSTATUS Status = STATUS_UNSUCCESSFUL;
PFFS_VCB Vcb;
PFILE_OBJECT FileObject;
PFFS_FCB Fcb;
PFFS_CCB Ccb;
PIRP Irp;
PIO_STACK_LOCATION IoStackLocation;
FILE_INFORMATION_CLASS FileInformationClass;
ULONG Length;
PUNICODE_STRING FileName;
ULONG FileIndex;
BOOLEAN RestartScan;
BOOLEAN ReturnSingleEntry;
BOOLEAN IndexSpecified;
PUCHAR Buffer;
BOOLEAN FirstQuery;
PFFSv1_INODE dinode1 = NULL;
PFFSv2_INODE dinode2 = NULL;
BOOLEAN FcbResourceAcquired = FALSE;
ULONG UsedLength = 0;
USHORT InodeFileNameLength;
UNICODE_STRING InodeFileName;
PFFS_DIR_ENTRY pDir = NULL;
ULONG dwBytes;
ULONG dwTemp = 0;
ULONG dwSize = 0;
ULONG dwReturn = 0;
BOOLEAN bRun = TRUE;
ULONG ByteOffset;
InodeFileName.Buffer = NULL;
__try
{
ASSERT(IrpContext);
ASSERT((IrpContext->Identifier.Type == FFSICX) &&
(IrpContext->Identifier.Size == sizeof(FFS_IRP_CONTEXT)));
DeviceObject = IrpContext->DeviceObject;
//
// This request is not allowed on the main device object
//
if (DeviceObject == FFSGlobal->DeviceObject)
{
Status = STATUS_INVALID_DEVICE_REQUEST;
__leave;
}
Vcb = (PFFS_VCB)DeviceObject->DeviceExtension;
ASSERT(Vcb != NULL);
ASSERT((Vcb->Identifier.Type == FFSVCB) &&
(Vcb->Identifier.Size == sizeof(FFS_VCB)));
ASSERT(IsMounted(Vcb));
FileObject = IrpContext->FileObject;
Fcb = (PFFS_FCB)FileObject->FsContext;
ASSERT(Fcb);
//
// This request is not allowed on volumes
//
if (Fcb->Identifier.Type == FFSVCB)
{
Status = STATUS_INVALID_PARAMETER;
__leave;
}
ASSERT((Fcb->Identifier.Type == FFSFCB) &&
(Fcb->Identifier.Size == sizeof(FFS_FCB)));
if (!IsDirectory(Fcb))
{
Status = STATUS_INVALID_PARAMETER;
__leave;
}
Ccb = (PFFS_CCB)FileObject->FsContext2;
ASSERT(Ccb);
ASSERT((Ccb->Identifier.Type == FFSCCB) &&
(Ccb->Identifier.Size == sizeof(FFS_CCB)));
Irp = IrpContext->Irp;
IoStackLocation = IoGetCurrentIrpStackLocation(Irp);
#ifndef _GNU_NTIFS_
FileInformationClass =
IoStackLocation->Parameters.QueryDirectory.FileInformationClass;
Length = IoStackLocation->Parameters.QueryDirectory.Length;
FileName = IoStackLocation->Parameters.QueryDirectory.FileName;
FileIndex = IoStackLocation->Parameters.QueryDirectory.FileIndex;
#else // _GNU_NTIFS_
FileInformationClass = ((PEXTENDED_IO_STACK_LOCATION)
IoStackLocation)->Parameters.QueryDirectory.FileInformationClass;
Length = ((PEXTENDED_IO_STACK_LOCATION)
IoStackLocation)->Parameters.QueryDirectory.Length;
FileName = ((PEXTENDED_IO_STACK_LOCATION)
IoStackLocation)->Parameters.QueryDirectory.FileName;
FileIndex = ((PEXTENDED_IO_STACK_LOCATION)
IoStackLocation)->Parameters.QueryDirectory.FileIndex;
#endif // _GNU_NTIFS_
RestartScan = FlagOn(((PEXTENDED_IO_STACK_LOCATION)
IoStackLocation)->Flags, SL_RESTART_SCAN);
ReturnSingleEntry = FlagOn(((PEXTENDED_IO_STACK_LOCATION)
IoStackLocation)->Flags, SL_RETURN_SINGLE_ENTRY);
IndexSpecified = FlagOn(((PEXTENDED_IO_STACK_LOCATION)
IoStackLocation)->Flags, SL_INDEX_SPECIFIED);
/*
if (!Irp->MdlAddress && Irp->UserBuffer)
{
ProbeForWrite(Irp->UserBuffer, Length, 1);
}
*/
Buffer = FFSGetUserBuffer(Irp);
if (Buffer == NULL)
{
FFSBreakPoint();
Status = STATUS_INVALID_USER_BUFFER;
__leave;
}
if (!IrpContext->IsSynchronous)
{
Status = STATUS_PENDING;
__leave;
}
if (!ExAcquireResourceSharedLite(
&Fcb->MainResource,
IrpContext->IsSynchronous))
{
Status = STATUS_PENDING;
__leave;
}
FcbResourceAcquired = TRUE;
if (FileName != NULL)
{
if (Ccb->DirectorySearchPattern.Buffer != NULL)
{
FirstQuery = FALSE;
}
else
{
FirstQuery = TRUE;
Ccb->DirectorySearchPattern.Length =
Ccb->DirectorySearchPattern.MaximumLength =
FileName->Length;
Ccb->DirectorySearchPattern.Buffer =
ExAllocatePool(PagedPool, FileName->Length);
if (Ccb->DirectorySearchPattern.Buffer == NULL)
{
Status = STATUS_INSUFFICIENT_RESOURCES;
__leave;
}
Status = RtlUpcaseUnicodeString(
&(Ccb->DirectorySearchPattern),
FileName,
FALSE);
if (!NT_SUCCESS(Status))
__leave;
}
}
else if (Ccb->DirectorySearchPattern.Buffer != NULL)
{
FirstQuery = FALSE;
FileName = &Ccb->DirectorySearchPattern;
}
else
{
FirstQuery = TRUE;
Ccb->DirectorySearchPattern.Length =
Ccb->DirectorySearchPattern.MaximumLength = 2;
Ccb->DirectorySearchPattern.Buffer =
ExAllocatePool(PagedPool, 2);
if (Ccb->DirectorySearchPattern.Buffer == NULL)
{
Status = STATUS_INSUFFICIENT_RESOURCES;
__leave;
}
RtlCopyMemory(
Ccb->DirectorySearchPattern.Buffer,
L"*\0", 2);
}
if (!IndexSpecified)
{
if (RestartScan || FirstQuery)
{
FileIndex = Fcb->FFSMcb->DeOffset = 0;
}
else
{
FileIndex = Ccb->CurrentByteOffset;
}
}
if (FS_VERSION == 1)
{
dinode1 = (PFFSv1_INODE)ExAllocatePool(
PagedPool,
DINODE1_SIZE);
if (dinode1 == NULL)
{
Status = STATUS_INSUFFICIENT_RESOURCES;
__leave;
}
RtlZeroMemory(Buffer, Length);
if (Fcb->dinode1->di_size <= FileIndex)
{
Status = STATUS_NO_MORE_FILES;
__leave;
}
}
else
{
dinode2 = (PFFSv2_INODE)ExAllocatePool(
PagedPool,
DINODE2_SIZE);
if (dinode2 == NULL)
{
Status = STATUS_INSUFFICIENT_RESOURCES;
__leave;
}
RtlZeroMemory(Buffer, Length);
if (Fcb->dinode2->di_size <= FileIndex)
{
Status = STATUS_NO_MORE_FILES;
__leave;
}
}
pDir = ExAllocatePool(PagedPool,
sizeof(FFS_DIR_ENTRY));
if (!pDir)
{
Status = STATUS_INSUFFICIENT_RESOURCES;
__leave;
}
if (FS_VERSION == 1)
{
dwBytes = 0;
dwSize = (ULONG)Fcb->dinode1->di_size - FileIndex -
(sizeof(FFS_DIR_ENTRY) - FFS_NAME_LEN + 1);
ByteOffset = FileIndex;
dwTemp = 0;
while (bRun && UsedLength < Length && dwBytes < dwSize)
{
OEM_STRING OemName;
RtlZeroMemory(pDir, sizeof(FFS_DIR_ENTRY));
Status = FFSv1ReadInode(
NULL,
Vcb,
Fcb->dinode1,
ByteOffset,
(PVOID)pDir,
sizeof(FFS_DIR_ENTRY),
&dwReturn);
if (!NT_SUCCESS(Status))
{
__leave;
}
if (!pDir->d_ino)
{
if (pDir->d_reclen == 0)
{
FFSBreakPoint();
__leave;
}
goto ProcessNextEntryv1;
}
OemName.Buffer = pDir->d_name;
OemName.Length = (pDir->d_namlen & 0xff);
OemName.MaximumLength = OemName.Length;
#if 0
/*
//
// We could not filter the files: "." and ".."
//
if ((OemName.Length >) 1 && OemName.Buffer[0] == '.')
{
if ( OemName.Length == 2 && OemName.Buffer[1] == '.')
{
}
else
{
goto ProcessNextEntry1;
}
}
*/
#endif
InodeFileNameLength = (USHORT)
RtlOemStringToUnicodeSize(&OemName);
InodeFileName.Length = 0;
InodeFileName.MaximumLength = InodeFileNameLength + 2;
if (InodeFileNameLength <= 0)
{
break;
}
InodeFileName.Buffer = ExAllocatePool(
PagedPool,
InodeFileNameLength + 2);
if (!InodeFileName.Buffer)
{
Status = STATUS_INSUFFICIENT_RESOURCES;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -