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

📄 dirctl.c

📁 I want to provide an example file system driver for Windows NT/2000/XP. For some time I have worked
💻 C
📖 第 1 页 / 共 3 页
字号:
/*
    This is a romfs file system driver for Windows NT/2000/XP.
    Copyright (C) 1999, 2000, 2001, 2002 Bo Brant閚.
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.
    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.
    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*/

#include "ntifs.h"
#include "fsd.h"
#include "rom_fs.h"
#include "border.h"

#pragma code_seg(FSD_PAGED_CODE)

NTSTATUS
FsdDirectoryControl (
    IN PFSD_IRP_CONTEXT IrpContext
    )
{
    NTSTATUS Status;

    ASSERT(IrpContext);

    ASSERT((IrpContext->Identifier.Type == ICX) &&
           (IrpContext->Identifier.Size == sizeof(FSD_IRP_CONTEXT)));

    switch (IrpContext->MinorFunction)
    {
    case IRP_MN_QUERY_DIRECTORY:
        Status = FsdQueryDirectory(IrpContext);
        break;

    case IRP_MN_NOTIFY_CHANGE_DIRECTORY:
        Status = FsdNotifyChangeDirectory(IrpContext);
        break;

    default:
        Status = STATUS_INVALID_DEVICE_REQUEST;
        IrpContext->Irp->IoStatus.Status = Status;
        FsdCompleteRequest(IrpContext->Irp, IO_NO_INCREMENT);
        FsdFreeIrpContext(IrpContext);
    }

    return Status;
}

NTSTATUS
FsdQueryDirectory (
    IN PFSD_IRP_CONTEXT IrpContext
    )
{
    PDEVICE_OBJECT          DeviceObject;
    NTSTATUS                Status = STATUS_UNSUCCESSFUL;
    PFSD_VCB                Vcb;
    PFILE_OBJECT            FileObject;
    PFSD_FCB                Fcb;
    PFSD_CCB                Ccb;
    PIRP                    Irp;
    PIO_STACK_LOCATION      IrpSp;
    FILE_INFORMATION_CLASS  FileInformationClass;
    ULONG                   Length;
    PUNICODE_STRING         FileName;
    UNICODE_STRING          UpcaseFileName;
    ULONG                   FileIndex;
    BOOLEAN                 RestartScan;
    BOOLEAN                 ReturnSingleEntry;
    BOOLEAN                 IndexSpecified;
    PUCHAR                  UserBuffer;
    BOOLEAN                 FirstQuery;
    struct romfs_inode*     Inode = NULL;
    BOOLEAN                 FcbResourceAcquired = FALSE;
    ULONG                   QueryBlockLength;
    ULONG                   UsedLength = 0;
    USHORT                  InodeFileNameLength;
    UNICODE_STRING          InodeFileName;
    PULONG                  NextEntryOffset = NULL;

    UpcaseFileName.Buffer = NULL;
    InodeFileName.Buffer = NULL;

    __try
    {
        ASSERT(IrpContext);

        ASSERT((IrpContext->Identifier.Type == ICX) &&
               (IrpContext->Identifier.Size == sizeof(FSD_IRP_CONTEXT)));

        DeviceObject = IrpContext->DeviceObject;

        if (DeviceObject == FsdGlobalData.DeviceObject)
        {
            Status = STATUS_INVALID_DEVICE_REQUEST;
            __leave;
        }

        Vcb = (PFSD_VCB) DeviceObject->DeviceExtension;

        ASSERT(Vcb != NULL);

        ASSERT((Vcb->Identifier.Type == VCB) &&
               (Vcb->Identifier.Size == sizeof(FSD_VCB)));

        FileObject = IrpContext->FileObject;

        Fcb = (PFSD_FCB) FileObject->FsContext;

        ASSERT(Fcb);

        if (Fcb->Identifier.Type == VCB)
        {
            Status = STATUS_INVALID_PARAMETER;
            __leave;
        }

        ASSERT((Fcb->Identifier.Type == FCB) &&
               (Fcb->Identifier.Size == sizeof(FSD_FCB)));

        if (!FlagOn(Fcb->FileAttributes, FILE_ATTRIBUTE_DIRECTORY))
        {
            Status = STATUS_INVALID_PARAMETER;
            __leave;
        }

        Ccb = (PFSD_CCB) FileObject->FsContext2;

        ASSERT(Ccb);

        ASSERT((Ccb->Identifier.Type == CCB) &&
               (Ccb->Identifier.Size == sizeof(FSD_CCB)));

        Irp = IrpContext->Irp;

        IrpSp = IoGetCurrentIrpStackLocation(Irp);

#ifndef _GNU_NTIFS_

        FileInformationClass =
            IrpSp->Parameters.QueryDirectory.FileInformationClass;

        Length = IrpSp->Parameters.QueryDirectory.Length;

        FileName = IrpSp->Parameters.QueryDirectory.FileName;

        FileIndex = IrpSp->Parameters.QueryDirectory.FileIndex;

#else // _GNU_NTIFS_

        FileInformationClass = ((PEXTENDED_IO_STACK_LOCATION)
            IrpSp)->Parameters.QueryDirectory.FileInformationClass;

        Length = ((PEXTENDED_IO_STACK_LOCATION)
            IrpSp)->Parameters.QueryDirectory.Length;

        FileName = ((PEXTENDED_IO_STACK_LOCATION)
            IrpSp)->Parameters.QueryDirectory.FileName;

        FileIndex = ((PEXTENDED_IO_STACK_LOCATION)
            IrpSp)->Parameters.QueryDirectory.FileIndex;

#endif // _GNU_NTIFS_

        RestartScan = FlagOn(IrpSp->Flags, SL_RESTART_SCAN);
        ReturnSingleEntry = FlagOn(IrpSp->Flags, SL_RETURN_SINGLE_ENTRY);
        IndexSpecified = FlagOn(IrpSp->Flags, SL_INDEX_SPECIFIED);

        if (Irp->RequestorMode != KernelMode &&
            !Irp->MdlAddress &&
            Irp->UserBuffer)
        {
            ProbeForWrite(Irp->UserBuffer, Length, 1);
        }

        UserBuffer = FsdGetUserBuffer(Irp);

        if (UserBuffer == NULL)
        {
            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)
        {
            UpcaseFileName.Length = UpcaseFileName.MaximumLength =
                FileName->Length;

            UpcaseFileName.Buffer =
                FsdAllocatePool(NonPagedPool, FileName->Length, '1iDR');

            if (UpcaseFileName.Buffer == NULL)
            {
                Status = STATUS_INSUFFICIENT_RESOURCES;
                __leave;
            }

            RtlUpcaseUnicodeString(
                &UpcaseFileName,
                FileName,
                FALSE
                );

            FileName = &UpcaseFileName;

            if (Ccb->DirectorySearchPattern.Buffer != NULL)
            {
                FirstQuery = FALSE;
            }
            else
            {
                FirstQuery = TRUE;

                Ccb->DirectorySearchPattern.Length =
                Ccb->DirectorySearchPattern.MaximumLength =
                    FileName->Length;

                Ccb->DirectorySearchPattern.Buffer =
                    FsdAllocatePool(NonPagedPool, FileName->Length, '2iDR');

                if (Ccb->DirectorySearchPattern.Buffer == NULL)
                {
                    Status = STATUS_INSUFFICIENT_RESOURCES;
                    __leave;
                }

                RtlCopyMemory(
                    Ccb->DirectorySearchPattern.Buffer,
                    FileName->Buffer,
                    FileName->Length
                    );
            }
        }
        else if (Ccb->DirectorySearchPattern.Buffer != NULL)
        {
            FirstQuery = FALSE;
            FileName = &Ccb->DirectorySearchPattern;
        }
        else
        {
            FirstQuery = TRUE;

            Ccb->DirectorySearchPattern.Length = sizeof(WCHAR);
            Ccb->DirectorySearchPattern.MaximumLength = sizeof(WCHAR);

            Ccb->DirectorySearchPattern.Buffer =
                FsdAllocatePool(NonPagedPool, sizeof(WCHAR), '3iDR');

            if (Ccb->DirectorySearchPattern.Buffer == NULL)
            {
                Status = STATUS_INSUFFICIENT_RESOURCES;
                __leave;
            }

            RtlCopyMemory(Ccb->DirectorySearchPattern.Buffer, L"*", sizeof(WCHAR));

            FileName = &Ccb->DirectorySearchPattern;
        }

        if (!IndexSpecified)
        {
            if (RestartScan || FirstQuery)
            {
                FileIndex = Fcb->romfs_inode->spec;
            }
            else
            {
                FileIndex = Ccb->CurrentByteOffset;
            }
        }

        if (!(be32_to_cpu(FileIndex) & ROMFH_MASK))
        {
            if (FirstQuery)
            {
                Status = STATUS_NO_SUCH_FILE;
            }
            else
            {
                Status = STATUS_NO_MORE_FILES;
            }
            __leave;
        }

        Inode = (struct romfs_inode*) FsdAllocatePool(
            NonPagedPool,
            sizeof(struct romfs_inode) + ROMFS_MAXFN,
            '4iDR'
            );

        if (Inode == NULL)
        {
            Status = STATUS_INSUFFICIENT_RESOURCES;
            __leave;
        }

        RtlZeroMemory(UserBuffer, Length);

        switch (FileInformationClass)
        {
        case FileDirectoryInformation:
            if (Length < sizeof(FILE_DIRECTORY_INFORMATION))
            {
                Status = STATUS_INFO_LENGTH_MISMATCH;
                __leave;
            }
            QueryBlockLength = sizeof(FILE_DIRECTORY_INFORMATION);
            break;

        case FileFullDirectoryInformation:
            if (Length < sizeof(FILE_FULL_DIR_INFORMATION))
            {
                Status = STATUS_INFO_LENGTH_MISMATCH;
                __leave;
            }
            QueryBlockLength = sizeof(FILE_FULL_DIR_INFORMATION);
            break;

        case FileBothDirectoryInformation:
            if (Length < sizeof(FILE_BOTH_DIR_INFORMATION))
            {
                Status = STATUS_INFO_LENGTH_MISMATCH;
                __leave;
            }
            QueryBlockLength = sizeof(FILE_BOTH_DIR_INFORMATION);
            break;

        case FileNamesInformation:
            if (Length < sizeof(FILE_NAMES_INFORMATION))
            {
                Status = STATUS_INFO_LENGTH_MISMATCH;
                __leave;
            }
            QueryBlockLength = sizeof(FILE_NAMES_INFORMATION);
            break;

#if (VER_PRODUCTBUILD >= 2600)

        case FileIdFullDirectoryInformation:
            if (Length < sizeof(FILE_ID_FULL_DIR_INFORMATION))
            {
                Status = STATUS_INFO_LENGTH_MISMATCH;
                __leave;
            }
            QueryBlockLength = sizeof(FILE_ID_FULL_DIR_INFORMATION);
            break;

        case FileIdBothDirectoryInformation:
            if (Length < sizeof(FILE_ID_BOTH_DIR_INFORMATION))
            {
                Status = STATUS_INFO_LENGTH_MISMATCH;
                __leave;
            }
            QueryBlockLength = sizeof(FILE_ID_BOTH_DIR_INFORMATION);
            break;

#endif // (VER_PRODUCTBUILD >= 2600)

        default:
            Status = STATUS_INVALID_PARAMETER;
            __leave;
        }

        while (UsedLength < Length
           && (be32_to_cpu(FileIndex) & ROMFH_MASK))
        {
            Status = FsdReadInodeByIndex(
                Vcb->TargetDeviceObject,
                FileIndex,
                Inode
                );

            if (!NT_SUCCESS(Status))
            {
                if (!UsedLength)
                {
                    if (FirstQuery)
                    {
                        Status = STATUS_NO_SUCH_FILE;
                    }
                    else
                    {
                        Status = STATUS_NO_MORE_FILES;
                    }
                }
                else
                {
                    Status = STATUS_SUCCESS;
                }
                __leave;
            }

            InodeFileNameLength = (USHORT) strnlen(Inode->name, ROMFS_MAXFN);

⌨️ 快捷键说明

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