2014年7月10日星期四

minifilter打开/创建的前操作识别目录

#include <fltKernel.h>

PFLT_FILTER gFilterHandle;

/*
打开/创建的前操作的时候判断是不是目录。

打开/创建的前操作不可以用FltIsDirectory,因为第一个参数为空/不可以使用。

made by correy
made at 2014.07.10
homepage:http://correy.webs.com
*/

//这些在WDK 7600.16385.1中没有定义,在WDK8.0中定义了.
//一下代码是解决办法之一.
#ifndef _In_
#define _Inout_
#define _In_
#define _In_opt_
#endif
//另一思路可参考:http://msdn.microsoft.com/zh-cn/library/windows/hardware/ff554695(v=vs.85).aspx


FLT_PREOP_CALLBACK_STATUS CreatePreOPeration(__inout PFLT_CALLBACK_DATA Cbd, __in PCFLT_RELATED_OBJECTS FltObjects, __out PVOID *CompletionContext)
{
    PFLT_FILE_NAME_INFORMATION    pfni;
    NTSTATUS                      status;
    FILE_STANDARD_INFORMATION fsi = {0};
    ULONG  LengthReturned;
    BOOLEAN  IsDirectory = FALSE ;

    //status = FltIsDirectory(FltObjects->FileObject, FltObjects->Instance, &IsDirectory);//FileObject不可用,所以这个函数不可用。
    //if (NT_SUCCESS(status) && IsDirectory) 
    //{  
    //    //如果是目录.
    //}
    //else
    //{
    //    return FLT_PREOP_SUCCESS_NO_CALLBACK;
    //}

    /*
    方法一:
    确信用户打开文件填写的是FILE_NON_DIRECTORY_FILE,打开目录是FILE_DIRECTORY_FILE。
    应用程序没有这个选项,所以过滤应用层是正确的。驱动层的有的程序会填写错误。
    */
    if (!FlagOn( Cbd->Iopb->Parameters.Create.Options, FILE_DIRECTORY_FILE ))
    {
        return FLT_PREOP_SUCCESS_NO_CALLBACK;
    }

    /*
    创建的标志:
    FILE_SUPERSEDE 
    FILE_CREATE 
    FILE_OPEN_IF 
    FILE_OVERWRITE_IF

    打开标志:
    FILE_OPEN  
    FILE_OPEN_IF  
    FILE_OVERWRITE  
    FILE_OVERWRITE_IF 
    注释:FILE_OPEN和FILE_OVERWRITE不会创建。    
    */  

    /*
    方法二:FltQueryInformationFile OR ZwQueryInformationFile。
    最好判断下目的。新建的估计失败,估计是PFILE_OBJECT不存在。
    */
    //status = FltQueryInformationFile(FltObjects->Instance, FltObjects->FileObject, &fsi, sizeof(FILE_STANDARD_INFORMATION), FileStandardInformation, &LengthReturned);
    //if (!NT_SUCCESS( status )) 
    //{
    //    return FLT_PREOP_SUCCESS_NO_CALLBACK;
    //}
    //if (fsi.Directory != TRUE )
    //{
    //    return FLT_PREOP_SUCCESS_NO_CALLBACK;
    //}

    /*
    FltGetFileNameInformation cannot get file name information if the TopLevelIrp field of the current thread is not NULL, 
    because the resulting file system recursion could cause deadlocks or stack overflows. (For more information about this issue, see IoGetTopLevelIrp.) 
    FltGetFileNameInformation cannot get file name information in the paging I/O path. 
    FltGetFileNameInformation cannot get file name information in the post-close path. 
    FltGetFileNameInformation cannot get the short name of a file in the pre-create path. 
    */
    if (FlagOn(Cbd->Iopb->IrpFlags, IRP_PAGING_IO) || FlagOn(Cbd->Iopb->IrpFlags, IRP_SYNCHRONOUS_PAGING_IO) || IoGetTopLevelIrp()) //IRP_NOCACHE
    {
        return FLT_PREOP_SUCCESS_NO_CALLBACK;
    }
    
    status = FltGetFileNameInformation( Cbd, FLT_FILE_NAME_NORMALIZED | FLT_FILE_NAME_QUERY_DEFAULT, &pfni);    
    if (!NT_SUCCESS( status )) 
    {
        return FLT_PREOP_SUCCESS_NO_CALLBACK;
    }

    status = FltParseFileNameInformation(pfni);
    if (!NT_SUCCESS( status )) 
    {
        FltReleaseFileNameInformation(pfni); 
        return FLT_PREOP_SUCCESS_NO_CALLBACK;
    }

    KdPrint(("目录:%wZ\n", &pfni->Name));

    FltReleaseFileNameInformation(pfni);

    return FLT_PREOP_SUCCESS_NO_CALLBACK;
}


CONST FLT_OPERATION_REGISTRATION Callbacks[] = {
    { IRP_MJ_CREATE,  0, CreatePreOPeration, 0},
    { IRP_MJ_OPERATION_END }
};


#pragma PAGEDCODE
NTSTATUS PtInstanceQueryTeardown (__in PCFLT_RELATED_OBJECTS FltObjects,__in FLT_INSTANCE_QUERY_TEARDOWN_FLAGS Flags)
{
    return STATUS_SUCCESS;
}


#pragma PAGEDCODE//#pragma alloc_text(PAGE, PtUnload)
NTSTATUS PtUnload (__in FLT_FILTER_UNLOAD_FLAGS Flags)
{
    FltUnregisterFilter( gFilterHandle );
    return STATUS_SUCCESS;
}


CONST FLT_REGISTRATION FilterRegistration = {
    sizeof( FLT_REGISTRATION ),         //  Size
    FLT_REGISTRATION_VERSION,           //  Version
    0,                                  //  Flags
    NULL,                               //  Context
    Callbacks,                          //  Operation callbacks
    PtUnload,                           //  MiniFilterUnload
    NULL,                               //  InstanceSetup
    PtInstanceQueryTeardown,            //  InstanceQueryTeardown
    NULL,                               //  InstanceTeardownStart
    NULL,                               //  InstanceTeardownComplete
    NULL,                               //  GenerateFileName
    NULL,                               //  GenerateDestinationFileName
    NULL                                //  NormalizeNameComponent
};


DRIVER_INITIALIZE DriverEntry;
#pragma alloc_text(INIT, DriverEntry)//#pragma INITCODE
NTSTATUS DriverEntry (_In_ PDRIVER_OBJECT DriverObject, _In_ PUNICODE_STRING RegistryPath)
{
    NTSTATUS status;

    UNREFERENCED_PARAMETER( RegistryPath );

    KdBreakPoint();

    status = FltRegisterFilter( DriverObject, &FilterRegistration, &gFilterHandle );
    if (!NT_SUCCESS( status )) //FLT_ASSERT( NT_SUCCESS( status ) );
    {        
        return status;
    }

    status = FltStartFiltering( gFilterHandle );
    if (!NT_SUCCESS( status )) {
        FltUnregisterFilter( gFilterHandle );
    }

    return status;
}

没有评论:

发表评论