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

📄 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 页
字号:
                            SetFlag(
                                Buffer->FileAttributes,
                                FILE_ATTRIBUTE_DIRECTORY
                                );
                        }

#ifndef FSD_RO
                        if (FlagOn(Vcb->Flags, VCB_READ_ONLY))
#endif
                        {
                            SetFlag(
                                Buffer->FileAttributes,
                                FILE_ATTRIBUTE_READONLY
                                );
                        }

                        Buffer->FileNameLength = InodeFileNameLength * 2;

                        Buffer->EaSize = 0;

                        Buffer->FileId = Fcb->IndexNumber;

                        RtlCopyMemory(
                            Buffer->FileName,
                            InodeFileName.Buffer,
                            InodeFileNameLength * 2
                            );

                        UsedLength += QueryBlockLength +
                            InodeFileNameLength * 2 - sizeof(WCHAR);

                        if (!ReturnSingleEntry)
                        {
                            Buffer->NextEntryOffset = QueryBlockLength +
                                InodeFileNameLength * 2 - sizeof(WCHAR) +
                                UsedLength % 8;
                        }
                        else
                        {
                            Buffer->NextEntryOffset = 0;
                        }

                        UsedLength += UsedLength % 8;

                        NextEntryOffset = &Buffer->NextEntryOffset;
                    }
                    break;

                case FileIdBothDirectoryInformation:
                    {
                        PFILE_ID_BOTH_DIR_INFORMATION Buffer;

                        Buffer = (PFILE_ID_BOTH_DIR_INFORMATION)
                            (UserBuffer + UsedLength);

/*
                        typedef struct _FILE_ID_BOTH_DIR_INFORMATION {
                            ULONG           NextEntryOffset;
                            ULONG           FileIndex;
                            LARGE_INTEGER   CreationTime;
                            LARGE_INTEGER   LastAccessTime;
                            LARGE_INTEGER   LastWriteTime;
                            LARGE_INTEGER   ChangeTime;
                            LARGE_INTEGER   EndOfFile;
                            LARGE_INTEGER   AllocationSize;
                            ULONG           FileAttributes;
                            ULONG           FileNameLength;
                            ULONG           EaSize;
                            CCHAR           ShortNameLength;
                            WCHAR           ShortName[12];
                            LARGE_INTEGER   FileId;
                            WCHAR           FileName[1];
                        } FILE_ID_BOTH_DIR_INFORMATION, *PFILE_ID_BOTH_DIR_INFORMATION;
*/

                        Buffer->FileIndex = FileIndex;

                        Buffer->CreationTime.QuadPart = 0;

                        Buffer->LastAccessTime.QuadPart = 0;

                        Buffer->LastWriteTime.QuadPart = 0;

                        Buffer->ChangeTime.QuadPart = 0;

                        Buffer->EndOfFile.QuadPart =
                            be32_to_cpu(Inode->size);

                        Buffer->AllocationSize.QuadPart =
                            be32_to_cpu(Inode->size);

                        Buffer->FileAttributes = FILE_ATTRIBUTE_NORMAL;

                        if (FlagOn(be32_to_cpu(Inode->next), ROMFH_DIR))
                        {
                            SetFlag(
                                Buffer->FileAttributes,
                                FILE_ATTRIBUTE_DIRECTORY
                                );
                        }

#ifndef FSD_RO
                        if (FlagOn(Vcb->Flags, VCB_READ_ONLY))
#endif
                        {
                            SetFlag(
                                Buffer->FileAttributes,
                                FILE_ATTRIBUTE_READONLY
                                );
                        }

                        Buffer->FileNameLength = InodeFileNameLength * 2;

                        Buffer->EaSize = 0;

                        // TODO: Present a short alias

                        // Here we would like to use RtlGenerate8dot3Name but
                        // I don't know how to use the argument
                        // PGENERATE_NAME_CONTEXT

                        // Buffer->ShortNameLength
                        // Buffer->ShortName

                        Buffer->FileId = Fcb->IndexNumber;

                        RtlCopyMemory(
                            Buffer->FileName,
                            InodeFileName.Buffer,
                            InodeFileNameLength * 2
                            );

                        UsedLength += QueryBlockLength +
                            InodeFileNameLength * 2 - sizeof(WCHAR);

                        if (!ReturnSingleEntry)
                        {
                            Buffer->NextEntryOffset = QueryBlockLength +
                                InodeFileNameLength * 2 - sizeof(WCHAR) +
                                UsedLength % 8;
                        }
                        else
                        {
                            Buffer->NextEntryOffset = 0;
                        }

                        UsedLength += UsedLength % 8;

                        NextEntryOffset = &Buffer->NextEntryOffset;
                    }
                    break;

#endif // (VER_PRODUCTBUILD >= 2600)

                }
            }

            if (InodeFileName.Buffer != NULL)
            {
                FsdFreePool(InodeFileName.Buffer);
                InodeFileName.Buffer = NULL;
            }

            Ccb->CurrentByteOffset =
            FileIndex =
                Inode->next;

            if (UsedLength && ReturnSingleEntry)
            {
                Status = STATUS_SUCCESS;
                __leave;
            }
        }

        if (!UsedLength)
        {
            if (FirstQuery)
            {
                Status = STATUS_NO_SUCH_FILE;
            }
            else
            {
                Status = STATUS_NO_MORE_FILES;
            }
        }
        else
        {
            Status = STATUS_SUCCESS;
        }
    }
    __finally
    {
        if (FcbResourceAcquired)
        {
            ExReleaseResourceForThreadLite(
                &Fcb->MainResource,
                ExGetCurrentResourceThread()
                );
        }

        if (UpcaseFileName.Buffer != NULL)
        {
            FsdFreePool(UpcaseFileName.Buffer);
        }

        if (Inode != NULL)
        {
            FsdFreePool(Inode);
        }

        if (InodeFileName.Buffer != NULL)
        {
            FsdFreePool(InodeFileName.Buffer);
        }

        if (NextEntryOffset != NULL)
        {
            *NextEntryOffset = 0;
        }

        if (!AbnormalTermination())
        {
            if (Status == STATUS_PENDING)
            {
                Status = FsdLockUserBuffer(
                    IrpContext->Irp,
                    Length,
                    IoWriteAccess
                    );

                if (NT_SUCCESS(Status))
                {
                    Status = FsdQueueRequest(IrpContext);
                }
                else
                {
                    IrpContext->Irp->IoStatus.Status = Status;
                    FsdCompleteRequest(IrpContext->Irp, IO_NO_INCREMENT);
                    FsdFreeIrpContext(IrpContext);
                }
            }
            else
            {
                IrpContext->Irp->IoStatus.Information = UsedLength;
                IrpContext->Irp->IoStatus.Status = Status;

                FsdCompleteRequest(
                    IrpContext->Irp,
                    (CCHAR)
                    (NT_SUCCESS(Status) ? IO_DISK_INCREMENT : IO_NO_INCREMENT)
                    );

                FsdFreeIrpContext(IrpContext);
            }
        }
    }

    return Status;
}

NTSTATUS
FsdNotifyChangeDirectory (
    IN PFSD_IRP_CONTEXT IrpContext
    )
{
    PDEVICE_OBJECT      DeviceObject;
    BOOLEAN             CompleteRequest;
    NTSTATUS            Status = STATUS_UNSUCCESSFUL;
    PFSD_VCB            Vcb;
    PFILE_OBJECT        FileObject;
    PFSD_FCB            Fcb;
    PIRP                Irp;
    PIO_STACK_LOCATION  IrpSp;
    ULONG               CompletionFilter;
    BOOLEAN             WatchTree;

    __try
    {
        ASSERT(IrpContext);

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

        DeviceObject = IrpContext->DeviceObject;

        if (DeviceObject == FsdGlobalData.DeviceObject)
        {
            CompleteRequest = TRUE;
            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)
        {
            CompleteRequest = TRUE;
            Status = STATUS_INVALID_PARAMETER;
            __leave;
        }

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

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

        Irp = IrpContext->Irp;

        IrpSp = IoGetCurrentIrpStackLocation(Irp);

#ifndef _GNU_NTIFS_

        CompletionFilter =
            IrpSp->Parameters.NotifyDirectory.CompletionFilter;

#else

        CompletionFilter = ((PEXTENDED_IO_STACK_LOCATION)
            IrpSp)->Parameters.NotifyDirectory.CompletionFilter;

#endif

        WatchTree = FlagOn(IrpSp->Flags, SL_WATCH_TREE);

        CompleteRequest = FALSE;

        Status = STATUS_PENDING;

        FsRtlNotifyChangeDirectory(
            Vcb->NotifySync,
            FileObject->FsContext2,
            (PSTRING)&Fcb->FileName,
            &Vcb->NotifyList,
            WatchTree,
            CompletionFilter,
            Irp
            );

/*
    Currently the driver is read-only but here is an example on how to use the
    FsRtl-functions to report a change:

    UNICODE_STRING  TestString;
    USHORT          FileNamePartLength;

    RtlInitUnicodeString(&TestString, L"\\ntifs.h");

    FileNamePartLength = 7 * sizeof(WCHAR);

    FsRtlNotifyReportChange(
        Vcb->NotifySync,                // PNOTIFY_SYNC NotifySync
        &Vcb->NotifyList,               // PLIST_ENTRY  NotifyList
        (PSTRING)&TestString,           // PSTRING      FullTargetName
        &FileNamePartLength,            // PUSHORT      FileNamePartLength
        FILE_NOTIFY_CHANGE_FILE_NAME    // ULONG        FilterMatch
        );

    or

    UNICODE_STRING TestString;

    RtlInitUnicodeString(&TestString, L"\\ntifs.h");

    FsRtlNotifyFullReportChange(
        Vcb->NotifySync,                // PNOTIFY_SYNC NotifySync
        &Vcb->NotifyList,               // PLIST_ENTRY  NotifyList
        (PSTRING)&TestString,           // PSTRING      FullTargetName
        2,                              // USHORT       TargetNameOffset
        NULL,                           // PSTRING      StreamName OPTIONAL
        NULL,                           // PSTRING      NormalizedParentName OPTIONAL
        FILE_NOTIFY_CHANGE_FILE_NAME,   // ULONG        FilterMatch
        FILE_ACTION_ADDED,              // ULONG        Action
        NULL                            // PVOID        TargetContext
        );
*/
    }
    __finally
    {
        if (!AbnormalTermination())
        {
            if (CompleteRequest)
            {
                IrpContext->Irp->IoStatus.Status = Status;

                FsdCompleteRequest(
                    IrpContext->Irp,
                    (CCHAR)
                    (NT_SUCCESS(Status) ? IO_DISK_INCREMENT : IO_NO_INCREMENT)
                    );
            }

            FsdFreeIrpContext(IrpContext);
        }
    }

    return Status;
}

#pragma code_seg() // end FSD_PAGED_CODE

⌨️ 快捷键说明

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