[note] 贴一段能实现文件隐藏的Minifilter
#include <fltKernel.h>
#include <fltKernel.h>
#include <dontuse.h>
#include <suppress.h>
#pragma prefast(disable:__WARNING_ENCODE_MEMBER_FUNCTION_POINTER, "Not valid for kernel mode drivers")
PFLT_FILTER filterHandle;
PWCHAR prefixName = L"invisible";
ULONG prefixLength = 9;
/*************************************************************************
Prototypes
*************************************************************************/
NTSTATUS DriverEntry ( __in PDRIVER_OBJECT DriverObject, __in PUNICODE_STRING RegistryPath );
NTSTATUS PtUnload ( __in FLT_FILTER_UNLOAD_FLAGS Flags );
FLT_POSTOP_CALLBACK_STATUS MjDirectoryControlPostOperation ( __inout PFLT_CALLBACK_DATA Data,
__in PCFLT_RELATED_OBJECTS FltObjects,
__in_opt PVOID CompletionContext,
__in FLT_POST_OPERATION_FLAGS Flags );
BOOLEAN hasPrefix( PWCHAR name, ULONG length );
#ifdef ALLOC_PRAGMA
#pragma alloc_text(INIT, DriverEntry)
#pragma alloc_text(PAGE, PtUnload)
#endif
CONST FLT_OPERATION_REGISTRATION Callbacks[] =
{
{ IRP_MJ_DIRECTORY_CONTROL,
0,
NULL,
MjDirectoryControlPostOperation },
{ IRP_MJ_OPERATION_END }
};
CONST FLT_REGISTRATION FilterRegistration =
{
sizeof( FLT_REGISTRATION ), // Size
FLT_REGISTRATION_VERSION, // Version
0, // Flags
NULL, // Context
Callbacks, // Operation callbacks
PtUnload, // MiniFilterUnload
NULL, // InstanceSetup
NULL, // InstanceQueryTeardown
NULL, // InstanceTeardownStart
NULL, // InstanceTeardownComplete
NULL, // GenerateFileName
NULL, // GenerateDestinationFileName
NULL // NormalizeNameComponent
};
NTSTATUS DriverEntry ( __in PDRIVER_OBJECT DriverObject, __in PUNICODE_STRING RegistryPath )
{
NTSTATUS status;
UNREFERENCED_PARAMETER( RegistryPath );
status = FltRegisterFilter( DriverObject, &FilterRegistration, &filterHandle );
if (NT_SUCCESS( status ))
{
status = FltStartFiltering( filterHandle );
if (!NT_SUCCESS( status ))
{
FltUnregisterFilter( filterHandle );
}
}
return status;
}
NTSTATUS PtUnload ( __in FLT_FILTER_UNLOAD_FLAGS Flags )
{
UNREFERENCED_PARAMETER( Flags );
PAGED_CODE();
FltUnregisterFilter( filterHandle );
return STATUS_SUCCESS;
}
FLT_POSTOP_CALLBACK_STATUS MjDirectoryControlPostOperation ( __inout PFLT_CALLBACK_DATA Data,
__in PCFLT_RELATED_OBJECTS FltObjects,
__in_opt PVOID CompletionContext,
__in FLT_POST_OPERATION_FLAGS Flags )
{
ULONG length;
ULONG nextOffset = 0;
ULONG previousEntryWasDeleted = 0;
PCHAR queryBuffer = 0;
int modified = 0;
int removedAllEntries = 1;
PFILE_BOTH_DIR_INFORMATION currentFileInfo = 0;
PFILE_BOTH_DIR_INFORMATION nextFileInfo = 0;
PFILE_BOTH_DIR_INFORMATION previousFileInfo = 0;
UNICODE_STRING fileName;
UNREFERENCED_PARAMETER( FltObjects );
UNREFERENCED_PARAMETER( CompletionContext );
if( FlagOn( Flags, FLTFL_POST_OPERATION_DRAINING ) )
{
return FLT_POSTOP_FINISHED_PROCESSING;
}
if( Data->Iopb->MinorFunction == IRP_MN_QUERY_DIRECTORY &&
Data->Iopb->Parameters.DirectoryControl.QueryDirectory.FileInformationClass == FileBothDirectoryInformation &&
Data->Iopb->Parameters.DirectoryControl.QueryDirectory.Length > 0 &&
NT_SUCCESS(Data->IoStatus.Status) )
{
currentFileInfo = (PFILE_BOTH_DIR_INFORMATION)Data->Iopb->Parameters.DirectoryControl.QueryDirectory.DirectoryBuffer;
previousFileInfo = currentFileInfo;
do
{
nextOffset = currentFileInfo->NextEntryOffset;
nextFileInfo = (PFILE_BOTH_DIR_INFORMATION)((PCHAR)(currentFileInfo) + nextOffset);
if( hasPrefix( currentFileInfo->FileName, currentFileInfo->FileNameLength ) )
{
if( nextOffset == 0 )
{
previousFileInfo->NextEntryOffset = 0;
}
else
{
previousFileInfo->NextEntryOffset = (ULONG)((PCHAR)currentFileInfo - (PCHAR)previousFileInfo) + nextOffset;
}
modified = 1;
previousEntryWasDeleted = 1;
}
else
{
removedAllEntries = 0;
if( !previousEntryWasDeleted )
{
previousFileInfo = currentFileInfo;
}
previousEntryWasDeleted = 0;
}
currentFileInfo = nextFileInfo;
} while( nextOffset != 0 );
if( modified )
{
if( removedAllEntries )
{
Data->IoStatus.Status = STATUS_NO_MORE_FILES;
}
else
{
FltSetCallbackDataDirty( Data );
}
}
}
return FLT_POSTOP_FINISHED_PROCESSING;
}
BOOLEAN hasPrefix( PWCHAR name, ULONG length )
{
ULONG i;
ULONG wcharLength = length / 2;
if( wcharLength < prefixLength )
{
return FALSE;
}
for( i=0; i<prefixLength; i++ )
{
if( name[i] != prefixName[i] )
return FALSE;
}
return TRUE;
}