⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dirctl.c

📁 FSD file system driver
💻 C
📖 第 1 页 / 共 2 页
字号:
/* 
 * 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 + -