首页
社区
课程
招聘
[分享]judge IRP_MJ_CREATE CreateDisposition on minifilter
发表于: 2013-7-24 01:22 4745

[分享]judge IRP_MJ_CREATE CreateDisposition on minifilter

2013-7-24 01:22
4745
为了判断文件建立时, 是否有可能建立新文件. 找了些资料, 只看到
Data->Iopb->Parameters.Create.Options >> 24

为什么? 见到的例子中都没说...
代码中没有注释害死人啊.
/// @file       IrpOptCallBack.c
/// @brief      ...

#include "IrpOptCallBack.h"

#include "DebugDefine.h"

BOOLEAN CbdIsCreateFile(PFLT_CALLBACK_DATA Data)
{
    /// Wdk's help : Options define
    /// The low 24 bits contains CreateOptions flag values.
    /// The high 8 bits contains the CreateDisposition values.
    
    /**
    CreateDisposition Define
    FILE_SUPERSEDE 
        If the file already exists, replace it with the given file. 
        If it does not, create the given file.  
    FILE_CREATE  
        If the file already exists, fail the request and do not create 
        or open the given file. If it does not, create the given file. 
    FILE_OPEN  
        If the file already exists, open it instead of creating a new 
        file. If it does not, fail the request and do not create a new file. 
    FILE_OPEN_IF 
        If the file already exists, open it. If it does not, create the 
        given file. 
    FILE_OVERWRITE 
        If the file already exists, open it and overwrite it. 
        If it does not, fail the request. 
    FILE_OVERWRITE_IF If the file already exists, open it and overwrite 
        it. If it does not, create the given file. 
    */

    DWORD   dwCreateDisposition =   0;
    
    ASSERT(IRP_MJ_CREATE == Data->Iopb->MajorFunction);

    dwCreateDisposition = Data->Iopb->Parameters.Create.Options >> 24;

    /// 除了FILE_OPEN, 都有可能建立新文件
    return ((FILE_SUPERSEDE == dwCreateDisposition)
            || (FILE_CREATE == dwCreateDisposition)
            || (FILE_OPEN_IF == dwCreateDisposition)
            || (FILE_OVERWRITE == dwCreateDisposition)
            || (FILE_OVERWRITE_IF == dwCreateDisposition));
}

FLT_PREOP_CALLBACK_STATUS
PreOpCallback_Create(
    __inout PFLT_CALLBACK_DATA Data,
    __in PCFLT_RELATED_OBJECTS FltObjects,
    __deref_out_opt PVOID *CompletionContext)
{
    PFLT_FILE_NAME_INFORMATION nameInfo = NULL;
    NTSTATUS status;
    FLT_PREOP_CALLBACK_STATUS FltRc = FLT_PREOP_SUCCESS_NO_CALLBACK;
    WCHAR name[MAX_PATH];
    
    if (   (Data->Iopb->IrpFlags & IRP_PAGING_IO) 
        || (Data->Iopb->IrpFlags & IRP_SYNCHRONOUS_PAGING_IO)
        || IoGetTopLevelIrp())
    {
        return FltRc;
    }

    if (IRP_MJ_SHUTDOWN == Data->Iopb->MajorFunction)
        return FltRc;
        
    if ( !NT_SUCCESS( Data->IoStatus.Status ) 
         || (STATUS_REPARSE == Data->IoStatus.Status)) 
        {
            return FltRc;
        }

    /// @todo 如果得到文件名失败, 需要参照MiniSpy的另外2种方法继续取文件名
    /// 现在按照简单的方法搞
    status = FltGetFileNameInformation(
                Data,
                FLT_FILE_NAME_NORMALIZED |
                FLT_FILE_NAME_QUERY_DEFAULT,
                &nameInfo);

    ///  Use the name if we got it else use a default name
    if (NT_SUCCESS(status))
    {
        /// Parse the name if requested
        FltParseFileNameInformation(nameInfo);

        
        //
        //  Compare to see if this is the magic file whose I/O is to be pended.
        //

        if (0 != RtlCompareUnicodeString(   &nameInfo->Extension,
                                            &g_ObjFilePostFix,
                                            TRUE))
        {
            goto _PreOpCallback_Create_END;
        }

        if (CbdIsCreateFile(Data))
        {
            /// use the name
            /// @todo nameInfo中的整理工作
            /// 根据Volume, 将逻辑分区转换出来
            /// 要根据Stream, 从FinalComponent中将文件名剥离出来
            /// 就可以得到全路径的普通文件名
            /// c:\\forTest\\test.txt
            /// 如果需要文件名前缀名称, 根据Extension
            /**
            nameInfo->Volume = \Device\HarddiskVolume1 
            nameInfo->ParentDir = \fortest\ 
            nameInfo->FinalComponent = test.txt:Docf_QebiesnrMkudrfcoIaamtykdDa 
            nameInfo->Stream = :Docf_QebiesnrMkudrfcoIaamtykdDa 
            */
            DebugTrace(DBGLOG_INFO, 
                        ("nameInfo->Volume = %wZ\r\n"
                        "nameInfo->ParentDir = %wZ\r\n"
                        "nameInfo->FinalComponent = %wZ\r\n"
                        "nameInfo->Stream = %wZ\r\n", 
                        &nameInfo->Volume,
                        &nameInfo->ParentDir,
                        &nameInfo->FinalComponent,
                        &nameInfo->Stream));

            Data->IoStatus.Information = 0;

            /// 防止新建文件, 就在 PreOpCallback_Create 做
            /// 不需要在 PostOpCallback_Create 中做
            
            /// @todo
            /// 加入队列, 置Pending标记, 发到r3裁决
            /// 新建一个文件, 直接提示, "文件无法建立"
			Data->IoStatus.Status = STATUS_ACCESS_DENIED;
			FltRc = FLT_PREOP_COMPLETE;
			goto _PreOpCallback_Create_END;
        }

        /// 不加入队列, 只返回 FLT_PREOP_PENDING 的效果
        /// 已经建立的txt文件打开, 经过这
        
        /// 打开已有的txt文件, 记事本被定住了.无法响应.
        /// 窗口能拖动, 菜单条和编辑区, 都没反应
        
        /// 关闭虚拟机也关闭不了~
        // FltRc = FLT_PREOP_PENDING;

        /// 这个是可以的, 允许打开已经建立的文件
        /// 但是编辑后保存, 就被拦住了
        FltRc = FLT_PREOP_SUCCESS_NO_CALLBACK;
    }
    else
        FltRc = FLT_POSTOP_FINISHED_PROCESSING;

_PreOpCallback_Create_END:

    /// Release the name information structure (if defined)
    if (NULL != nameInfo)
        FltReleaseFileNameInformation(nameInfo);
 
    return FltRc;
}

[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!

收藏
免费 0
支持
分享
最新回复 (0)
游客
登录 | 注册 方可回帖
返回
//