Windows内核驱动 - MiniFilter文件系统过滤

MiniFilter 微过滤驱动是相对于SFilter传统过滤驱动而言的,传统文件过滤驱动相对来说较为复杂,且接口不清晰并不符合快速开发的需求,为了解决复杂的开发问题,微过滤驱动就此诞生,微过滤驱动在编写时更简单,多数IRP操作都由过滤管理器(FilterManager或Fltmgr)所接管,因为有了兼容层,所以在开发中不需要考虑底层IRP如何派发,更无需要考虑兼容性问题,用户只需要编写对应的回调函数处理请求即可,这极大的提高了文件过滤驱动的开发效率。

一、过滤驱动程序

右击项目->属性->配置属性->链接器->输入->附加依赖项->添加fltMgr.lib。

// MiniFilter.h

#pragma once

#include <fltKernel.h>
#include <ntifs.h>

#define TC_APP_NAME  "KmdfTest"

#define LOG(format,...) \
	DbgPrint("[%s] - %s %d: " format "\n", TC_APP_NAME, __FUNCTION__, __LINE__, ##__VA_ARGS__)

#define DRIVER_MEM_TAG 'T1T4'

typedef enum {
	PACKET_NONE,
	PACKET_ADD_PATH,  // 添加路径
	PACKET_DEL_PATH,  // 移除路径
	PACKET_SET_PATH,  // 设置路径
	PACKET_CLE_PATH   // 清空路径
} PACKET_TYPE;

typedef enum {
	FLT_PATH_TYPE_READONLY,    // 只读保护 - 防止创建/修改/删除
	FLT_PATH_TYPE_DELPROTECT,  // 删除保护 - 防止删除
} FLT_PATH_TYPE;

typedef struct {
	PACKET_TYPE Type;
	wchar_t Path[260];
	FLT_PATH_TYPE PathType;
} DATA_PACKET;

typedef struct _FLT_RULE {
	LIST_ENTRY List;
	wchar_t Path[260];
	FLT_PATH_TYPE PathType;
} FLT_RULE, * PFLT_RULE;

typedef struct _FLT_RULE_LIST {
	LIST_ENTRY HeadList;
	KSPIN_LOCK SpinLock;
	PFLT_RULE FltRule;
} FLT_RULE_LIST, * PFLT_RULE_LIST;

extern PFLT_FILTER gFilterHandle;
extern PFLT_PORT gFilterServerPort;
extern CONST FLT_REGISTRATION FilterRegistration;

NTSTATUS ConnectionNotify(
	PFLT_PORT ClientPort,
	PVOID ServerPortCookie,
	PVOID ConnectionContext,
	ULONG SizeOfContext,
	PVOID* ConnectionPortCookie);

NTSTATUS DisconnectionNotify(
	PVOID ConnectionContext);

NTSTATUS MessageNotify(
	PVOID PortCookie,
	PVOID InputBuffer,
	ULONG InputBufferLength,
	PVOID OutputBuffer,
	ULONG OutputBufferLength,
	PULONG ReturnOutputBufferLength);
// Minifilter.c

#include "Minifilter.h"

PFLT_FILTER gFilterHandle = NULL;
PFLT_PORT gFilterServerPort = NULL;

void InitRuleList(PFLT_RULE_LIST Self)
{
	InitializeListHead(&Self->HeadList);
	KeInitializeSpinLock(&Self->SpinLock);
}

PFLT_RULE_LIST GetRuleListInstance()
{
	static PFLT_RULE_LIST pRuleList = NULL;

	if (!pRuleList) {
		pRuleList = ExAllocatePoolWithTag(NonPagedPool, sizeof(FLT_RULE_LIST), DRIVER_MEM_TAG);
		InitRuleList(pRuleList);
	}

	return pRuleList;
}

void ReviewRuleList()
{
	PFLT_RULE_LIST Self = GetRuleListInstance();
	PLIST_ENTRY pList = Self->HeadList.Flink;
	while (pList != &Self->HeadList) {
		PFLT_RULE pRule = CONTAINING_RECORD(pList, FLT_RULE, List);
		LOG("#Rule - Path: %ws, Type: %d", pRule->Path, pRule->PathType);
		pList = pList->Flink;
	}
}

BOOLEAN IsRuleExistFromList(PFLT_RULE_LIST Self, const wchar_t* FilePath, PFLT_RULE* Rule, BOOLEAN Contain)
{
	PLIST_ENTRY pList = Self->HeadList.Flink;
	while (pList != &Self->HeadList) {
		PFLT_RULE pRule = CONTAINING_RECORD(pList, FLT_RULE, List);
		if (Contain) {
			if (wcsstr(FilePath, pRule->Path) != NULL) {
				*Rule = pRule;
				return TRUE;
			}
		} else {
			if (wcscmp(FilePath, pRule->Path) == 0) {
				*Rule = pRule;
				return TRUE;
			}
		}

		pList = pList->Flink;
	}

	return FALSE;
}

void AddRuleToList(PFLT_RULE_LIST Self, PFLT_RULE Rule)
{
	PFLT_RULE pRule = NULL;
	PFLT_RULE pRuleMem = NULL;
	KIRQL kIrql;

	if (!Self || !Rule) {
		LOG("Parameter invalid.");
		return;
	}

	if (IsRuleExistFromList(Self, Rule->Path, &pRule, FALSE)) {
		LOG("Path already exists.");
		return;
	}

	pRuleMem = (PFLT_RULE)ExAllocatePoolWithTag(NonPagedPool, sizeof(FLT_RULE), DRIVER_MEM_TAG);
	memset(pRuleMem, 0, sizeof(pRuleMem));
	memcpy(pRuleMem->Path, Rule->Path, sizeof(pRuleMem->Path));
	pRuleMem->PathType = Rule->PathType;

	KeAcquireSpinLock(&Self->SpinLock, &kIrql);
	InsertTailList(&Self->HeadList, &pRuleMem->List);
	KeReleaseSpinLock(&Self->SpinLock, kIrql);
}

void DeleteRuleFromList(PFLT_RULE_LIST Self, const wchar_t* Path)
{
	PLIST_ENTRY pList = NULL;

	if (!Self || !Path) {
		LOG("Parameter invalid.");
		return;
	}

	pList = Self->HeadList.Flink;
	while (pList != &Self->HeadList) {
		PFLT_RULE pRule = (PFLT_RULE)CONTAINING_RECORD(pList, FLT_RULE, List);

		if (wcscmp(pRule->Path, Path) == 0) {
			KIRQL kIrql;
			KeAcquireSpinLock(&Self->SpinLock, &kIrql);
			RemoveEntryList(&pRule->List);
			KeReleaseSpinLock(&Self->SpinLock, kIrql);
			ExFreePoolWithTag(pRule, DRIVER_MEM_TAG);

			break;
		}

		pList = pList->Flink;
	}
}

void SetRuleFromList(PFLT_RULE_LIST Self, const wchar_t* Path, PFLT_RULE Rule)
{
	PLIST_ENTRY pList = NULL;

	if (!Self || !Path || !Rule) {
		LOG("Parameter invalid.");
		return;
	}

	pList = Self->HeadList.Flink;
	while (pList != &Self->HeadList) {
		PFLT_RULE pRule = (PFLT_RULE)CONTAINING_RECORD(pList, FLT_RULE, List);

		if (wcscmp(pRule->Path, Path) == 0) {
			KIRQL kIrql;

			KeAcquireSpinLock(&Self->SpinLock, &kIrql);
			// 直接更新链表项中的字段
			wcsncpy(pRule->Path, Rule->Path, ARRAYSIZE(pRule->Path) - 1);
			pRule->PathType = Rule->PathType;
			KeReleaseSpinLock(&Self->SpinLock, kIrql);

			return;
		}

		pList = pList->Flink;
	}

	// 如果未存在链表则添加规则
	AddRuleToList(Self, Rule);
}

void CleRuleFromList(PFLT_RULE_LIST Self, FLT_PATH_TYPE PathType)
{
	PLIST_ENTRY pList = NULL;

	if (!Self || PathType < 0) {
		LOG("Parameter invalid.");
		return;
	}

	pList = Self->HeadList.Flink;
	while (pList != &Self->HeadList) {
		PFLT_RULE pRule = (PFLT_RULE)CONTAINING_RECORD(pList, FLT_RULE, List);
		pList = pList->Flink;

		if (pRule->PathType == PathType) {
			KIRQL kIrql;
			KeAcquireSpinLock(&Self->SpinLock, &kIrql);
			RemoveEntryList(&pRule->List);
			KeReleaseSpinLock(&Self->SpinLock, kIrql);
			ExFreePoolWithTag(pRule, DRIVER_MEM_TAG);
		}
	}
}

void CleanAllRule(PFLT_RULE_LIST Self)
{
	PLIST_ENTRY pList = NULL;

	if (!Self) {
		return;
	}

	pList = Self->HeadList.Flink;
	while (pList != &Self->HeadList) {
		PFLT_RULE pRule = NULL;
		KIRQL kIrql;

		pRule = (PFLT_RULE)CONTAINING_RECORD(pList, FLT_RULE, List);
		pList = pList->Flink;

		KeAcquireSpinLock(&Self->SpinLock, &kIrql);
		RemoveEntryList(&pRule->List);
		KeReleaseSpinLock(&Self->SpinLock, kIrql);

		ExFreePoolWithTag(pRule, DRIVER_MEM_TAG);
	}
}

FLT_PREOP_CALLBACK_STATUS PreOperation(
	PFLT_CALLBACK_DATA Data,
	PCFLT_RELATED_OBJECTS FltObjects,
	PVOID* CompletionContext)
{
	PFLT_FILE_NAME_INFORMATION lpNameInfo = NULL;
	NTSTATUS status;

	UNREFERENCED_PARAMETER(FltObjects);
	UNREFERENCED_PARAMETER(CompletionContext);

	// 获取路径信息
	status = FltGetFileNameInformation(Data, FLT_FILE_NAME_NORMALIZED | FLT_FILE_NAME_QUERY_DEFAULT, &lpNameInfo);
	if (NT_SUCCESS(status)) {
		// 获取目标路径
		UNICODE_STRING targetPath = lpNameInfo->Name;
		// 链表匹配
		PFLT_RULE rule;
		if (IsRuleExistFromList(GetRuleListInstance(), targetPath.Buffer, &rule, TRUE)) {
			UCHAR MajorFunction = Data->Iopb->MajorFunction;
			if (rule->PathType == FLT_PATH_TYPE_READONLY) {
				// -----------------------------------目录只读保护
				LOG("RULE-READONLY: %wZ", &lpNameInfo->Name);
				LOG("-----------Create.Options: 0x%08X", Data->Iopb->Parameters.Create.Options);
				if (IRP_MJ_CREATE == MajorFunction) {
					// 防止文件/文件夹创建
					if ((Data->Iopb->Parameters.Create.Options & (FILE_WRITE_THROUGH | FILE_WRITE_DATA | FILE_APPEND_DATA | FILE_DIRECTORY_FILE))) {
						LOG("-----FILE_WRITE_THROUGH | FILE_WRITE_DATA | FILE_APPEND_DATA | FILE_DIRECTORY_FILE\n");
						// 允许拷出
						if (!(Data->Iopb->Parameters.Create.Options & (FO_DISALLOW_EXCLUSIVE)) &&
							(Data->Iopb->Parameters.Create.Options & (FILE_NON_DIRECTORY_FILE | FILE_SEQUENTIAL_ONLY))) {
							LOG("-----FILE_NON_DIRECTORY_FILE | FILE_SEQUENTIAL_ONLY\n");
							return FLT_PREOP_SUCCESS_WITH_CALLBACK;
						}
						Data->IoStatus.Information = 0;
						Data->IoStatus.Status = STATUS_ACCESS_DENIED;
						return FLT_PREOP_COMPLETE;
					}
					// 防止文件/文件夹删除
					if ((Data->Iopb->Parameters.Create.Options & (FILE_DELETE_ON_CLOSE))) {
						LOG("-----FILE_DELETE_ON_CLOSE\n");
						Data->IoStatus.Information = 0;
						Data->IoStatus.Status = STATUS_ACCESS_DENIED;
						return FLT_PREOP_COMPLETE;
					}
				} else if (IRP_MJ_WRITE == MajorFunction) {
					// 拒绝写操作
					Data->IoStatus.Information = 0;
					Data->IoStatus.Status = STATUS_ACCESS_DENIED;
					return FLT_PREOP_COMPLETE;
				} else if (IRP_MJ_SET_INFORMATION == MajorFunction) {
					// 拒绝修改操作
					Data->IoStatus.Information = 0;
					Data->IoStatus.Status = STATUS_ACCESS_DENIED;
					return FLT_PREOP_COMPLETE;
				}
			} else if (rule->PathType == FLT_PATH_TYPE_DELPROTECT) {
				// -----------------------------------目录删除保护
				LOG("RULE-DELPROTECT: %wZ", &lpNameInfo->Name);
				if (IRP_MJ_CREATE == MajorFunction) {
					if ((Data->Iopb->Parameters.Create.Options & (FILE_DELETE_ON_CLOSE))) {
						Data->IoStatus.Information = 0;
						Data->IoStatus.Status = STATUS_ACCESS_DENIED;
						return FLT_PREOP_COMPLETE;
					}
				} else if (IRP_MJ_SET_INFORMATION == MajorFunction) {
					if (Data->Iopb->Parameters.SetFileInformation.FileInformationClass 
							== FileDispositionInformation) {
						Data->IoStatus.Information = 0;
						Data->IoStatus.Status = STATUS_ACCESS_DENIED;
						return FLT_PREOP_COMPLETE;
					}
				}
			}
		}
	}

	//return FLT_PREOP_SUCCESS_NO_CALLBACK;   // 无后续处理
	return FLT_PREOP_SUCCESS_WITH_CALLBACK; // 允许后续处理
}

FLT_POSTOP_CALLBACK_STATUS PostOperation( 
	PFLT_CALLBACK_DATA Data, 
	PCFLT_RELATED_OBJECTS FltObjects, 
	PVOID CompletionContext, 
	FLT_POST_OPERATION_FLAGS Flags)
{
	UNREFERENCED_PARAMETER(Data);
	UNREFERENCED_PARAMETER(FltObjects);
	UNREFERENCED_PARAMETER(CompletionContext);
	UNREFERENCED_PARAMETER(Flags);

	return FLT_POSTOP_FINISHED_PROCESSING;
}

NTSTATUS InstanceUnload(
	FLT_FILTER_UNLOAD_FLAGS Flags)
{
	UNREFERENCED_PARAMETER(Flags);

	LOG("Uninstall MiniFilter.");

	CleanAllRule(GetRuleListInstance());
	FltCloseCommunicationPort(gFilterServerPort);
	FltUnregisterFilter(gFilterHandle);

	return STATUS_SUCCESS;
}

NTSTATUS InstanceSetup(
	PCFLT_RELATED_OBJECTS FltObjects,
	FLT_INSTANCE_SETUP_FLAGS Flags,
	DEVICE_TYPE VolumeDeviceType,
	FLT_FILESYSTEM_TYPE VolumeFilesystemType)
{
	UNREFERENCED_PARAMETER(FltObjects);
	UNREFERENCED_PARAMETER(Flags);
	UNREFERENCED_PARAMETER(VolumeDeviceType);
	UNREFERENCED_PARAMETER(VolumeFilesystemType);

	LOG("Install MiniFilter.");
	return STATUS_SUCCESS;
}

NTSTATUS InstanceQueryTeardown(
	PCFLT_RELATED_OBJECTS FltObjects, 
	FLT_INSTANCE_QUERY_TEARDOWN_FLAGS Flags)
{
	UNREFERENCED_PARAMETER(FltObjects);
	UNREFERENCED_PARAMETER(Flags);

	LOG("Destroy MiniFilter.");

	return STATUS_SUCCESS;
}

VOID InstanceTeardownStart(
	PCFLT_RELATED_OBJECTS FltObjects, 
	FLT_INSTANCE_TEARDOWN_FLAGS Flags)
{
	UNREFERENCED_PARAMETER(FltObjects);
	UNREFERENCED_PARAMETER(Flags);

	LOG("Unbundle MiniFilter.");
}

VOID InstanceTeardownComplete(
	PCFLT_RELATED_OBJECTS FltObjects, 
	FLT_INSTANCE_TEARDOWN_FLAGS Flags)
{
	UNREFERENCED_PARAMETER(FltObjects);
	UNREFERENCED_PARAMETER(Flags);

	LOG("Unbundle finish MiniFilter.");
}

// 回调函数集
CONST FLT_OPERATION_REGISTRATION Callbacks[] = {
	// 创建时触发 PreOperation(之前回调函数) / PostOperation(之后回调函数)
	{ IRP_MJ_CREATE, 0, PreOperation, PostOperation },
	// 写入触发
	{ IRP_MJ_WRITE, 0, PreOperation, PostOperation },
	// 设置时触发
	{ IRP_MJ_SET_INFORMATION, 0, PreOperation, PostOperation },
	// 结束标志
	{ IRP_MJ_OPERATION_END }
};

// 过滤驱动数据结构
CONST FLT_REGISTRATION FilterRegistration = {
	sizeof(FLT_REGISTRATION),           //  结构大小(默认)
	FLT_REGISTRATION_VERSION,           //  结构版本(默认)
	0,                                  //  过滤器标志
	NULL,                               //  上下文
	Callbacks,                          //  注册回调函数集
	InstanceUnload,                     //  驱动卸载函数
	InstanceSetup,                      //  实例安装回调函数
	InstanceQueryTeardown,              //  实例销毁回调函数
	InstanceTeardownStart,              //  实例解除绑定时触发
	InstanceTeardownComplete,           //  实例解绑完成时触发
	NULL,                               //  GenerateFileName
	NULL,                               //  GenerateDestinationFileName
	NULL                                //  NormalizeNameComponent
};

NTSTATUS ConnectionNotify(
	PFLT_PORT ClientPort,
	PVOID ServerPortCookie,
	PVOID ConnectionContext,
    ULONG SizeOfContext,
	PVOID* ConnectionPortCookie)
{
	UNREFERENCED_PARAMETER(ClientPort);
	UNREFERENCED_PARAMETER(ServerPortCookie);
	UNREFERENCED_PARAMETER(ConnectionContext);
	UNREFERENCED_PARAMETER(SizeOfContext);
	UNREFERENCED_PARAMETER(ConnectionPortCookie);

	LOG("Client connected.");
	return STATUS_SUCCESS;
}

NTSTATUS DisconnectionNotify(
	PVOID ConnectionContext)
{
	UNREFERENCED_PARAMETER(ConnectionContext);

	LOG("Client disconnected.");
	return STATUS_SUCCESS;
}

NTSTATUS MessageNotify(
	PVOID PortCookie,
	PVOID InputBuffer,
	ULONG InputBufferLength,
	PVOID OutputBuffer,
	ULONG OutputBufferLength,
	PULONG ReturnOutputBufferLength)
{
	NTSTATUS status = STATUS_SUCCESS;
	DATA_PACKET* packet = NULL;
	FLT_RULE_LIST* ruleList = NULL;

	UNREFERENCED_PARAMETER(PortCookie);
	UNREFERENCED_PARAMETER(OutputBuffer);
	UNREFERENCED_PARAMETER(OutputBufferLength);
	UNREFERENCED_PARAMETER(ReturnOutputBufferLength);

	if (InputBuffer == NULL || InputBufferLength == 0 || InputBufferLength != sizeof(DATA_PACKET)) {
		return STATUS_INVALID_PARAMETER;
	}

	packet = (DATA_PACKET*)InputBuffer;
	ruleList = GetRuleListInstance();

	switch (packet->Type) {
		case PACKET_ADD_PATH: {
			FLT_RULE rule;
			memset(rule.Path, 0, sizeof(rule.Path));
			memcpy(rule.Path, packet->Path, sizeof(rule.Path));
			rule.PathType = packet->PathType;

			LOG("PACKET_ADD_PATH - %ws, %d", rule.Path, rule.PathType);
			AddRuleToList(ruleList, &rule);
			ReviewRuleList();
		} break;

		case PACKET_DEL_PATH: {
			LOG("PACKET_DEL_PATH - %ws", packet->Path);
			DeleteRuleFromList(ruleList, packet->Path);
			ReviewRuleList();
		} break;

		case PACKET_SET_PATH: {
			FLT_RULE rule;
			memset(rule.Path, 0, sizeof(rule.Path));
			memcpy(rule.Path, packet->Path, sizeof(rule.Path));
			rule.PathType = packet->PathType;

			LOG("PACKET_SET_PATH - %ws, %d", rule.Path, rule.PathType);
			SetRuleFromList(ruleList, packet->Path, &rule);
			ReviewRuleList();
		} break;

		case PACKET_CLE_PATH: {
			FLT_PATH_TYPE PathType;
			PathType = packet->PathType;

			LOG("PACKET_CLE_PATH - %d", PathType);

			CleRuleFromList(ruleList, PathType);
			ReviewRuleList();
		} break;

		default: {
			status = STATUS_INVALID_PARAMETER;
		} break;
	}

	return status;
}
// Driver.c

#include "Minifilter.h"
#include <ntstrsafe.h>

// 驱动版本号
#define VERSION_STRING  "1.0.0"

// 驱动信息
#define NT_ROOT_PREFIX  L"\\Device\\KmdfTest"
#define DOS_ROOT_PREFIX  L"\\DosDevices\\KmdfTest"

// 通信端口
#define MINIFILTER_PORT L"\\KmdfTestPort"

// 驱动控制码
#define TC_IOCTL_GET_DRIVER_VERSION  CTL_CODE(FILE_DEVICE_UNKNOWN, 0x800, METHOD_BUFFERED, FILE_ANY_ACCESS)

// 设备对象全局指针
PDEVICE_OBJECT RootDeviceObject = NULL;

// IRP完成处理
NTSTATUS CompleteIrp(PIRP irp, NTSTATUS status, ULONG_PTR information)
{
	irp->IoStatus.Status = status;
	irp->IoStatus.Information = information;
	// 调用方已完成所有I/O请求处理操作 并且不增加优先级
	IoCompleteRequest(irp, IO_NO_INCREMENT);
	return status;
}

// IOCTL回调处理
NTSTATUS ProcessDeviceControlIrp(PDEVICE_OBJECT DeviceObject, PIRP Irp)
{
	PIO_STACK_LOCATION irpSp;

	UNREFERENCED_PARAMETER(DeviceObject);

	irpSp = IoGetCurrentIrpStackLocation(Irp);

	switch (irpSp->Parameters.DeviceIoControl.IoControlCode) {
		case TC_IOCTL_GET_DRIVER_VERSION: {
			size_t versionLength;

			LOG("TC_IOCTL_GET_DRIVER_VERSION.");
			versionLength = strlen(VERSION_STRING) + 1;
			memcpy(Irp->AssociatedIrp.SystemBuffer, VERSION_STRING, versionLength);
			Irp->IoStatus.Information = versionLength;
			Irp->IoStatus.Status = STATUS_SUCCESS;
		} break;

		default: {
			return CompleteIrp(Irp, STATUS_INVALID_DEVICE_REQUEST, 0);
		}
	}

	return CompleteIrp(Irp, Irp->IoStatus.Status, Irp->IoStatus.Information);
}

// IRP回调处理 - 所有设备在这里分发请求
NTSTATUS IRP_CALL(PDEVICE_OBJECT DeviceObject, PIRP Irp)
{
	PIO_STACK_LOCATION irpStackL;

	UNREFERENCED_PARAMETER(DeviceObject);

	// 获取应用层参数传递
	irpStackL = IoGetCurrentIrpStackLocation(Irp);

	switch (irpStackL->MajorFunction) {
		case IRP_MJ_CLOSE:
		case IRP_MJ_CREATE: {
			return CompleteIrp(Irp, STATUS_SUCCESS, 0);
		} break;

		case IRP_MJ_DEVICE_CONTROL: {
			NTSTATUS status = ProcessDeviceControlIrp(DeviceObject, Irp);
			return status;
		} break;
	}

	return CompleteIrp(Irp, STATUS_INVALID_DEVICE_REQUEST, 0);
}

// 设备删除函数
void DeleteDeviceObject(PDEVICE_OBJECT DeviceObject)
{
	UNICODE_STRING Win32NameString;
	NTSTATUS ntStatus;

	LOG("DeleteDeviceObject BEGIN.");

	// 删除符号链接
	RtlInitUnicodeString(&Win32NameString, (LPWSTR)DOS_ROOT_PREFIX);
	ntStatus = IoDeleteSymbolicLink(&Win32NameString);
	if (!NT_SUCCESS(ntStatus))
		LOG("IoDeleteSymbolicLink failed ntStatus = 0x%08x.", ntStatus);

	// 删除设备
	RootDeviceObject = NULL;
	IoDeleteDevice(DeviceObject);

	LOG("DeleteDeviceObject END.");
}

// 设备创建函数
NTSTATUS CreateRootDeviceObject(PDRIVER_OBJECT DriverObject)
{
	UNICODE_STRING Win32NameString, ntUnicodeString;
	WCHAR dosname[32], ntname[32];
	PDEVICE_OBJECT DeviceObject;
	NTSTATUS ntStatus;

	RtlStringCbCopyW(dosname, sizeof(dosname), (LPWSTR)DOS_ROOT_PREFIX);
	RtlStringCbCopyW(ntname, sizeof(ntname), (LPWSTR)NT_ROOT_PREFIX);
	RtlInitUnicodeString(&ntUnicodeString, ntname);
	RtlInitUnicodeString(&Win32NameString, dosname);

	LOG("Creating root device nt=%ls dos=%ls.", ntname, dosname);

	// 创建设备对象
	ntStatus = IoCreateDevice(
		DriverObject,             // 驱动对象
		sizeof(int),              // 状态信息大小
		&ntUnicodeString,         // 设备名称 - 必须是"\Device\[设备名]"
		FILE_DEVICE_UNKNOWN,      // 设备类型 - 常用设备之外类型
		FILE_DEVICE_SECURE_OPEN,  // 设备描述
		FALSE,                    // 独占设备
		&DeviceObject             // 返回ptr到设备对象
	);
	if (!NT_SUCCESS(ntStatus)) {
		LOG("TCCreateRootDeviceObject NTSTATUS = 0x%08x END.", ntStatus);
		return ntStatus;
	}

	// 使用直接IO(禁用缓冲区)
	DeviceObject->Flags |= DO_DIRECT_IO;
	// 4字节对齐
	DeviceObject->AlignmentRequirement = FILE_WORD_ALIGNMENT;

	// 创建符号链接,允许用户模式程序通过 \\.\Devicename 访问设备
	ntStatus = IoCreateSymbolicLink(&Win32NameString, &ntUnicodeString);
	if (!NT_SUCCESS(ntStatus)) {
		LOG("TCCreateRootDeviceObject NTSTATUS = 0x%08x END.", ntStatus);
		IoDeleteDevice(DeviceObject);
		return ntStatus;
	}

	// 注册关机通知,使设备能够在系统关机或重启时执行某些清理操作
	IoRegisterShutdownNotification(DeviceObject);

	// 获取设备对象指针
	RootDeviceObject = DeviceObject;

	return STATUS_SUCCESS;
}

// 驱动卸载函数
void DriverUnload(PDRIVER_OBJECT DriverObject)
{
	LOG("DriverUnload BEGIN DriverObject=%p.", DriverObject);
	// 资源释放
	DeleteDeviceObject(RootDeviceObject);
	LOG("DriverUnload END");
}

// 驱动入口函数
NTSTATUS
DriverEntry(
	PDRIVER_OBJECT  DriverObject,
	PUNICODE_STRING RegistryPath
)
{
	NTSTATUS status;

	PSECURITY_DESCRIPTOR pSD = NULL;
	OBJECT_ATTRIBUTES objAttri = { 0 };
	UNICODE_STRING uniPortName = { 0 };

	LOG("Version %s.", VERSION_STRING);
	LOG("RegistryPath=%ws.", RegistryPath->Buffer);

	// 注册卸载回调函数
	DriverObject->DriverUnload = DriverUnload;

	// 注册IRP处理函数
	DriverObject->MajorFunction[IRP_MJ_CREATE] = IRP_CALL;
	DriverObject->MajorFunction[IRP_MJ_CLOSE] = IRP_CALL;
	DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = IRP_CALL;

	// 向过滤管理器注册过滤器
	status = FltRegisterFilter(DriverObject, &FilterRegistration, &gFilterHandle);
	if (!NT_SUCCESS(status)) {
		LOG("FltRegisterFilter failed with status: 0x%08x", status);
		return status;
	}

	// 开启过滤
	status = FltStartFiltering(gFilterHandle);
	if (!NT_SUCCESS(status)) {
		FltUnregisterFilter(gFilterHandle);
		LOG("FltStartFiltering failed with status: 0x%08x", status);
		return status;
	}

	// 创建通信端口
	status = FltBuildDefaultSecurityDescriptor(&pSD, FLT_PORT_ALL_ACCESS);
	if (!NT_SUCCESS(status)) {
		FltUnregisterFilter(gFilterHandle);
		LOG("FltBuildDefaultSecurityDescriptor failed with status: 0x%08x", status);
		return status;
	}

	RtlInitUnicodeString(&uniPortName, MINIFILTER_PORT);
	InitializeObjectAttributes(&objAttri, &uniPortName, OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE, NULL, pSD);

	status = FltCreateCommunicationPort(gFilterHandle, &gFilterServerPort,
		&objAttri, NULL, ConnectionNotify, DisconnectionNotify, MessageNotify, 1);

	FltFreeSecurityDescriptor(pSD);

	if (!NT_SUCCESS(status)) {
		FltUnregisterFilter(gFilterHandle);
		LOG("FltCreateCommunicationPort failed with status: 0x%08x", status);
		return status;
	}

	// 创建设备
	return CreateRootDeviceObject(DriverObject);
}

二、编写应用程序

// driver.h

#pragma once

#include <iostream>
#include <windows.h>

// 驱动信息
#define DRIVER_NAME "KmdfTest"
#define DRIVER_PATH "C:\\Users\\\dxf\\Desktop\\KmdfTest\\Driver\\KmdfTest\\x64\\Debug\\KmdfTest.sys"

// 驱动路径
#define WIN32_ROOT_PREFIX  L"\\\\.\\KmdfTest"

// 驱动功能码
#define TC_IOCTL_GET_DRIVER_VERSION  CTL_CODE(FILE_DEVICE_UNKNOWN, 0x800, METHOD_BUFFERED, FILE_ANY_ACCESS)

class Driver {
public:
	Driver();
	~Driver();

	// 获取驱动版本号
	std::string GetDriverVersion();
	// 安装驱动
	BOOL InstallDriver(const char* lpszDriverName,
		const char* lpszDriverPath, const char* lpszAltitude, BOOL isAutoStart);
	// 启动驱动
	BOOL StartDriver(const char* lpszDriverName);
	// 关闭驱动
	BOOL StopDriver(const char* lpszDriverName);
	// 删除驱动
	 BOOL DeleteDriver(const char* lpszDriverName);

private:
	// 检查驱动是否安装
	BOOL IsDriverInstalled(const char* lpszDriverName);
	// 检查驱动是否运行
	BOOL IsDriverRunning(const char* lpszDriverName);
	// 打开驱动
	BOOL OpenDriver(const std::wstring& devicePath);

	// 驱动句柄
	HANDLE hDevice;
};
// dirver.cpp

#include "driver.h"
#include <winsvc.h>
#include <winioctl.h>

Driver::Driver() : hDevice(INVALID_HANDLE_VALUE) {
    // 检测驱动是否安装
    if (!IsDriverInstalled(DRIVER_NAME)) {
        std::cout << "The driver is not installed. install the driver..." << std::endl;
        if (!Driver::InstallDriver(DRIVER_NAME, DRIVER_PATH, "225864", FALSE)) {
            std::cerr << "Driver install failed!" << std::endl;
            //std::exit(-1);
        }
        std::cout << "Driver install ok." << std::endl;
    }
    // 检测驱动是否运行
    if (!IsDriverRunning(DRIVER_NAME)) {
        std::cout << "The driver is not running, run the driver..." << std::endl;
        if (!Driver::StartDriver(DRIVER_NAME)) {
            std::cerr << "Driver running failed!" << std::endl;
            //std::exit(-1);
        }
        std::cout << "Driver running ok." << std::endl;
    }
    // 打开驱动获取句柄
    if (!OpenDriver(WIN32_ROOT_PREFIX)) {
        std::cerr << "Failed to open device. Error: " << GetLastError() << std::endl;
        //std::exit(-1);
    }
    // 获取驱动版本号
    std::string version = GetDriverVersion();
    std::cout << "Driver version: " << version << std::endl;
}

Driver::~Driver() {
    if(hDevice != INVALID_HANDLE_VALUE)
        CloseHandle(hDevice);
}

std::string Driver::GetDriverVersion()
{
    char version[16];
    DWORD bytesReturned;

    if (DeviceIoControl(hDevice, TC_IOCTL_GET_DRIVER_VERSION, nullptr, 0, version, sizeof(version), &bytesReturned, nullptr)) {
        return std::string(version, bytesReturned);
    } else {
        return std::string();
    }
}

BOOL Driver::InstallDriver(const char* lpszDriverName, 
    const char* lpszDriverPath, const char* lpszAltitude, BOOL isAutoStart)
{
    char szTempStr[MAX_PATH];
    HKEY hKey;
    DWORD dwData;
    char szDriverImagePath[MAX_PATH];

    if (NULL == lpszDriverName || NULL == lpszDriverPath) {
        return FALSE;
    }

    // 得到完整的驱动路径
    GetFullPathName(lpszDriverPath, MAX_PATH, szDriverImagePath, NULL);

    SC_HANDLE hServiceMgr = NULL;  // SCM管理器句柄
    SC_HANDLE hService = NULL;  // NT驱动程序的服务句柄

    // 打开服务控制管理器
    hServiceMgr = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
    if (hServiceMgr == NULL) {
        // OpenSCManager失败
        CloseServiceHandle(hServiceMgr);
        return FALSE;
    }

    // 创建驱动所对应的服务
    int startType = SERVICE_DEMAND_START;
    if (isAutoStart) startType = SERVICE_AUTO_START;
    else startType = SERVICE_DEMAND_START;
    hService = CreateService(hServiceMgr,
        lpszDriverName,  // 驱动程序的在注册表中的名称
        lpszDriverName,  // 注册表驱动程序的DisplayName值
        SERVICE_ALL_ACCESS,  // 加载驱动程序的访问权限
        SERVICE_FILE_SYSTEM_DRIVER,  // 表示加载的服务是文件系统驱动程序
        startType,  // 注册表驱动程序的Start值
        SERVICE_ERROR_IGNORE,  // 注册表驱动程序的ErrorControl值
        szDriverImagePath,  // 注册表驱动程序的ImagePath值
        "FSFilter Activity Monitor",  // 注册表驱动程序的Group值
        NULL,
        "FltMgr",  // 注册表驱动程序的DependOnService值
        NULL,
        NULL);
    if (hService == NULL) {
        if (GetLastError() == ERROR_SERVICE_EXISTS) {
            // 服务创建失败,是由于服务已经创立过
            CloseServiceHandle(hService);  // 服务句柄
            CloseServiceHandle(hServiceMgr);  // SCM句柄
            return TRUE;
        }
        else {
            CloseServiceHandle(hService);  // 服务句柄
            CloseServiceHandle(hServiceMgr);  // SCM句柄
            return FALSE;
        }
    }
    CloseServiceHandle(hService);  // 服务句柄
    CloseServiceHandle(hServiceMgr);  // SCM句柄

    // --------------------------------------------------------------------------
    // SYSTEM\\CurrentControlSet\\Services\\DriverName\\Instances 子键下的键值项 
    // --------------------------------------------------------------------------
    strcpy(szTempStr, "SYSTEM\\CurrentControlSet\\Services\\");
    strcat(szTempStr, lpszDriverName);
    strcat(szTempStr, "\\Instances");
    if (RegCreateKeyEx(HKEY_LOCAL_MACHINE, szTempStr, 0, "", TRUE, KEY_ALL_ACCESS, NULL, &hKey, (LPDWORD)&dwData) != ERROR_SUCCESS) {
        return FALSE;
    }
    // 注册表驱动程序的DefaultInstance 值 
    strcpy(szTempStr, lpszDriverName);
    strcat(szTempStr, " Instance");
    if (RegSetValueEx(hKey, "DefaultInstance", 0, REG_SZ, (CONST BYTE*)szTempStr, (DWORD)strlen(szTempStr)) != ERROR_SUCCESS) {
        return FALSE;
    }
    // 刷新注册表
    RegFlushKey(hKey);
    RegCloseKey(hKey);

    // --------------------------------------------------------------------------
    // SYSTEM\\CurrentControlSet\\Services\\DriverName\\Instances\\DriverName Instance 子键下的键值项 
    // --------------------------------------------------------------------------
    strcpy(szTempStr, "SYSTEM\\CurrentControlSet\\Services\\");
    strcat(szTempStr, lpszDriverName);
    strcat(szTempStr, "\\Instances\\");
    strcat(szTempStr, lpszDriverName);
    strcat(szTempStr, " Instance");
    if (RegCreateKeyEx(HKEY_LOCAL_MACHINE, szTempStr, 0, "", TRUE, KEY_ALL_ACCESS, NULL, &hKey, (LPDWORD)&dwData) != ERROR_SUCCESS) {
        return FALSE;
    }
    // 注册表驱动程序的Altitude值
    strcpy(szTempStr, lpszAltitude);
    if (RegSetValueEx(hKey, "Altitude", 0, REG_SZ, (CONST BYTE*)szTempStr, (DWORD)strlen(szTempStr)) != ERROR_SUCCESS) {
        return FALSE;
    }
    // 注册表驱动程序的Flags值
    dwData = 0x0;
    if (RegSetValueEx(hKey, "Flags", 0, REG_DWORD, (CONST BYTE*) & dwData, sizeof(DWORD)) != ERROR_SUCCESS) {
        return FALSE;
    }
    // 刷新注册表
    RegFlushKey(hKey);
    RegCloseKey(hKey);
    return TRUE;
}

BOOL Driver::StartDriver(const char* lpszDriverName)
{
    SC_HANDLE schManager;
    SC_HANDLE schService;
    SERVICE_STATUS svcStatus;

    if (NULL == lpszDriverName) {
        return FALSE;
    }

    schManager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
    if (NULL == schManager) {
        CloseServiceHandle(schManager);
        return FALSE;
    }
    schService = OpenService(schManager, lpszDriverName, SERVICE_ALL_ACCESS);
    if (NULL == schService) {
        CloseServiceHandle(schService);
        CloseServiceHandle(schManager);
        return FALSE;
    }

    if (!StartService(schService, 0, NULL)) {
        CloseServiceHandle(schService);
        CloseServiceHandle(schManager);
        if (GetLastError() == ERROR_SERVICE_ALREADY_RUNNING) {
            // 服务已经开启
            return TRUE;
        }
        return FALSE;
    }

    CloseServiceHandle(schService);
    CloseServiceHandle(schManager);

    return TRUE;
}

BOOL Driver::StopDriver(const char* lpszDriverName)
{
    SC_HANDLE schManager;
    SC_HANDLE schService;
    SERVICE_STATUS svcStatus;
    bool bStopped = false;

    schManager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
    if (NULL == schManager) {
        return FALSE;
    }
    schService = OpenService(schManager, lpszDriverName, SERVICE_ALL_ACCESS);
    if (NULL == schService) {
        CloseServiceHandle(schManager);
        return FALSE;
    }
    if (!ControlService(schService, SERVICE_CONTROL_STOP, &svcStatus) && (svcStatus.dwCurrentState != SERVICE_STOPPED)) {
        CloseServiceHandle(schService);
        CloseServiceHandle(schManager);
        return FALSE;
    }

    CloseServiceHandle(schService);
    CloseServiceHandle(schManager);

    return TRUE;
}

BOOL Driver::DeleteDriver(const char* lpszDriverName)
{
    SC_HANDLE schManager;
    SC_HANDLE schService;
    SERVICE_STATUS svcStatus;

    schManager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
    if (NULL == schManager) {
        return FALSE;
    }
    schService = OpenService(schManager, lpszDriverName, SERVICE_ALL_ACCESS);
    if (NULL == schService) {
        CloseServiceHandle(schManager);
        return FALSE;
    }
    ControlService(schService, SERVICE_CONTROL_STOP, &svcStatus);
    if (!DeleteService(schService)) {
        CloseServiceHandle(schService);
        CloseServiceHandle(schManager);
        return FALSE;
    }
    CloseServiceHandle(schService);
    CloseServiceHandle(schManager);

    return TRUE;
}

BOOL Driver::IsDriverInstalled(const char* lpszDriverName)
{
    SC_HANDLE hServiceMgr = NULL;
    SC_HANDLE hService = NULL;

    // 打开服务控制管理器
    hServiceMgr = OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT);
    if (hServiceMgr == NULL) {
        return FALSE;
    }

    // 打开驱动程序服务
    hService = OpenService(hServiceMgr, lpszDriverName, SERVICE_QUERY_STATUS);
    if (hService == NULL) {
        // 如果没有找到服务,说明驱动没有安装
        CloseServiceHandle(hServiceMgr);
        return FALSE;
    }

    // 如果服务存在,说明驱动已经安装
    CloseServiceHandle(hService);
    CloseServiceHandle(hServiceMgr);
    return TRUE;
}

BOOL Driver::IsDriverRunning(const char* lpszDriverName)
{
    SC_HANDLE hServiceMgr = NULL;  // 服务控制管理器句柄
    SC_HANDLE hService = NULL;     // 服务句柄
    SERVICE_STATUS serviceStatus;  // 服务状态结构体

    // 打开服务控制管理器
    hServiceMgr = OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT);
    if (hServiceMgr == NULL) {
        // 打开服务控制管理器失败
        return FALSE;
    }

    // 打开服务,获取服务句柄
    hService = OpenService(hServiceMgr, lpszDriverName, SERVICE_QUERY_STATUS);
    if (hService == NULL) {
        // 如果服务不存在,返回 FALSE
        CloseServiceHandle(hServiceMgr);
        return FALSE;
    }

    // 查询服务状态
    if (!QueryServiceStatus(hService, &serviceStatus)) {
        // 查询服务状态失败
        CloseServiceHandle(hService);
        CloseServiceHandle(hServiceMgr);
        return FALSE;
    }

    // 检查服务的当前状态
    if (serviceStatus.dwCurrentState == SERVICE_RUNNING) {
        // 如果服务正在运行,返回 TRUE
        CloseServiceHandle(hService);
        CloseServiceHandle(hServiceMgr);
        return TRUE;
    }

    // 如果服务没有在运行,返回 FALSE
    CloseServiceHandle(hService);
    CloseServiceHandle(hServiceMgr);
    return FALSE;
}

BOOL Driver::OpenDriver(const std::wstring& devicePath)
{
    // 打开设备
    hDevice = CreateFileW(
        devicePath.c_str(),                   // 设备路径,从参数传递
        GENERIC_READ | GENERIC_WRITE,         // 访问模式
        FILE_SHARE_READ | FILE_SHARE_WRITE,   // 文件共享模式
        NULL,                                 // 安全描述符
        OPEN_EXISTING,                        // 仅打开已存在的设备
        0,                                    // 其他标志
        NULL                                  // 模板文件句柄
    );

    // 检查设备是否成功打开
    if (hDevice == INVALID_HANDLE_VALUE) {
        std::cerr << "Failed to open device. Error: " << GetLastError() << std::endl;
        return FALSE;
    }

    return TRUE;
}
// filter.h

#pragma once
#include <iostream>
#include <Windows.h>
#pragma comment(lib, "FltLib.lib")

// 通信端口名称
#define MINIFILTER_PORT L"\\KmdfTestPort"

typedef enum {
	PACKET_NONE,
	PACKET_ADD_PATH,  // 添加路径
	PACKET_DEL_PATH,  // 移除路径
	PACKET_SET_PATH,  // 设置路径
	PACKET_CLE_PATH   // 清空路径
} PACKET_TYPE;

typedef enum {
	FLT_PATH_TYPE_READONLY,    // 只读保护 - 防止创建/修改/删除
	FLT_PATH_TYPE_DELPROTECT,  // 删除保护 - 防止删除
} FLT_PATH_TYPE;

class DataPacket {
public:
	DataPacket() : m_type(PACKET_TYPE::PACKET_NONE), m_pathType(FLT_PATH_TYPE::FLT_PATH_TYPE_READONLY) {
		memset(m_path, 0, sizeof(m_path));
	}
	DataPacket(PACKET_TYPE Type, const wchar_t* Path, FLT_PATH_TYPE PathType)
		: m_type(Type), m_pathType(PathType) {
		if (Path != NULL) {
			memset(m_path, 0, sizeof(m_path));
			memcpy(m_path, Path, sizeof(m_path));
		}
	}

	PACKET_TYPE getType() {
		return m_type;
	}
	void setType(PACKET_TYPE Type) {
		m_type = Type;
	}

	std::wstring getPath() {
		return m_path;
	}
	void setPath(const std::wstring& Path) {
		memset(m_path, 0, sizeof(m_path));
		memcpy(m_path, Path.c_str(), Path.size() << 1);
	}

	FLT_PATH_TYPE getPathType() {
		return m_pathType;
	}
	void setPathType(FLT_PATH_TYPE PathType) {
		m_pathType = PathType;
	}

private:
	PACKET_TYPE m_type;
	wchar_t m_path[260];
	FLT_PATH_TYPE m_pathType;
};

class MiniFilterCommunication {
public:
	MiniFilterCommunication();
	~MiniFilterCommunication();

	// 设置目录只读保护
	BOOL SetDirReadonly(std::string& dirpath, BOOL isReadOnly);
	// 清空目录只读保护
	BOOL CleDirReadonly();
	// 设置目录删除保护
	BOOL SetDirDelprotect(std::string& dirpath, BOOL isDelprotect);
	// 清空目录删除保护
	BOOL CleDirDelprotect();

private:
	// 连接Minifilter服务
	BOOL Connect(const std::wstring& PortName);
	// 发送消息到Minifilter服务
	BOOL SendMessageToFlt(PACKET_TYPE Type, const wchar_t* FilePath, FLT_PATH_TYPE PathType);
	// 盘符路径转卷路径
	std::string DriveLetterToVolumePath(std::string& path);

	HANDLE m_hPort = INVALID_HANDLE_VALUE;
};
// filter.cpp

#include "Filter.h"
#include <Windows.h>
#include <fltUser.h>

MiniFilterCommunication::MiniFilterCommunication() {
	// 连接驱动通信端口
	if (!Connect(MINIFILTER_PORT)) {
		std::cerr << "Minifilter connect failed!" << std::endl;
		//std::exit(-1);
	}
}

MiniFilterCommunication::~MiniFilterCommunication() 
{
	if (m_hPort != INVALID_HANDLE_VALUE) {
		CloseHandle(m_hPort);
	}
}

BOOL MiniFilterCommunication::SetDirReadonly(std::string& dirpath, BOOL isReadOnly)
{
	std::string driveLetter;
	char devicePath[1024];

	// 路径以\Device\HarddiskVolumex为起始而不是盘符
	std::string path = DriveLetterToVolumePath(dirpath);
	if (!path.empty()) {
		dirpath = path;
	}
	std::cout << "SetDirReadonly " << dirpath << " " << isReadOnly << std::endl;

	std::wstring wpath(dirpath.begin(), dirpath.end());

	PACKET_TYPE type = isReadOnly ? PACKET_SET_PATH : PACKET_DEL_PATH;

	return SendMessageToFlt(type, wpath.c_str(), FLT_PATH_TYPE_READONLY);
}

BOOL MiniFilterCommunication::CleDirReadonly()
{
	return SendMessageToFlt(PACKET_CLE_PATH, NULL, FLT_PATH_TYPE_READONLY);
}

BOOL MiniFilterCommunication::SetDirDelprotect(std::string& dirpath, BOOL isDelprotect)
{
	std::string driveLetter;
	char devicePath[1024];

	// 路径以\Device\HarddiskVolumex为起始而不是盘符
	std::string path = DriveLetterToVolumePath(dirpath);
	if (!path.empty()) {
		dirpath = path;
	}
	std::cout << "SetDirDelprotect " << dirpath << " " << isDelprotect << std::endl;

	std::wstring wpath(dirpath.begin(), dirpath.end());

	PACKET_TYPE type = isDelprotect ? PACKET_SET_PATH : PACKET_DEL_PATH;

	return SendMessageToFlt(type, wpath.c_str(), FLT_PATH_TYPE_DELPROTECT);
}

BOOL MiniFilterCommunication::CleDirDelprotect()
{
	return SendMessageToFlt(PACKET_CLE_PATH, NULL, FLT_PATH_TYPE_DELPROTECT);
}

BOOL MiniFilterCommunication::Connect(const std::wstring& PortName) 
{
	HRESULT hResult = FilterConnectCommunicationPort(PortName.c_str(), 0, NULL, 0, NULL, &m_hPort);
	if (hResult != S_OK) {
		return FALSE;
	}

	return TRUE;
}

BOOL MiniFilterCommunication::SendMessageToFlt(PACKET_TYPE Type, const wchar_t* FilePath, FLT_PATH_TYPE PathType)
{
	DataPacket packet {Type, FilePath, PathType};

	DWORD outputSize = 0;

	HRESULT hResult = FilterSendMessage(m_hPort, &packet, sizeof(packet), &packet, sizeof(packet), &outputSize);
	if (hResult != S_OK) {
		return FALSE;
	}

	return TRUE;
}

std::string MiniFilterCommunication::DriveLetterToVolumePath(std::string& path)
{
	std::string driveLetter;
	char devicePath[1024];

	if (path.length() >= 3 && path[1] == ':' && path[2] == '\\') {
		driveLetter = path.substr(0, 2);
		std::cout << "driveLetter: " << driveLetter << std::endl;
		DWORD result = QueryDosDeviceA(driveLetter.c_str(), devicePath, sizeof(devicePath));
		if (result == 0) {
			DWORD errorCode = GetLastError();
			std::cerr << "SetDirReadonly QueryDosDeviceA failed: " << errorCode << std::endl;
			return std::string();
		}
		path.replace(0, 2, std::string(devicePath));

		return path;
	} else {
		return std::string();
	}
}
// main.cpp

#include <iostream>
#include <sstream>

#include "driver.h"
#include "filter.h"

int main(int argc, char* argv[])
{
    Driver driver;
    MiniFilterCommunication miniFilterCommunication;

    std::string str;
    while (1) {
        std::cout << "> ";
        if (std::getline(std::cin, str)) {
            std::istringstream iss(str);
            std::string command;
            iss >> command;

            if (command.empty()) {
                continue;
            } else if (command == "stop") {
                if (driver.StopDriver(DRIVER_NAME)) std::cout << "stop ok." << std::endl;
                else std::cerr << "stop failed!" << std::endl;
            } else if (command == "delete") {
                if (driver.DeleteDriver(DRIVER_NAME)) std::cout << "delete ok." << std::endl;
                else std::cerr << "delete failed!" << std::endl;
            } else if (command == "readonly") {
                // readonly C:\Users\dxf\Desktop\FilterTest 1
                std::string path;
                BOOL readonly;
                if (iss >> path >> readonly) {
                    if (miniFilterCommunication.SetDirReadonly(path, readonly))
                        std::cout << "SetDirReadonly ok." << std::endl;
                    else
                        std::cerr << "SetDirReadonly failed!" << std::endl;
                } 
            } else if (command == "clereadonly") {
                if (miniFilterCommunication.CleDirReadonly())
                    std::cout << "CleDirReadonly ok." << std::endl;
                else
                    std::cerr << "CleDirReadonly failed!" << std::endl;
            } else if (command == "delprotect") {
                // delprotect C:\Users\dxf\Desktop\FilterTest 1
                std::string path;
                BOOL delprotect;
                if (iss >> path >> delprotect) {
                    if (miniFilterCommunication.SetDirDelprotect(path, delprotect))
                        std::cout << "SetDirDelprotect ok." << std::endl;
                    else
                        std::cerr << "SetDirDelprotect failed!" << std::endl;
                }
            } else if (command == "cledelprotect") {
                if (miniFilterCommunication.CleDirDelprotect())
                    std::cout << "CleDirDelprotect ok." << std::endl;
                else
                    std::cerr << "CleDirDelprotect failed!" << std::endl;
            } else if (command == "quit") {
                std::cerr << "Exit." << std::endl;
                break;
            } else {
                std::cerr << "Unknown command!" << std::endl;
            }
        }
    }

    return 0;
}

三、过滤驱动安装

对于微过滤驱动,它和一般的驱动不同,在加载前必须有一份安装文件向注册表中写出子键,直接使用sc启动FltRegisterFilter会注册失败,参考通用驱动程序代码加载方式,注意自动重启方式无效。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值