你好,欢迎来到电脑编程技巧与维护杂志社! 杂志社简介广告服务读者反馈编程社区  
合订本订阅
 
 
您的位置:技术专栏 / Linux开发
文件系统识别器(2)
 
// DriverEntry
//
// 驱动的入口点
//
// 输入参数:
// DriverObject – 驱动的驱动程序对象
// RegistryPath – 驱动程序的服务键
//
// 输出参数:
// None.
//
// 返回值:
// success
//
// 注意:
// 这只是一个实验型的驱动.
//

NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath)
{
	NTSTATUS code;
	UNICODE_STRING driverName;
	
	// 保存驱动程序对象的全局指针
	RecognizerDriverObject = DriverObject;

	// 为IRP_MJ_FILE_SYSTEM_CONTROL设置派遣例程入口点
	DriverObject->MajorFunction[IRP_MJ_FILE_SYSTEM_CONTROL] =
	RecognizerFsControl;

	// 这个驱动是可卸载的
	DriverObject->DriverUnload = Unload;

	// 为识别器的设备名初始化一个unicode字符串.
	RtlInitUnicodeString(&driverName, FSD_RECOGNIZER_NAME);

	// 创建命名的设备对象.
	code = IoCreateDevice(RecognizerDriverObject,
		0,
		&driverName,
		FILE_DEVICE_DISK_FILE_SYSTEM,
		0,
		FALSE,
		&RecognizerDeviceObject);

	if (!NT_SUCCESS(code)) {
		DbgPrint("Recognizer failed to load, failure in IoCreateDevice call returned 0x%x\n", code);

		// 失败.
		return (code);
	}

	// 把设备对象注册为文件系统.
	IoRegisterFileSystem(RecognizerDeviceObject);
	
	// 完成
	return STATUS_SUCCESS;
}
上面的代码描述了识别器的入口点DriverEntry。DriverEntry识别器初始化驱动程序。向IO管理器注册两个回调例程。一个处理IRP_MJ_FILE_SYSTEM_ CONTROL,一个是卸载例程。我们只需要识别文件系统的格式,所以不需要处理其他请求。当真正的驱动程序被加载后,它会处理这些请求。

在DriverEntry中,创建了一个设备对象,并且指定了需要识别的文件系统的介质类型。调用IoRegisterFileSystem把设备对象注册为文件系统。整个过程非常简单。需要注意的是,你可以在一个驱动程序中识别几种存储介质类型的文件系统。这样的一个驱动程序需要为每一种存储介质类型创建一个设备对象。

为什么需要识别不同存储介质呢?有两种不同的可能性。 假如你的文件系统像UDF文件系统一样支持不同种类的存储介质,便需要识别不同的存储介质。因为Windows NT 通过匹配不同的存储介质类型来选择文件系统,你的识别器可以为每一种类型的存储介质创建一个设备对象。在创建设备对象时指定介质类型就可以了,如用FILE_DEVICE_DISK_FILE_SYSTEM类型创建对象,就像例子代码中的那样,用FILE_DEVICE_CD_ROM_FILE_SYSTEM创建第二个设备对象。这样,不管UDF文件系统存在与磁盘还是CD上都可以被你的识别器检测到。另外一个可能的原因是需要处理多种存储介质类型。这种方法被微软的文件系统驱动程序识别起采用,一个驱动程序可以识别FAT,NTFD,CDFS文件系统。它用设备对象来决定加载哪个文件系统驱动程序。它为每一个可以识别的文件系统创建一个设备对象。
//
// 卸载例程
//
// 输入参数:
// DeviceObject – 可能是我们设备对象指针
//
// 输出参数:
// None.
//
// 返回值:
// None.
//

static VOID Unload(PDRIVER_OBJECT DriverObject)
{
	//
	// 如果存在设备对象,则删除它.
	//

	if (RecognizerDeviceObject) {
		IoUnregisterFileSystem(RecognizerDeviceObject);
		IoDeleteDevice(RecognizerDeviceObject);
		RecognizerDeviceObject = 0;
	}

	//
	// 完成
	//
}
上面的代码是识别器unload例程。当驱动被停止时(命令net stop) 或者对驱动程序对象没有引用时(文件系统驱动程序已经加载完毕),此例程被调用。如果停止驱动的命令有用户模式程序发出,RecognizerDeviceObject 不为NULL,所以卸载,删除设备对象,返回。如果请求有IO管理器发出,表示没有对该驱动的引用了。
static NTSTATUS RecognizerFsControl(PDEVICE_OBJECT DeviceObject, PIRP Irp)
{
	PIO_STACK_LOCATION irpSp = IoGetCurrentIrpStackLocation(Irp);
	UNICODE_STRING driverName;
	NTSTATUS code;

	// 是否是本驱动创建的设备对象
	if (DeviceObject != RecognizerDeviceObject) {
		// 不是.
		Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED;
		Irp->IoStatus.Information = 0;
		IoCompleteRequest(Irp, IO_NO_INCREMENT);
		return STATUS_NOT_IMPLEMENTED;
	}

	//检查是否为 “装配/加载”请求。如果不是,什么也不做
	if ((irpSp->MinorFunction != IRP_MN_MOUNT_VOLUME) && (irpSp->MinorFunction != IRP_MN_LOAD_FILE_SYSTEM))
	{
		// 什么也不做
		Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED;
		Irp->IoStatus.Information = 0;
		IoCompleteRequest(Irp, IO_NO_INCREMENT);
		return STATUS_NOT_IMPLEMENTED;
	}

	// 处理 “加载”请求
	if (irpSp->MinorFunction == IRP_MN_LOAD_FILE_SYSTEM) {
		// 加载文件系统
		RtlInitUnicodeString(&driverName, FSD_SERVICE_PATH);
		code = ZwLoadDriver(&driverName);

		// 用加载的结果完成IRP
		Irp->IoStatus.Status = code;
		Irp->IoStatus.Information = 0;
		IoCompleteRequest(Irp, IO_NO_INCREMENT);

		// 在成功加载了文件系统驱动程序的情况下,不在需要这个设备对象
		if (NT_SUCCESS(code)) {
			IoUnregisterFileSystem(RecognizerDeviceObject);
			IoDeleteDevice(RecognizerDeviceObject);
			RecognizerDeviceObject = 0;
		// 文件系统已经被加载了。
		}

	return (code);
	}

	//调用RecognizerDetectFileSystem决定该卷是否可以被本文件系统识别。

	code = RecognizerDetectFileSystem(Irp);

	//检查返回值,如果成功,说明这是可以识别的文件系统。
	//接下来告诉调用者(IO管理器)应该调用加载文件系统驱动的例程(即发送IRP_MN_LOAD_FILE_SYSTEM)

	if (NT_SUCCESS(code))
	{
		// 卷可以被识别

		Irp->IoStatus.Status = STATUS_FS_DRIVER_REQUIRED;
		Irp->IoStatus.Information = 0;
		IoCompleteRequest(Irp, IO_NO_INCREMENT);
		return STATUS_FS_DRIVER_REQUIRED;
	}

	// 卷不可以被识别
	Irp->IoStatus.Status = STATUS_UNRECOGNIZED_VOLUME;
	Irp->IoStatus.Information = 0;
	IoCompleteRequest(Irp, IO_NO_INCREMENT);
	return STATUS_UNRECOGNIZED_VOLUME;
}
(编辑:aniston)
  推荐精品文章

·2024年12月目录 
·2024年11月目录 
·2024年10月目录 
·2024年9月目录 
·2024年8月目录 
·2024年7月目录 
·2024年6月目录 
·2024年5月目录 
·2024年4月目录 
·2024年3月目录 
·2024年2月目录 
·2024年1月目录
·2023年12月目录
·2023年11月目录

  联系方式
TEL:010-82561037
Fax: 010-82561614
QQ: 100164630
Mail:gaojian@comprg.com.cn

  友情链接
 
Copyright 2001-2010, www.comprg.com.cn, All Rights Reserved
京ICP备14022230号-1,电话/传真:010-82561037 82561614 ,Mail:gaojian@comprg.com.cn
地址:北京市海淀区远大路20号宝蓝大厦E座704,邮编:100089