2013年8月1日星期四

Minifilter禁止创建文件或者文件夹

/*
禁止创建文件或者文件夹。

很简单,也值得收藏。

这里没有加禁止的条件,所以整个计算机都不可以。

注意:
1.普通的删除,就是移往回收站的操作也会拦截,会失败。
2.对网络文件无效,如本地的网络盘符(不是本地盘符),即路径的前面有\\Device\\Mup的,这种情况下会弹出问题。
3.对于subst创建的盘符依然有效。
4.对于本地的共享在远程的操作依然有效。

made by correy
made at 2013.08.01
email:kouleguan at hotmail dot com
homepage:http://correy.webs.com
*/

#include <fltKernel.h>

PFLT_FILTER gFilterHandle;
ULONG_PTR OperationStatusCtx = 1;

#define PT_DBG_PRINT( _dbgLevel, _string )        (FlagOn(1,(_dbgLevel)) ?  DbgPrint _string :  ((int)0))

VOID PtOperationStatusCallback (__in PCFLT_RELATED_OBJECTS FltObjects,__in PFLT_IO_PARAMETER_BLOCK ParameterSnapshot,__in NTSTATUS OperationStatus,__in PVOID RequesterContext)
{
    PT_DBG_PRINT( 2,("PassThrough!PtOperationStatusCallback: Status=%08x ctx=%p IrpMj=%02x.%02x \"%s\"\n",
        OperationStatus,RequesterContext,ParameterSnapshot->MajorFunction,ParameterSnapshot->MinorFunction, FltGetIrpName(ParameterSnapshot->MajorFunction)) );
}

BOOLEAN PtDoRequestOperationStatus(__in PFLT_CALLBACK_DATA Data)
{
    PFLT_IO_PARAMETER_BLOCK iopb = Data->Iopb;
    return (BOOLEAN)( ( (iopb->MajorFunction == IRP_MJ_FILE_SYSTEM_CONTROL) &&
        ((iopb->Parameters.FileSystemControl.Common.FsControlCode == FSCTL_REQUEST_FILTER_OPLOCK)  ||
        (iopb->Parameters.FileSystemControl.Common.FsControlCode == FSCTL_REQUEST_BATCH_OPLOCK)   ||
        (iopb->Parameters.FileSystemControl.Common.FsControlCode == FSCTL_REQUEST_OPLOCK_LEVEL_1) ||
        (iopb->Parameters.FileSystemControl.Common.FsControlCode == FSCTL_REQUEST_OPLOCK_LEVEL_2))) ||
        ((iopb->MajorFunction == IRP_MJ_DIRECTORY_CONTROL) && (iopb->MinorFunction == IRP_MN_NOTIFY_CHANGE_DIRECTORY)));
}

FLT_PREOP_CALLBACK_STATUS CreatePreOperation (__inout PFLT_CALLBACK_DATA Data,__in PCFLT_RELATED_OBJECTS FltObjects,__deref_out_opt PVOID *CompletionContext)
{
    NTSTATUS status;

    if (PtDoRequestOperationStatus( Data )) 
    {
        status = FltRequestOperationStatusCallback( Data,PtOperationStatusCallback,(PVOID)(++OperationStatusCtx) );
        if (!NT_SUCCESS(status)) {
            PT_DBG_PRINT( 2,("FltRequestOperationStatusCallback Failed, status=%08x\n",status) );
        }
    }
    return FLT_PREOP_SUCCESS_WITH_CALLBACK;
}

FLT_POSTOP_CALLBACK_STATUS CreatePostOperation (__inout PFLT_CALLBACK_DATA Data,__in PCFLT_RELATED_OBJECTS FltObjects,
                                                       __in_opt PVOID CompletionContext,__in FLT_POST_OPERATION_FLAGS Flags)
{
    PFLT_FILE_NAME_INFORMATION    pfni;
    NTSTATUS                      status;
    FILE_DISPOSITION_INFORMATION  fdi;
    BOOLEAN  IsDirectory = FALSE ;
    
    if ( !NT_SUCCESS( Data->IoStatus.Status ) || ( STATUS_REPARSE == Data->IoStatus.Status ) ) // If we have an error then just exit
    {
        return FLT_POSTOP_FINISHED_PROCESSING;
    }

    /*
    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(Data->Iopb->IrpFlags, IRP_PAGING_IO) || FlagOn(Data->Iopb->IrpFlags, IRP_SYNCHRONOUS_PAGING_IO) || IoGetTopLevelIrp()) //IRP_NOCACHE
    {
        return FLT_POSTOP_FINISHED_PROCESSING;
    }

    status = FltGetFileNameInformation( Data, FLT_FILE_NAME_NORMALIZED | FLT_FILE_NAME_QUERY_DEFAULT, &pfni);    
    if (!NT_SUCCESS( status )) // If we could not get the name information then exit
    {
        return FLT_POSTOP_FINISHED_PROCESSING;
    }

    FltParseFileNameInformation(pfni);

    //一个有用的函数,还有FsRtlIsDbcsInExpression。
    //FsRtlIsNameInExpression( &gProtectedData->NameInfo.VolumeName, &FNameInfo->Volume, TRUE, NULL )

    //判断操作意图。
    //if ( FltObjects->FileObject->DeletePending || FltObjects->FileObject->WriteAccess || FltObjects->FileObject->DeleteAccess ||
    //     FltObjects->FileObject->SharedWrite || FltObjects->FileObject->SharedDelete) 
    {
        if ( Data->IoStatus.Information == FILE_CREATED ) //如果是新建操作。
        {
            status = FltIsDirectory(FltObjects->FileObject, FltObjects->Instance, &IsDirectory);//在打开的前操作中FileObject不可用,所以这个函数不可用。
            if (NT_SUCCESS(status) && IsDirectory) //如果是目录.
            {  
                //这两行最好加上,不然出其他问题。
                fdi.DeleteFile = TRUE;
                FltSetInformationFile( FltObjects->Instance, FltObjects->FileObject, &fdi, sizeof( FILE_DISPOSITION_INFORMATION ), FileDispositionInformation );

                /*
                Callers of FltCancelFileOpen must be running at IRQL <= APC_LEVEL.
                However, a minifilter driver can safely call this routine from a post-create callback routine, because, for IRP_MJ_CREATE operations, the postoperation callback routine is called at IRQL = PASSIVE_LEVEL, in the context of the thread that originated the create operation. 
                */
                FltCancelFileOpen( FltObjects->Instance, FltObjects->FileObject );//干掉句柄。

                Data->IoStatus.Status = STATUS_ACCESS_DENIED;
                Data->IoStatus.Information = 0;
            }            
        }
    }    

    FltReleaseFileNameInformation(pfni);           
    
    return FLT_POSTOP_FINISHED_PROCESSING;
}

FLT_PREOP_CALLBACK_STATUS PtPreOperationNoPostOperationPassThrough (__inout PFLT_CALLBACK_DATA Data,__in PCFLT_RELATED_OBJECTS FltObjects,__deref_out_opt PVOID *CompletionContext)
{
    return FLT_PREOP_SUCCESS_NO_CALLBACK;
}

CONST FLT_OPERATION_REGISTRATION Callbacks[] = {
    { IRP_MJ_CREATE, 0, CreatePreOperation, CreatePostOperation},
    { IRP_MJ_SHUTDOWN, 0, PtPreOperationNoPostOperationPassThrough, NULL },   //post operations not supported
    { IRP_MJ_OPERATION_END }
};

#pragma PAGEDCODE
NTSTATUS PtInstanceSetup (__in PCFLT_RELATED_OBJECTS FltObjects,__in FLT_INSTANCE_SETUP_FLAGS Flags,__in DEVICE_TYPE VolumeDeviceType,__in FLT_FILESYSTEM_TYPE VolumeFilesystemType)
{
    return STATUS_SUCCESS;
}

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

#pragma PAGEDCODE
VOID PtInstanceTeardownStart (__in PCFLT_RELATED_OBJECTS FltObjects,__in FLT_INSTANCE_TEARDOWN_FLAGS Flags)
{

}

#pragma PAGEDCODE
VOID PtInstanceTeardownComplete (__in PCFLT_RELATED_OBJECTS FltObjects,__in FLT_INSTANCE_TEARDOWN_FLAGS Flags)
{

}

#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
    PtInstanceSetup,                    //  InstanceSetup
    PtInstanceQueryTeardown,            //  InstanceQueryTeardown
    PtInstanceTeardownStart,            //  InstanceTeardownStart
    PtInstanceTeardownComplete,         //  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();//DbgBreakPoint() 
    
    status = FltRegisterFilter( DriverObject, &FilterRegistration, &gFilterHandle );//  Register with FltMgr to tell it our callback routines    
    if (NT_SUCCESS( status )) //FLT_ASSERT( NT_SUCCESS( status ) );
    {        
        status = FltStartFiltering( gFilterHandle );//  Start filtering i/o
        if (!NT_SUCCESS( status )) {
            FltUnregisterFilter( gFilterHandle );
        }
    }

    return status;
}

没有评论:

发表评论