Chinaunix首页 | 论坛 | 博客
  • 博客访问: 431809
  • 博文数量: 72
  • 博客积分: 1583
  • 博客等级: 上尉
  • 技术积分: 775
  • 用 户 组: 普通用户
  • 注册时间: 2010-09-23 09:36
文章分类

全部博文(72)

文章存档

2011年(72)

我的朋友

分类: WINDOWS

2011-02-09 12:51:52

一、何谓文件系统过滤驱动?
     文件系统过滤驱动是一种可选的,为文件系统提供具有附加值功能的驱动程序。文件系统过滤驱动是一种核心模式组件,它作为Windows NT执行体的一部分运行。
     文件系统过滤驱动可以过滤一个或多个文件系统或文件系统卷的I/O操作。按不同的种类划分,文件系统过滤驱动可以分成日志记录、系统监测、数据修改或事件预防几类。通常,以文件系统过滤驱动为核心的应用程序有防毒软件、加密程序、分级存储管理系统等。
二、文件系统过滤驱动并不是设备驱动
     设备驱动是用来控制特定硬件I/O设备的软件组件。例如:DVD存储设备驱动是一个DVD驱动。
     相反,文件系统过滤驱动与一个或多个文件系统协同工作来处理文件I/O操作。这些操作包括:创建、打开、关闭、枚举文件和目录;获取和设置文件、目录、卷的相关信息;向文件中读取或写入数据。另外,文件系统过滤驱动必须支持文件系统特定的功能,例如缓存、锁定、稀疏文件、磁盘配额、压缩、安全、可恢复性、还原点和卷装载等。
     下面两部分详细的阐述了文件系统过滤驱动和设备驱动之间的相似点与不同点。
1、文件系统过滤驱动同设备驱动的相似点:
下列部分描述了Windows操作系统中文件系统过滤驱动和设备驱动之间的相似点:
(1)、类似的结构
     类似于设备驱动,文件系统过滤驱动有着属于自己的DriverEntry、Dispatch和I/O组件例程。文件系统过滤驱动同设备驱动一样调用许多相同的系统核心例程,它们都会过滤发送给它们所关联的设备的I/O请求。
(2)、类似的功能:
     文件系统过滤驱动和设备驱动都是I/O子系统的组成部分,因此它们都接收和作用于I/O请求包(IRP)。
     类似于设备驱动,文件系统过滤驱动同样可以创建它们自己的IRP并将该IRP发送到低层驱动。
     这两种驱动均可以通过注册回调函数来接收多种系统事件的通知。
(3)、其它类似点:
     同设备驱动类似,文件系统过滤驱动可以接收传入的I/O控制码(IOCTLs)。而且,文件系统过滤驱动还可以接收和定义文件系统控制码(FSCTLs)。
     同设备驱动类似,文件系统过滤驱动可以被配置为在系统引导过程中加载或者在系统启动过程完成后加载。
2、文件系统过滤驱动同设备驱动之间的不同点:
     下例部分描述了文件系统过滤驱动同设备驱动之间的不同点:
     (1)、无需电源管理
     由于文件系统过滤驱动并不是真正的设备驱动,而且它们不需要直接控制硬件设备,因此它们并不接收IRP_MJ_POWER请求。(电源管理IRP将直接发送到存储设备堆栈中。但是,在非常罕见的情况下,文件系统过滤驱动有可能会影响到电源管理。)由此,文件系统过滤驱动并不注册IRP_MJ_POWER相关例程,它们也不会调用PoXxx例程。
     (2)、非WDM
     文件系统过滤驱动并不是WDM驱动程序,WDM驱动模型仅适用于设备驱动。
     (3)、没有AddDevice或StartIo例程
     由于文件系统过滤驱动并不是设备驱动,而且它们并不直接控制硬件设备,因此它们没有AddDevice或StartIo例程。
     (4)、创建不同的设备对象
     虽然文件系统过滤驱动和设备驱动均需要创建设备对象,但是它们所创建的设备对象的种类和数量都是不同的。
     设备驱动创建物理和功能设备对象来描述设备。即插即用(PnP)管理器将构建一个设备树来存放所有由设备驱动所创建的设备对象。文件系统过滤驱动所创建的设备对象,并不包含在这个设备树中。
     文件系统过滤驱动并不创建物理或功能设备对象,它们创建控制设备对象和过滤设备对象。控制设备对象对系统和用户模式应用程序提供过滤驱动的描绘。过滤设备对象执行对指定文件系统或卷的实际过滤工作。文件系统过滤驱动通常创建一个控制设备对象和多个过滤设备对象。
     (5)、其它不同点:
     由于文件系统过滤驱动并不是设备驱动,因此他们将不会执行直接内存访问(DMA)。
     与设备过滤驱动不同,设备过滤驱动可以附加到目标设备功能驱动的上层和下层,文件系统过滤驱动仅能附加到目标文件系统驱动的上层。因此在设备驱动队列中,文件系统仅能进行上层过滤而无法进行下层过滤。
三、安装文件系统过滤驱动
    对于Windows XP和后续操作系统来说,可以通过INI文件或安装应用程序来安装文件系统过滤驱动(对于Windows 2000和更早的操作系统,过滤驱动通常通过服务控制管理器Service Control Manager来进行安装)。
四、初始化文件系统过滤驱动
与设备驱动类似,文件系统过滤驱动也使用DriverEntry例程进行初始化工作。在驱动程序加载后,加载驱动相同的组件将通过调用驱动程序的 DriverEntry例程来对驱动程序进行初始化工作。对于文件系统过滤驱动来说,加载和初始化过滤驱动的系统组件为I/O管理器。
    DriverEntry例程运行于系统线程上下文中,其IRQL = PASSIVE_LEVEL。本例程可分页,详细信息参见MmLockPagableCodeSection。
    DriverEntry例程定义如下:
NTSTATUS
DriverEntry (
    IN PDRIVER_OBJECT DriverObject,
    IN PUNICODE_STRING RegistryPath
)
本例程有两个输入参数。第一个参数,DriverObject为系统在文件系统过滤驱动加载时所创建的驱动对象;第二个参数,RegistryPath为包含驱动程序注册键路径的Unicode字符串。
    文件系统过滤驱动按如下顺序执行DriverEntry例程:
     01、创建控制设备对象:
    文件系统过滤驱动的DriverEntry例程通常以创建控制设备对象作为该例程的起始。创建控制设备对象的目的在于允许应用程序即使在过滤驱动加载到文件系统或卷设备对象之前也能够直接与过滤驱动进行通信。
 注意:文件系统也会创建控制设备对象。当文件系统过滤驱动将其自身附加到文件系统之上时(而不是附加到某一特定文件系统卷),过滤驱动同样将其自身附加到文件系统的控制设备对象之上。
    在FileSpy驱动范例中,控制设备对象按如下方式创建:
RtlInitUnicodeString(&nameString, FILESPY_FULLDEVICE_NAME);
status = IoCreateDevice(
    DriverObject,                                                //DriverObject
    0,                                                           //DeviceExtensionSize
    &nameString,                                                 //DeviceName
    FILE_DEVICE_DISK_FILE_SYSTEM,                                //DeviceType
    FILE_DEVICE_SECURE_OPEN,                                     //DeviceCharacteristics
    FALSE,                                                       //Exclusive
    &gControlDeviceObject);                                      //DeviceObject
 
RtlInitUnicodeString(&linkString, FILESPY_DOSDEVICE_NAME);
status = IoCreateSymbolicLink(&linkString, &nameString);
    与文件系统不同,文件系统过滤驱动并不是一定要为其控制设备对象命名。如果传递给DeviceName参数一个非空(Non-NULL)值,该值将作为控制设备对象的名称。接下来,在前面的代码范例中DriverEntry可以调用IoCreateSymbolicLink例程来将该对象的核心模式名称与应用程序可见的用户模式名称关联到一起(同样可以通过调用IoRegisterDeviceInterface来使设备对象对应用程序可见)。
    注意:由于控制设备对象是唯一不会附加到设备堆栈中的设备对象,因此控制设备对象是唯一的可安全命名的设备对象。由此,是否为文件系统过滤驱动的控制设备对象是否命名是可选的。
    注意:文件系统的控制设备对象必须命名。过滤设备对象从不命名。
    参数DeviceType代表某种设备类型,其可能的取值均以常量形式定义在ntifs.h中,例如: FILE_DEVICE_DISK_FILE_SYSTEM。
    如果向DeviceName传递了一个非空值(Non-NULL),DeviceCharacteristics标识必须包括 FILE_DEVICE_SECURE_OPEN。该标识指示I/O管理器对所有发送到控制设备对象的Open请求进行安全检测。
    文件系统过滤驱动在分派例程中识别其自身控制设备对象的有效方式为将设备指针与前期存储的全局控制设备对象指针进行比较。因此FileSpy驱动范例将 IoCreateDevice所返回的设备对象指针存储到了全局变量gControlDeviceObject中。
     02、注册IRP分派例程:
    过滤驱动DriverEntry例程中的DriverObject参数提供了一个指向过滤驱动的驱动对象的指针。为了注册I/O请求包(IRP)的分派例程,必须为主功能码注册分派例程的入口点。例如:FileSpy驱动范例按下列方式设置分派例程入口点:
for (i = 0; i <= IRP_MJ_MAXIMUM_FUNCTION; i++)
{
    DriverObject->MajorFunction[i] = SpyDispatch;
}
DriverObject->MajorFunction[IRP_MJ_CREATE] = SpyCreate;
DriverObject->MajorFunction[IRP_MJ_CLOSE] = SpyClose;
DriverObject->MajorFunction[IRP_MJ_FILE_SYSTEM_CONTROL] = SpyFsControl;
    注意:在上面的For循环为每个IRP主功能码分派例程都分派了默认的分派例程。这是一个比较好的做法,因为,默认情况下,I/O管理器完成未知IRP并返回STATUS_INVALID_DEVICE_REQUEST。文件系统过滤驱动在这种方式下不会拒绝未知的IRP,这些请求将发送给低层驱动。由于这个原因,默认分派例程仅向下层传递IRP。
     03、注册Fast I/O分派例程:
    过滤驱动DriverEntry例程的DriverObject参数提供了指向过滤驱动驱动对象的指针。
    为了注册文件系统过滤驱动的Fast I/O分派例程,必须分配并初始化Fast I/O分派表,向该表中存储Fast I/O分派例程,然后将该分派表的地址存储到驱动对象的FastIoDispatch成员中。
    例如:FileSpy驱动范例按下述方式为Fast I/O分派例程设置入口点:
 
RtlZeroMemory(fastIoDispatch, sizeof(FAST_IO_DISPATCH));
fastIoDispatch->SizeOfFastIoDispatch = sizeof(FAST_IO_DISPATCH);
fastIoDispatch->FastIoCheckIfPossible = SpyFastIoCheckIfPossible;
fastIoDispatch->FastIoRead = SpyFastIoRead;
fastIoDispatch->FastIoWrite = SpyFastIoWrite;
fastIoDispatch->FastIoQueryBasicInfo = SpyFastIoQueryBasicInfo;
fastIoDispatch->FastIoQueryStandardInfo = SpyFastIoQueryStandardInfo;
fastIoDispatch->FastIoLock = SpyFastIoLock;
fastIoDispatch->FastIoUnlockSingle = SpyFastIoUnlockSingle;
fastIoDispatch->FastIoUnlockAll = SpyFastIoUnlockAll;
fastIoDispatch->FastIoUnlockAllByKey = SpyFastIoUnlockAllByKey;
fastIoDispatch->FastIoDeviceControl = SpyFastIoDeviceControl;
fastIoDispatch->FastIoDetachDevice = SpyFastIoDetachDevice;
fastIoDispatch->FastIoQueryNetworkOpenInfo = SpyFastIoQueryNetworkOpenInfo;
fastIoDispatch->MdlRead = SpyFastIoMdlRead;
fastIoDispatch->MdlReadComplete = SpyFastIoMdlReadComplete;
fastIoDispatch->PrepareMdlWrite = SpyFastIoPrepareMdlWrite;
fastIoDispatch->MdlWriteComplete = SpyFastIoMdlWriteComplete;
fastIoDispatch->FastIoReadCompressed = SpyFastIoReadCompressed;
fastIoDispatch->FastIoWriteCompressed = SpyFastIoWriteCompressed;
fastIoDispatch->MdlReadCompleteCompressed = SpyFastIoMdlReadCompleteCompressed;
fastIoDispatch->MdlWriteCompleteCompressed = SpyFastIoMdlWriteCompleteCompressed;
fastIoDispatch->FastIoQueryOpen = SpyFastIoQueryOpen;
 
DriverObject->FastIoDispatch = fastIoDispatch;
     04、注册FsFilter回调例程:
    FsFilter通知回调例程在下层文件系统执行某些操作之前或之后调用。如果需要获取更多有关于FsFilter回调例程相关信息,可参见FsRtlRegisterFileSystemFilterCallbacks例程
    为了注册FsFilter的通知回调例程必须分配并初始化FS_FILTER_CALLBACKS结构体,然后向该结构体中促出FsFilter回调例程,并将存储有Callbacks parameter到FsRtlRegisterFileSystemFilterCallbacks中。
    例如:FileSpy驱动范例按如下方式注册FsFilter回调。
 
fsFilterCallbacks.SizeOfFsFilterCallbacks = sizeof(FS_FILTER_CALLBACKS);
fsFilterCallbacks.PreAcquireForSectionSynchronization = SpyPreFsFilterOperation;
fsFilterCallbacks.PostAcquireForSectionSynchronization = SpyPostFsFilterOperation;
fsFilterCallbacks.PreReleaseForSectionSynchronization = SpyPreFsFilterOperation;
fsFilterCallbacks.PostReleaseForSectionSynchronization = SpyPostFsFilterOperation;
fsFilterCallbacks.PreAcquireForCcFlush = SpyPreFsFilterOperation;
fsFilterCallbacks.PostAcquireForCcFlush = SpyPostFsFilterOperation;
fsFilterCallbacks.PreReleaseForCcFlush = SpyPreFsFilterOperation;
fsFilterCallbacks.PostReleaseForCcFlush = SpyPostFsFilterOperation;
fsFilterCallbacks.PreAcquireForModifiedPageWriter = SpyPreFsFilterOperation;
fsFilterCallbacks.PostAcquireForModifiedPageWriter = SpyPostFsFilterOperation;
fsFilterCallbacks.PreReleaseForModifiedPageWriter = SpyPreFsFilterOperation;
fsFilterCallbacks.PostReleaseForModifiedPageWriter = SpyPostFsFilterOperation;
 
status = FsRtlRegisterFileSystemFilterCallbacks(DriverObject, &fsFilterCallbacks);
    05、执行其它必要的初始化工作:
    在注册完IRP和Fast I/O分派例程之后,文件系统过滤驱动的DriverEntry例程需要初始化其它该驱动所需的全局变量和数据结构。
    06、注册回调例程【可选】:
    过滤驱动可以通过调用IoRegisterFsRegistrationChange例程来注册用来侦听在文件系统调用 IoRegisterFileSystem或IoUnregisterFileSystem注册或卸载自身时所触发事件的回调例程。过滤驱动通过注册这个回调函数来发觉新的文件系统加载事件,然后,过滤驱动将自身附加到这个新的文件系统之上。
    注意:文件系统过滤驱动不可能调用IoRegisterFileSystem或IoUnregisterFileSystem例程。这两个例程都是专为文件系统提供服务的。
    过滤驱动并不是在调用IoRegisterFsRegistrationChange时加载到卷之上,它必须在侦测到卷以后才能进行加载(例如,通过一个用户模式应用程序)。注意:过滤驱动使用该例程来获得在卷装在后立即附加到该卷之上的能力。使用该例程时,并不能保证过滤驱动将直接附加到卷设备对象之上。其余部分未翻译,如下: But it does ensure that such a filter attaches before (and thus below) any filter that instead waits for a command from a user-mode application, because filters can attach only at the top of the current file system volume device stack.
    07、存储注册表路径字符串拷贝【可选】:
    注意:本步骤是过滤驱动在执行DriverEntry例程之后,需要使用注册表路径时所必须的。
    其余部分未翻译,如下:Save a copy of the RegistryPath string that was passed as input to DriverEntry. This parameter points to a counted Unicode string that specifies a path to the driver's registry key,
\Registry\Machine\System\CurrentControlSet\Services\DriverName, where
DriverName is the name of the driver. If the RegistryPath string will be needed later, DriverEntry must save a copy of it, not just a pointer to it, because the pointer is no longer valid after the DriverEntry routine returns.
    08、返回状态:
    文件系统过滤驱动的DriverEntry例程通常会返回STATUS_SUCCESS。然而,如果驱动初始化失败,DriverEntry会向返回一个适当的状态值。
    如果DriverEntry例程返回了一个指示未成功的状态值,系统将卸载该驱动。因此,DriverEntry例程必须在返回错误代码之前释放那些自己所分配的内存和所获取的诸如设备对象之类系统资源。
 
五、附加过滤驱动到文件系统或卷之上
文件系统过滤驱动将其自身附加到一个或多个已装载卷之上,并过滤发送给这些卷的I/O操作。下面将以Windows Driver Kit (WDK)中的范例来说明通常会采用的两种方式:
·         文件系统过滤驱动可以附加到终端用户指定需要过滤的卷,比如键入卷的驱动符。用户命令将传递给过滤驱动一个私有的IRP_MJ_DEVICE_CONTROL请求。FileSpy驱动范例在全局变量gFileSpyAttachMode设置为FILESPY_ATTACH_ON_DEMAND时,采用这种方式(默认情况下, gFileSpyAttachMode将设置为FILESPY_ATTACH_ALL_VOLUMES)。
·         文件系统过滤驱动可以附加到一个或多个文件系统驱动之上,监听 IRP_MJ_FILE_SYSTEM_CONTROL、IRP_MN_MOUNT_VOLUME请求,并附加到文件系统所装载的卷之上。SFilter 就驱动范例使用这种方式。FileSpy驱动范例在全局变量gFileSpyAttachMode被设置为 FILESPY_ATTACH_ALL_VOLUMES(默认值)采取这种方式。
     注意:通常需要假定卷和文件系统驱动的关系为一对多,而不是一对一。这是由于某些高级存储功能,例如动态卷和卷装载点等所造成的。
    注意:不要将定文件系统会一直以同步方式处理IRP_MN_MOUNT_VOLUME请求。例如,辅助存储器可能异步的进行装载。因此,过滤驱动需要在Mount Completion例程中传递PendingReturned标识。如果需要获取更多信息,可查阅DDK在线文档的“PendingReturned Flag”部分。
    文件系统过滤驱动可以附加并过滤文件系统卷。但是它们无法直接附加到诸如磁盘驱动或分区等存储设备之上,同样他们也无法附加到单独的目录或文件之上。
     如果需要获取更多信息,可参见下面章节:
    01、创建过滤设备对象
    调用IoCreateDevice例程来创建用来附加到卷或文件系统堆栈上的过滤设备对象,在FileSpy范例中,以下述方式进行该工作:
status = IoCreateDevice(
    gFileSpyDriverObject,     //DriverObject
    sizeof(FILESPY_DEVICE_EXTENSION),     //DeviceExtensionSize
    NULL,           //DeviceName
    DeviceObject->DeviceType,     //DeviceType
    0,            //DeviceCharacteristics
    FALSE,          //Exclusive
    &newDeviceObject);        //DeviceObject

    在上面的代码片段中,DeviceObject为指向过滤驱动所需要附加到的目标设备的设备对象,而newDeviceObject为指向过滤驱动自身的设备对象的指针。
    为了为过滤设备对象的设备扩展数据结构体分配存储空间,因此需要将DeviceExtensionSize参数设置为sizeof (FILESPY_DEVICE_EXTENSION)。新创建的过滤设备对象的设备扩展成员将设置为指向该数据结构的指针。文件系统过滤驱动通常为每个过滤设备对象定义并分配设备扩展。设备扩展的数量和结构均由驱动指定。然而,在MS Windows XP以及后续操作系统之上,过滤驱动所定义的设备扩展结构DEVICE_EXTENSION至少需要包含下述成员:PDEVICE_OBJECT AttachedToDeviceObject。
    在上面调用IoCreateDevice时,由于过滤设备对象并没有命名,因此将DeviceName参数设置为NULL。由于过滤设备对象需要附加到文件系统或卷设备堆栈之上,因此,为过滤设备对象分配一个名字将造成系统安全漏洞。
    DeviceType参数必须始终设置为过滤设备对象所附加到的目标(文件系统或过滤)设备对象。按照此方法传递设备类型是非常重要的,这是因为它将由I/O Manager使用,并传回给应用程序。
    注意:文件系统和文件系统过滤驱动从来不会将DeviceType参数设置为FILE_DEVICE_FILE_SYSTEM。该值并不是一个有效参数值(FILE_DEVICE_FILE_SYSTEM常量仅在定义FSCTL时使用)。
    DeviceType参数非常重要的其它原因是,许多过滤驱动仅仅附加到某些特定的文件系统之上。例如,一个特殊的过滤驱动将会附加到本地磁盘文件系统之上,而并不附加到CD-ROM文件系统或远程文件系统之上。这些过滤驱动测试最文件系统或卷设备堆栈中最高层设备对象的DeviceType参数。在大多数情况下,最高层设备对象为一个过滤设备对象。这就是为什么过滤驱动的Device Type参数需要同下层文件系统或卷设备对象的该参数一致的原因。

    02、将过滤设备对象附加到目标设备对象之上
    通过调用IoAttachDeviceToDeviceStackSafe来将过滤设备对象附加到目标文件系统或卷的过滤设备堆栈之中。
devExt = filespyDeviceObject->DeviceExtension;
status = IoAttachDeviceToDeviceStackSafe(
     filespyDeviceObject,       //SourceDevice
     DeviceObject,        //TargetDevice
     &devext->AttachedToDeviceObject);  //AttachedToDeviceObject

    注意:在有其它过滤驱动已经附加到目标设备对象之上时,AttachedToDeviceObject输出参数接收到的设备对象指针可以与TargeDevice不同。
    通过名称附加到文件系统之上
    每种文件系统需要创建一个或多个已命名控制设备对象。如果需要直接附加到文件系统之上,文件系统过滤驱动需要传递给 IoGetDeviceObjectPointer传递该特定文件系统控制设备对象的名称来获取该设备对象的指针。下列代码范例显示了如何获取RAW文件系统的两个控制设备对象中的一个的方法:
RtlInitUnicodeString(&nameString, L"");
status = IoGetDeviceObjectPointer(
      &nameString,        //ObjectName
      FILE_READ_ATTRIBUTES,     //DesiredAccess
      &fileObject,        //FileObject
      &rawDeviceObject);      //DeviceObject
if (NT_SUCCESS(status)) {
      ObDereferenceObject(fileObject);
}
    如果调用IoGetDeviceObjectPointer成功,文件系统过滤驱动调用IoAttachDeviceToDeviceStackSafe方法来附加到前述方法返回的控制设备对象之上。
    注意:除了控制设备对象指针(rawDeviceObject)以外,IoGetDeviceObjectPointer还会返回一个指向向用户模式应用表现该控制设备对象的文件对象的指针(fileObject)。在上述代码范例中,并不需要文件对象,因此通过调用ObDereferenceObject关闭了该文件对象。下面没有翻译:It is important to note that decrementing the reference count on the file object returned by IoGetDeviceObjectPointer causes the reference count on the device object to be decremented as well. Thus the fileObject and rawDeviceObject pointers should both be considered invalid after the above call to ObDereferenceObject, unless the reference count on the device object is incremented by an additional call to ObReferenceObject before ObDereferenceObject is called for the file object.

    03、传递DO_BUFFERED_IO和DO_DIRECT_IO标识
    在过滤设备对象成功的附加到文件系统或卷之上以后,下面没有翻译:always be sure to set or clear the DO_BUFFERED_IO and DO_DIRECT_IO flags as needed so that they match the values of the next-lower device object on the driver stack. (For more information about these flags, see Methods for Accessing Data Buffers.) In the FileSpy sample, this is done as follows:
if (FlagOn( DeviceObject->Flags, DO_BUFFERED_IO ))
{
    SetFlag( filespyDeviceObject->Flags, DO_BUFFERED_IO );
}
if (FlagOn( DeviceObject->Flags, DO_DIRECT_IO ))
{
    SetFlag( filespyDeviceObject->Flags, DO_DIRECT_IO );
}

    在上述代码片段中,DeviceObject为一个过滤设备对象附加到的设备对象的指针, filespyDeviceObject为指向过滤设备对象自身的指针。

    04、传递FILE_DEVICE_SECURE_OPEN标识
    在过滤设备对象成功附加到文件系统(并非卷)设备对象之上以后,下面没有翻译:always be sure to set the FILE_DEVICE_SECURE_OPEN flag on the filter device object as needed to so that it matches the value of the next-lower device object on the driver stack. (For more information about this flag, see Specifying Device Characteristics in the Kernel Architecture Design Guide and DEVICE_OBJECT in the Kernel Reference.)在FileSpy驱动范例中,实现方式如下:
if (FlagOn( DeviceObject->Characteristics, FILE_DEVICE_SECURE_OPEN ))
{
    SetFlag( filespyDeviceObject->Characteristics, FILE_DEVICE_SECURE_OPEN );
}

    在上述代码片段中,DeviceObject为一个过滤设备对象附加到的设备对象的指针, filespyDeviceObject为指向过滤设备对象自身的指针。

    05、清除DO_DEVICE_INITIALIZING标记:
    在过滤设备对象附加到文件系统或卷之上以后,,需要确保清除过滤设备对象的DO_DEVICE_INITIALIZING标识。在FileSpy驱动范例中,以如下方式实现:
ClearFlag(NewDeviceObject->Flags, DO_DEVICE_INITIALIZING);

    在过滤设备对象创建以后,IoCreateDevice为设备对象设置DO_DEVICE_INITIALIZING标识。在过滤驱动成功进行附加以后,这个标识必须被清除掉。注意:如果本标识没有被清除,其它过滤驱动将无法再次附加到该过滤链中,因为,此时调用IoAttachDeviceToDeviceStackSafe将失败。
    注意:在DriverEntry例程中创建的设备对象,并不需要必须清除DO_DEVICE_INITIALIZING标识,这是因为这个工作将会由I/O管理器自动完成。然而,如果创建了其它设备对象,则需要进行该清除工作。

本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/yzzm521/archive/2007/07/12/1686369.aspx
阅读(1585) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~