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

📄 dirctl.c

📁 This is a ReiserFs file system driver for Windows NT/2000/XP/Vista.
💻 C
📖 第 1 页 / 共 3 页
字号:
/*
 * COPYRIGHT:        GNU GENERAL PUBLIC LICENSE VERSION 2
 * PROJECT:          ReiserFs file system driver for Windows NT/2000/XP/Vista.
 * FILE:             dirctl.c
 * PURPOSE:          
 * PROGRAMMER:       Mark Piper, Matt Wu, Bo Brant閚.
 * HOMEPAGE:         
 * UPDATE HISTORY: 
 */

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

#include "rfsd.h"

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

extern PRFSD_GLOBAL RfsdGlobal;

/* DEFINITIONS *************************************************************/

NTSTATUS
RfsdDirectoryCallback(
		    ULONG			BlockNumber,
			PVOID			pContext);

typedef struct _RFSD_CALLBACK_CONTEXT {
	
	PRFSD_VCB					Vcb;	
	PRFSD_CCB					Ccb;

	PRFSD_KEY_IN_MEMORY			pDirectoryKey;
	ULONG						idxStartingDentry;				// The dentry at which the callback should beging triggering output to the Buffer
	ULONG						idxCurrentDentry;				// The current dentry (relative to entire set of dentrys, across all spans)

	// These parameters are forwarded to ProcessDirectoryEntry 
    FILE_INFORMATION_CLASS		FileInformationClass;			// [s]
	PVOID						Buffer;							// [s]
	ULONG						BufferLength;					// [s]
	BOOLEAN						ReturnSingleEntry;				// [s]

    PULONG						pUsedLength;    
	PVOID						pPreviousEntry;    
	
} RFSD_CALLBACK_CONTEXT, *PRFSD_CALLBACK_CONTEXT;


#ifdef ALLOC_PRAGMA
#pragma alloc_text(PAGE, RfsdGetInfoLength)
#pragma alloc_text(PAGE, RfsdProcessDirEntry)
#pragma alloc_text(PAGE, RfsdQueryDirectory)
#pragma alloc_text(PAGE, RfsdNotifyChangeDirectory)
#pragma alloc_text(PAGE, RfsdDirectoryControl)
#pragma alloc_text(PAGE, RfsdIsDirectoryEmpty)
#pragma alloc_text(PAGE, RfsdDirectoryCallback)
#endif

ULONG
RfsdGetInfoLength(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		// Returns 0 on error, or InfoLength + NameLength (the amount of the buffer used for the entry given)
RfsdProcessDirEntry(
			IN PRFSD_VCB         Vcb,
            IN FILE_INFORMATION_CLASS  FileInformationClass,		// Identifier indicating the type of file information this function should report
            IN __u32		 Key_ParentDirectoryID,
			IN __u32		 Key_ObjectID,
            IN PVOID         Buffer,								// The user's buffer, as obtained from the IRP context (it is already gauranteed to be valid)
            IN ULONG         UsedLength,							// Length of Buffer used so far
            IN ULONG         Length,								// Length of Buffer remaining, beyond UsedLength
            IN ULONG         FileIndex,								// Byte offset of the dentry??  (This will just be placed into the file info structure of the same name)
            IN PUNICODE_STRING   pName,								// Filled unicode equivalent of the name (as pulled out from the dentry)
            IN BOOLEAN       Single, 								// Whether or not QueryDirectory is only supposed to return a single entry
			IN PVOID		 pPreviousEntry	)						// A pointer to the previous dir entry in Buffer, which will be linked into the newly added entry if one is created
{
    RFSD_INODE inode;
    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;
    LONGLONG    FileSize;
    LONGLONG    AllocationSize;

	// Calculate the size of the entry
    NameLength = pName->Length;
    InfoLength = RfsdGetInfoLength(FileInformationClass);

    if (!InfoLength || InfoLength + NameLength - sizeof(WCHAR) > Length)  {
        RfsdPrint((DBG_INFO, "RfsdPricessDirEntry: Buffer is not enough.\n"));
        return 0;
    }

	// Given the incoming key for this dentry, load the corresponding stat data.
	{ 
	  RFSD_KEY_IN_MEMORY key; 
	  key.k_dir_id = Key_ParentDirectoryID; 
	  key.k_objectid = Key_ObjectID;	  

	  if(!RfsdLoadInode(Vcb, &key, &inode)) {
		  RfsdPrint((DBG_ERROR,  "RfsdPricessDirEntry: Loading stat data %xh, %xh error.\n", Key_ParentDirectoryID, Key_ObjectID));
		  DbgBreak();
		  return 0;
	  }
	}

    FileSize  = (LONGLONG) inode.i_size;
    AllocationSize = CEILING_ALIGNED(FileSize, (ULONGLONG)Vcb->BlockSize);		// TODO: THIS ISN'T QUITE RIGHT

	// Link the previous entry into this entry
	if (pPreviousEntry) {
		// NOTE: All entries begin with NextEntryOffset, so it doesn't matter what type I cast to.
		((PFILE_NAMES_INFORMATION) (pPreviousEntry))->NextEntryOffset = 
			(ULONG) ((PUCHAR) Buffer + UsedLength - (PUCHAR) (pPreviousEntry));
	}

    switch(FileInformationClass) {

    case FileDirectoryInformation:
        FDI = (PFILE_DIRECTORY_INFORMATION) ((PUCHAR)Buffer + UsedLength);
		FDI->NextEntryOffset = 0;

        FDI->FileIndex = FileIndex;
        FDI->CreationTime = RfsdSysTime(inode.i_ctime);
        FDI->LastAccessTime = RfsdSysTime(inode.i_atime);
        FDI->LastWriteTime = RfsdSysTime(inode.i_mtime);
        FDI->ChangeTime = RfsdSysTime(inode.i_mtime);
        FDI->EndOfFile.QuadPart = FileSize;
        FDI->AllocationSize.QuadPart = AllocationSize;
        FDI->FileAttributes = FILE_ATTRIBUTE_NORMAL;

        if (FlagOn(Vcb->Flags, VCB_READ_ONLY) || RfsdIsReadOnly(inode.i_mode)) {
            SetFlag(FDI->FileAttributes, FILE_ATTRIBUTE_READONLY);
        }

        if (S_ISDIR(inode.i_mode))
            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);
        FFI->NextEntryOffset = 0;

        FFI->FileIndex = FileIndex;
        FFI->CreationTime = RfsdSysTime(inode.i_ctime);
        FFI->LastAccessTime = RfsdSysTime(inode.i_atime);
        FFI->LastWriteTime = RfsdSysTime(inode.i_mtime);
        FFI->ChangeTime = RfsdSysTime(inode.i_mtime);
        FFI->EndOfFile.QuadPart = FileSize;
        FFI->AllocationSize.QuadPart = AllocationSize;
        FFI->FileAttributes = FILE_ATTRIBUTE_NORMAL;

        if (IsFlagOn(Vcb->Flags, VCB_READ_ONLY)  || RfsdIsReadOnly(inode.i_mode)) {
            SetFlag(FFI->FileAttributes, FILE_ATTRIBUTE_READONLY);
        }

        if (S_ISDIR(inode.i_mode))
            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);
        FBI->NextEntryOffset = 0;

        FBI->CreationTime = RfsdSysTime(inode.i_ctime);
        FBI->LastAccessTime = RfsdSysTime(inode.i_atime);
        FBI->LastWriteTime = RfsdSysTime(inode.i_mtime);
        FBI->ChangeTime = RfsdSysTime(inode.i_mtime);

        FBI->FileIndex = FileIndex;
        FBI->EndOfFile.QuadPart = FileSize;
        FBI->AllocationSize.QuadPart = AllocationSize;
        FBI->FileAttributes = FILE_ATTRIBUTE_NORMAL;

        if (FlagOn(Vcb->Flags, VCB_READ_ONLY)  || RfsdIsReadOnly(inode.i_mode)) {
            SetFlag(FBI->FileAttributes, FILE_ATTRIBUTE_READONLY);
        }

        if (S_ISDIR(inode.i_mode))
            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);        
		FNI->NextEntryOffset = 0;

        FNI->FileNameLength = NameLength;
        RtlCopyMemory(FNI->FileName, pName->Buffer, NameLength);
        dwBytes = InfoLength + NameLength - sizeof(WCHAR); 

        break;
        
    default:
        break;
    }

    return dwBytes;
}

/**
caller suplies a ptr to a file obj for an open target dir, a search pattern to use when listing, and a spec of the info requested.
FSD expected to search and return matching info [503]

The Fcb->RfsdMcb->Key will determine which directory to list the contents of.
*/
NTSTATUS
RfsdQueryDirectory (IN PRFSD_IRP_CONTEXT IrpContext)
{
    PDEVICE_OBJECT          DeviceObject;
    NTSTATUS                Status = STATUS_UNSUCCESSFUL;
    PRFSD_VCB               Vcb;
    PFILE_OBJECT            FileObject;
    PRFSD_FCB               Fcb;
    PRFSD_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;
    PRFSD_KEY_IN_MEMORY		pQueryKey;				// The key of the directory item that is being retrieved
    BOOLEAN                 FcbResourceAcquired = FALSE;
    ULONG                   UsedLength = 0;

    __try {

        ASSERT(IrpContext);
        
        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;
            __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;
		pQueryKey = &(Fcb->RfsdMcb->Key);
        
        ASSERT(Fcb);
        
		KdPrint(("QueryDirectory on Key {%x,%x,%x,%x}\n", 
			pQueryKey->k_dir_id, pQueryKey->k_objectid, pQueryKey->k_offset, pQueryKey->k_type));

        //
        // This request is not allowed on volumes
        //
        if (Fcb->Identifier.Type == RFSDVCB) {
            Status = STATUS_INVALID_PARAMETER;
            __leave;
        }
        
        ASSERT((Fcb->Identifier.Type == RFSDFCB) &&
            (Fcb->Identifier.Size == sizeof(RFSD_FCB)));
        
        if (!IsDirectory(Fcb)) {
            Status = STATUS_INVALID_PARAMETER;
            __leave;
        }
        
        Ccb = (PRFSD_CCB) FileObject->FsContext2;
        
        ASSERT(Ccb);
        
        ASSERT((Ccb->Identifier.Type == RFSDCCB) &&
            (Ccb->Identifier.Size == sizeof(RFSD_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_
        

⌨️ 快捷键说明

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