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

📄 dirctl.c

📁 一个windows 文件系统驱动源码
💻 C
📖 第 1 页 / 共 2 页
字号:
            {
                Status = STATUS_INSUFFICIENT_RESOURCES;
                __leave;
            }
            
            RtlCopyMemory(
                Ccb->DirectorySearchPattern.Buffer,
                L"*\0", 2);
        }
        
        if (!IndexSpecified)
        {
            if (RestartScan || FirstQuery)
            {
                FileIndex = Fcb->Ext2Mcb->DeOffset = 0;
            }
            else
            {
                FileIndex = Ccb->CurrentByteOffset;
            }
        }
        
        Inode = (PEXT2_INODE) ExAllocatePool(
            PagedPool,
            sizeof(EXT2_INODE));
        
        if (Inode == NULL)
        {
            Status = STATUS_INSUFFICIENT_RESOURCES;
            __leave;
        }
        
        RtlZeroMemory(Buffer, Length);

        if (Fcb->ext2_inode->i_size <= FileIndex)
        {
            Status = STATUS_NO_MORE_FILES;
            __leave;
        }
        
        pDir = ExAllocatePool(PagedPool,
                sizeof(EXT2_DIR_ENTRY2));
        if (!pDir)
        {
            Status = STATUS_INSUFFICIENT_RESOURCES;
            __leave;
        }
        
        dwBytes = 0;
        dwSize = Fcb->ext2_inode->i_size - FileIndex - (sizeof(EXT2_DIR_ENTRY2) - EXT2_NAME_LEN + 1);

        ByteOffset = FileIndex;

        dwTemp = 0;
        
        while (bRun && UsedLength < Length  && dwBytes < dwSize)
        {
            RtlZeroMemory(pDir, sizeof(EXT2_DIR_ENTRY2));

            Status = Ext2ReadInode(
                        NULL,
                        Vcb,
                        Fcb->ext2_inode,
                        ByteOffset,
                        (PVOID)pDir,
                        sizeof(EXT2_DIR_ENTRY2),
                        &dwReturn);

            if (!NT_SUCCESS(Status))
            {
                __leave;
            }

            if (!pDir->inode)
            {
                bRun = FALSE;
                break;
            }

            InodeFileNameLength = pDir->name_len & 0xff;
            
            InodeFileName.Length = InodeFileName.MaximumLength =
                InodeFileNameLength * 2;
            
            if (InodeFileName.Length <= 0)
                break;

            InodeFileName.Buffer = ExAllocatePool(
                PagedPool,
                InodeFileNameLength * 2 + 2);

            if (!InodeFileName.Buffer)
            {
                Status = STATUS_INSUFFICIENT_RESOURCES;
                __leave;
            }

            RtlZeroMemory(InodeFileName.Buffer, InodeFileNameLength * 2 + 2);
            
            Ext2CharToWchar(
                InodeFileName.Buffer,
                pDir->name,
                InodeFileNameLength );

            if (FsRtlDoesNameContainWildCards(&(Ccb->DirectorySearchPattern)) ?
                FsRtlIsNameInExpression(
                    &(Ccb->DirectorySearchPattern),
                    &InodeFileName,
                    TRUE,
                    NULL) :
                !RtlCompareUnicodeString(
                    &(Ccb->DirectorySearchPattern),
                    &InodeFileName,
                    TRUE)           )
            {
                dwReturn = Ext2ProcessDirEntry(
                    Vcb, FileInformationClass,
                    pDir->inode, Buffer, UsedLength, Length - UsedLength,
                    dwBytes, &InodeFileName,
                    ReturnSingleEntry );

                if (dwReturn <= 0)
                {
                    bRun = FALSE;
                }
                else
                {
                    dwTemp = UsedLength;
                    UsedLength += dwReturn;
                }
            }
            
            if (InodeFileName.Buffer != NULL)
            {
                ExFreePool(InodeFileName.Buffer);
                InodeFileName.Buffer = NULL;
            }
            
            if (bRun)
            {
                dwBytes +=pDir->rec_len;
                Ccb->CurrentByteOffset = FileIndex + dwBytes;
            }

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

            ByteOffset = FileIndex + dwBytes;
        }

        FileIndex += dwBytes;

        ((PULONG)((PUCHAR)Buffer + dwTemp)) [0] = 0;

        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 (Inode != NULL)
        {
            ExFreePool(Inode);
        }
        
        if (pDir != NULL)
        {
            ExFreePool(pDir);
            pDir = NULL;
        }
        
        if (InodeFileName.Buffer != NULL)
        {
            ExFreePool(InodeFileName.Buffer);
        }
        
        if (!IrpContext->ExceptionInProgress)
        {
            if (Status == STATUS_PENDING)
            {
                Status = Ext2LockUserBuffer(
                    IrpContext->Irp,
                    Length,
                    IoWriteAccess );
                
                if (NT_SUCCESS(Status))
                {
                    Status = Ext2QueueRequest(IrpContext);
                }
                else
                {
                    IrpContext->Irp->IoStatus.Status = Status;
                    Ext2CompleteRequest(IrpContext->Irp, IO_NO_INCREMENT);
                    Ext2FreeIrpContext(IrpContext);
                }
            }
            else
            {
                IrpContext->Irp->IoStatus.Information = UsedLength;
                IrpContext->Irp->IoStatus.Status = Status;
                
                Ext2CompleteRequest(
                    IrpContext->Irp,
                    (CCHAR)
                    (NT_SUCCESS(Status) ? IO_DISK_INCREMENT : IO_NO_INCREMENT));
                
                Ext2FreeIrpContext(IrpContext);
            }
        }
    }
    
    return Status;
}

NTSTATUS
Ext2NotifyChangeDirectory (
    IN PEXT2_IRP_CONTEXT IrpContext
    )
{
    PDEVICE_OBJECT      DeviceObject;
    BOOLEAN             CompleteRequest;
    NTSTATUS            Status = STATUS_UNSUCCESSFUL;
    PEXT2_VCB           Vcb;
    PFILE_OBJECT        FileObject;
    PEXT2_FCB           Fcb;
    PIRP                Irp;
    PIO_STACK_LOCATION  IrpSp;
    ULONG               CompletionFilter;
    BOOLEAN             WatchTree;

    __try
    {
        ASSERT(IrpContext);

        ASSERT((IrpContext->Identifier.Type == EXT2ICX) &&
               (IrpContext->Identifier.Size == sizeof(EXT2_IRP_CONTEXT)));

        //
        //  Always set the wait flag in the Irp context for the original request.
        //

        SetFlag( IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT );

        DeviceObject = IrpContext->DeviceObject;

        if (DeviceObject == gExt2Global->DeviceObject)
        {
            CompleteRequest = TRUE;
            Status = STATUS_INVALID_DEVICE_REQUEST;
            __leave;
        }

        Vcb = (PEXT2_VCB) DeviceObject->DeviceExtension;

        ASSERT(Vcb != NULL);

        ASSERT((Vcb->Identifier.Type == EXT2VCB) &&
               (Vcb->Identifier.Size == sizeof(EXT2_VCB)));

        FileObject = IrpContext->FileObject;

        Fcb = (PEXT2_FCB) FileObject->FsContext;

        ASSERT(Fcb);

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

        ASSERT((Fcb->Identifier.Type == EXT2FCB) &&
               (Fcb->Identifier.Size == sizeof(EXT2_FCB)));

        if (!FlagOn(Fcb->Ext2Mcb->FileAttr, 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 // _GNU_NTIFS_

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

#endif // _GNU_NTIFS_

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

        CompleteRequest = FALSE;

        Status = STATUS_PENDING;

        {
            UNICODE_STRING FullFileName;

            if (Ext2GetFullFileName(Fcb->Ext2Mcb, &FullFileName))
            {
                FsRtlNotifyFullChangeDirectory(Vcb->NotifySync,
                                        &Vcb->NotifyList,
                                        FileObject->FsContext2,
                                        (PSTRING)&FullFileName,
                                        WatchTree,
                                        FALSE,
                                        CompletionFilter,
                                        Irp,
                                        NULL,
                                        NULL );


                ExFreePool(FullFileName.Buffer);
            }
        }

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

    ANSI_STRING TestString;
    USHORT      FileNamePartLength;

    RtlInitAnsiString(&TestString, "\\ntifs.h");
    FileNamePartLength = 7;

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

    or

    ANSI_STRING TestString;

    RtlInitAnsiString(&TestString, "\\ntifs.h");
    FsRtlNotifyFullReportChange(
        Vcb->NotifySync,            // PNOTIFY_SYNC NotifySync
        &Vcb->NotifyList,           // PLIST_ENTRY  NotifyList
        &TestString,                // PSTRING      FullTargetName
        1,                          // USHORT       TargetNameOffset
        NULL,                       // PSTRING      StreamName OPTIONAL
        NULL,                       // PSTRING      NormalizedParentName OPTIONAL
        FILE_NOTIFY_CHANGE_NAME,    // ULONG        FilterMatch
        0,                          // ULONG        Action
        NULL                        // PVOID        TargetContext
        );
*/

    }
    __finally
    {
        if (!IrpContext->ExceptionInProgress)
        {
            if (CompleteRequest)
            {
                IrpContext->Irp->IoStatus.Status = Status;

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

            Ext2FreeIrpContext(IrpContext);
        }
    }

    return Status;
}



NTSTATUS
Ext2DirectoryControl (IN PEXT2_IRP_CONTEXT IrpContext)
{
    NTSTATUS Status;
    
    ASSERT(IrpContext);
    
    ASSERT((IrpContext->Identifier.Type == EXT2ICX) &&
        (IrpContext->Identifier.Size == sizeof(EXT2_IRP_CONTEXT)));
    
    switch (IrpContext->MinorFunction)
    {
    case IRP_MN_QUERY_DIRECTORY:
        Status = Ext2QueryDirectory(IrpContext);
        break;

    case IRP_MN_NOTIFY_CHANGE_DIRECTORY:
        Status = Ext2NotifyChangeDirectory(IrpContext);
        break;
        
    default:
        Status = STATUS_INVALID_DEVICE_REQUEST;
        IrpContext->Irp->IoStatus.Status = Status;
        Ext2CompleteRequest(IrpContext->Irp, IO_NO_INCREMENT);
        Ext2FreeIrpContext(IrpContext);
    }
    
    return Status;
}

⌨️ 快捷键说明

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