Статья третья, управление...
Сделаем чтобы драйвер блокировал файл только тогда, когда нам нужно.
А вернее чтобы программа управляла драйвером,
и так что нам нужно изменить от предыдущего примера,
Объявим функции в самом начале,
NTSTATUS
NullPortConnect (
__in PFLT_PORT ClientPort,
__in_opt PVOID ServerPortCookie,
__in_bcount_opt(SizeOfContext) PVOID ConnectionContext,
__in ULONG SizeOfContext,
__deref_out_opt PVOID *ConnectionCookie
);
VOID
NullPortDisconnect (
__in_opt PVOID ConnectionCookie
);
NTSTATUS
NullPortMessageNotify (
IN PVOID PortCookie,
IN PVOID InputBuffer OPTIONAL,
IN ULONG InputBufferLength,
OUT PVOID OutputBuffer OPTIONAL,
IN ULONG OutputBufferLength,
OUT PULONG ReturnOutputBufferLength
);
Три функции для работы с портом, вызываются при подключении отключении и принятии сообщения от порта.
Также объявим их чтобы они были в "подкачиваемой" памяти
#ifdef ALLOC_PRAGMA
#pragma alloc_text(INIT, DriverEntry)
#pragma alloc_text(PAGE, NullUnload)
#pragma alloc_text(PAGE, NullInstanceSetup)
#pragma alloc_text(PAGE, NullQueryTeardown)
#pragma alloc_text(PAGE, NullPreCreate)
#pragma alloc_text(PAGE, NullPortConnect)
#pragma alloc_text(PAGE, NullPortDisconnect)
#pragma alloc_text(PAGE, NullPortMessageNotify)
#endif
Теперь изменим функцию входа в драйвер, добавим "тела" трех функций и изменим функцию выгрузки
NTSTATUS
DriverEntry (
__in PDRIVER_OBJECT DriverObject,
__in PUNICODE_STRING RegistryPath
)
{
OBJECT_ATTRIBUTES oa;
UNICODE_STRING uniString;
PSECURITY_DESCRIPTOR sd;
NTSTATUS status;
UNREFERENCED_PARAMETER( RegistryPath );
DbgPrint("Null Filter, DriverEntry\n");
NullFilterData.BlockFile=0; // Уберем мусор из переменной
status = FltRegisterFilter( DriverObject,
&FilterRegistration,
&NullFilterData.FilterHandle );
if (!NT_SUCCESS( status ))
return status;
RtlInitUnicodeString( &uniString, ScannerPortName);
status = FltBuildDefaultSecurityDescriptor( &sd, FLT_PORT_ALL_ACCESS );
if (NT_SUCCESS( status ))
{
InitializeObjectAttributes( &oa,&uniString,OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,NULL,sd );
status = FltCreateCommunicationPort(NullFilterData.FilterHandle,&NullFilterData.ServerPort,&oa,NULL,NullPortConnect,NullPortDisconnect,NullPortMessageNotify,1);// регистрируем наши функции
FltFreeSecurityDescriptor( sd );
if (NT_SUCCESS( status ))
{
status = FltStartFiltering( NullFilterData.FilterHandle );
if (!NT_SUCCESS( status ))
{
FltCloseCommunicationPort( NullFilterData.ServerPort );//Ничего не вышло мы выгружаем все
FltUnregisterFilter( NullFilterData.FilterHandle );
}
}
}
return status;
}
NTSTATUS
NullPortConnect (
__in PFLT_PORT ClientPort,
__in_opt PVOID ServerPortCookie,
__in_bcount_opt(SizeOfContext) PVOID ConnectionContext,
__in ULONG SizeOfContext,
__deref_out_opt PVOID *ConnectionCookie
)
{
PAGED_CODE();
UNREFERENCED_PARAMETER( ServerPortCookie );
UNREFERENCED_PARAMETER( ConnectionContext );
UNREFERENCED_PARAMETER( SizeOfContext);
UNREFERENCED_PARAMETER( ConnectionCookie );
ASSERT( NullFilterData.ClientPort == NULL );
ASSERT( NullFilterData.UserProcess == NULL );
NullFilterData.UserProcess = PsGetCurrentProcess();
NullFilterData.ClientPort = ClientPort;
// Запомним порт
DbgPrint( "!!! NullFilter.sys --- connected, port=0x%p\n", ClientPort );
return STATUS_SUCCESS;
}
VOID
NullPortDisconnect(
__in_opt PVOID ConnectionCookie
)
{
UNREFERENCED_PARAMETER( ConnectionCookie );
PAGED_CODE();
DbgPrint( "!!! NullFilter.sys --- disconnected, port=0x%p\n", NullFilterData.ClientPort );
FltCloseClientPort( NullFilterData.FilterHandle, &NullFilterData.ClientPort );
NullFilterData.UserProcess = NULL;
// отсоединение
}
NTSTATUS
NullPortMessageNotify (
IN PVOID PortCookie,
IN PVOID InputBuffer OPTIONAL,
IN ULONG InputBufferLength,
OUT PVOID OutputBuffer OPTIONAL,
IN ULONG OutputBufferLength,
OUT PULONG ReturnOutputBufferLength
)
// При получении сообщения из программы вызывается эта функция
{
ULONG i;
PAGED_CODE();
DbgPrint( "!!! NullFilter.sys --- Message notify, port=0x%p\n", NullFilterData.ClientPort );
if(InputBufferLength==1)// Проверим буфер
RtlCopyMemory(&NullFilterData.BlockFile,InputBuffer,1);//запомним его
return STATUS_SUCCESS;
}
NTSTATUS
NullUnload (
__in FLT_FILTER_UNLOAD_FLAGS Flags
)
{
UNREFERENCED_PARAMETER( Flags );
PAGED_CODE();
FltCloseCommunicationPort( NullFilterData.ServerPort );
FltUnregisterFilter( NullFilterData.FilterHandle );
DbgPrint("Null Filter, NullUnload");
return STATUS_SUCCESS;
}
...
Наша функция блокировки
FLT_PREOP_CALLBACK_STATUS
NullPreCreate (
__inout PFLT_CALLBACK_DATA Data,
__in PCFLT_RELATED_OBJECTS FltObjects,
__deref_out_opt PVOID *CompletionContext
)
{
PFLT_FILE_NAME_INFORMATION nameInfo;
NTSTATUS status;
BOOLEAN scanFile;
UNICODE_STRING filename;
UNREFERENCED_PARAMETER( FltObjects );
UNREFERENCED_PARAMETER( CompletionContext );
PAGED_CODE();
if(NullFilterData.BlockFile==1)// Если мы получили указание блокировать, то...
{
ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL);
status = FltGetFileNameInformation( Data,
FLT_FILE_NAME_NORMALIZED |FLT_FILE_NAME_QUERY_DEFAULT,
&nameInfo );
if (!NT_SUCCESS( status )) {
return FLT_PREOP_SUCCESS_WITH_CALLBACK;
}
status = FltParseFileNameInformation( nameInfo );
if (!NT_SUCCESS( status )) {
return FLT_PREOP_SUCCESS_WITH_CALLBACK;
}
if(nameInfo->FinalComponent.Length>0)
{
if (NullFilterData.ClientPort != NULL)
{
}
RtlInitUnicodeString(&filename,L"123.txt\0");
scanFile = RtlEqualUnicodeString(&nameInfo->FinalComponent,&filename,TRUE);
if(scanFile)
{
Data->IoStatus.Status=STATUS_ACCESS_DENIED;
return FLT_PREOP_COMPLETE;
}
}
}
return FLT_PREOP_SUCCESS_WITH_CALLBACK;
}
С драйвером все, теперь возьмемся за программу, её я взял из примера scanner
и очень сильно сократил,
#include <windows.h>
#include <stdio.h>
#include <fltuser.h>
int _cdecl
main (
__in int argc,
__in_ecount(argc) char *argv[]
)
{
HANDLE port;
HRESULT hr;
DWORD bytesReturned;
CHAR buf;
printf( "Scanner: Connecting to the filter ...\n" );
hr = FilterConnectCommunicationPort( L"\\ScannerPort",
0,
NULL,
0,
NULL,
&port );
// Соединяемся с портом драйвера
if (IS_ERROR( hr )) {
printf( "ERROR: Connecting to filter port: 0x%08x\n", hr );
return 2;
}
printf( "Scanner: Port = 0x%p \n", port);
buf=1;
hr = FilterSendMessage( port,
&buf,
1,
0,
0,
&bytesReturned );
//Отсылаем месагу
printf( "Scanner: All done. Result = 0x%08x\n", hr );
CloseHandle( port );
return hr;
}
Теперь включаем драйвер, проверяем можно ли изменять файл 123.txt , после запускаем нашу программу и проверяем снова.
Вот так вот все просто на этом думаю закончу описывать драйвер мини фильтр файловой системы,
Если возникли вопросы пишите мне на почту.
Скачать пример.