// 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)
|