Recognizer & FS & Filter

来源:互联网 发布:国家支柱产业知乎 编辑:程序博客网 时间:2024/05/23 18:43

注一:File system recognizer 文件系统识别器(下文简称为recognizer)File system            文件系统     (下文简称为fs)File system filter     文件系统过滤器(下文简称为filter)

文件系统识别器是一个标准的NT内核模式驱动程序;它只实现一项功能:检查物理介质设备,如果它能够识别存储介质的格式便加载相应的文件系统驱动程序,利用它主要是为节约系统内存,文件系统驱动程序没用到时为什么让他在内存中呢?

               文件系统过滤驱动的一般处理流程(参照sfilter):

                     DriverEntry                        ||                        ||初始化dispatch表中的IRP_MJ_FILE_SYSTEM_CONTROL                        ||routine                         ||              DriverObject->MajorFunction[IRP_MJ_FILE_SYSTEM_CONTROL] = SfFsControl ...                        ||                        ||注册一个SfFsNotification;当文件系统或文件系统识别器                        ||registers or unregisters时被调用                        ||    IoRegisterFsRegistrationChange(DriverObject, SfFsNotification)                        ||                        ||                        //     SfFsNotification(PDEVICE_OBJECT DeviceObject, BOOLEAN FsActive)                        ||                        || FsActive        TRUE <----------//------------> FALSE         ||                              ||         ||                              ||IoAttachDeviceToDeviceStack         IoDetachDevice         ||         || /-------//------->Attach to (Filesystem)-----------------/IRP_MJ_FILE_SYSTEM_CONTROL |                                                        | |                                                        |MN:IRP_MN_MOUNT_VOLUME /---------------->Attach to (recognizer)                 |你就尽管Mount,只要fs                        ||                                |处理状态为STATUS_SUCCESS;                        ||MJ:IRP_MJ_FILE_SYSTEM_CONTROL   |fs中关于卷的Mount处理                        //                                |参见FatMountVolume函数    SfFsControl (PDEVICE_OBJECT DeviceObject, PIRP Irp)   |                        ||                                //filter其他处理参见sfilter                        ||MN:              /--------------//-----------------------------/         |                                             |         |IRP_MN_MOUNT_VOLUME                          |         |                                             | filter等待recognizer处理完成                                    ||                                            |         ||                                            |   /-----//-->STATUS_FS_DRIVER_REQUIRED(1)---|/        |    |                                         ||           /-------->STATUS_UNRECOGNIZED_VOLUME(2)---||                                                     ||        |                                             ||        |                                             //        |不论结果是哪一个,filter什么动作也没有;                  但IO管理器收到recognizer处理结果后,处理各不相同:           (1)表示recognizer认识这个卷,但对应的fs还没启动             |(2)表示recognizer不认识这个卷,对应的fs不能处理            || 如果是第一种情况I/O管理器就会向这个设备发送---------------||IRP_MN_LOAD_FILE_SYSTEM                                                      ||                                                      ||原来我们一直挂接在recognizer上的                                                      //                                                 IoDetachDevice(recognizer)                                                      ||                                                      ||                                             wait recognizer load fs status                                                      ||                                                      ||                              Other status<-----------//----------->STATUS_SUCCESS                                 ||                                                                       ||recognizer加载对应的fs失败                                 ||只好还挂到recognizer上                                 ||                                 //                  IoAttachDeviceToDeviceStack(recognizer)

 

注二:IoRegisterFsRegistrationChange函数在winxp,win2003下会对已加载的文件系统重新枚举一遍而nt4.0和win2000下则不会,具体原因代码见...(留意一下IopNotifyAlreadyRegisteredFileSystems的作用和实现)//win2000NTSTATUSIoRegisterFsRegistrationChange(    IN PDRIVER_OBJECT DriverObject,    IN PDRIVER_FS_NOTIFICATION DriverNotificationRoutine    )

/*++

Routine Description:

    This routine registers the specified driver's notification routine to be    invoked whenever a file system registers or unregisters itself as an active    file system in the system.

Arguments:

    DriverObject - Pointer to the driver object for the driver.

    DriverNotificationRoutine - Address of routine to invoke when a file system        registers or unregisters itself.

Return Value:

    The return status is the final value of the function.

--*/

{    PNOTIFICATION_PACKET nPacket;

    PAGED_CODE();

    //    // Begin by attempting to allocate storage for the shutdown packet.  If    // one cannot be allocated, simply return an appropriate error.    //

    nPacket = ExAllocatePoolWithTag( PagedPool,                                     sizeof( NOTIFICATION_PACKET ),                                     'sFoI' );    if (!nPacket) {        return STATUS_INSUFFICIENT_RESOURCES;    }

    //    // Initialize the notification packet and insert it onto the tail of the    // list.    //

    nPacket->DriverObject = DriverObject;    nPacket->NotificationRoutine = DriverNotificationRoutine;

    ExAcquireResourceExclusive( &IopDatabaseResource, TRUE );    InsertTailList( &IopFsNotifyChangeQueueHead, &nPacket->ListEntry );    ExReleaseResource( &IopDatabaseResource );

    //    // Increment the number of reasons that this driver cannot be unloaded.    //

    ObReferenceObject( DriverObject );

    return STATUS_SUCCESS;}

 

//win2003NTSTATUSIoRegisterFsRegistrationChange(    IN PDRIVER_OBJECT DriverObject,    IN PDRIVER_FS_NOTIFICATION DriverNotificationRoutine    )

/*++

Routine Description:

    This routine registers the specified driver's notification routine to be    invoked whenever a file system registers or unregisters itself as an active    file system in the system.

Arguments:

    DriverObject - Pointer to the driver object for the driver.

    DriverNotificationRoutine - Address of routine to invoke when a file system        registers or unregisters itself.

Return Value:

    STATUS_DEVICE_ALREADY_ATTACHED -                Indicates that the caller has already registered                last with the same driver object & driver notification

    STATUS_INSUFFICIENT_RESOURCES    STATUS_SUCCESS

--*/

{    PNOTIFICATION_PACKET nPacket;

    PAGED_CODE();

    ExAcquireResourceExclusiveLite( &IopDatabaseResource, TRUE );

    if (!IsListEmpty( &IopFsNotifyChangeQueueHead )) {

        //        // Retrieve entry at tail of list        //

        nPacket = CONTAINING_RECORD( IopFsNotifyChangeQueueHead.Blink, NOTIFICATION_PACKET, ListEntry );

        if ((nPacket->DriverObject == DriverObject) &&            (nPacket->NotificationRoutine == DriverNotificationRoutine)) {

            ExReleaseResourceLite( &IopDatabaseResource);            return STATUS_DEVICE_ALREADY_ATTACHED;        }    }

    //    // Begin by attempting to allocate storage for the shutdown packet.  If    // one cannot be allocated, simply return an appropriate error.    //

    nPacket = ExAllocatePoolWithTag( PagedPool|POOL_COLD_ALLOCATION,                                     sizeof( NOTIFICATION_PACKET ),                                     'sFoI' );    if (!nPacket) {

        ExReleaseResourceLite( &IopDatabaseResource );        return STATUS_INSUFFICIENT_RESOURCES;    }

    //    // Initialize the notification packet and insert it onto the tail of the    // list.    //

    nPacket->DriverObject = DriverObject;    nPacket->NotificationRoutine = DriverNotificationRoutine;

    InsertTailList( &IopFsNotifyChangeQueueHead, &nPacket->ListEntry );

    IopNotifyAlreadyRegisteredFileSystems(&IopNetworkFileSystemQueueHead, DriverNotificationRoutine, FALSE);    IopNotifyAlreadyRegisteredFileSystems(&IopCdRomFileSystemQueueHead, DriverNotificationRoutine, TRUE);    IopNotifyAlreadyRegisteredFileSystems(&IopDiskFileSystemQueueHead, DriverNotificationRoutine, TRUE);    IopNotifyAlreadyRegisteredFileSystems(&IopTapeFileSystemQueueHead, DriverNotificationRoutine, TRUE);

    //    // Notify this driver about all already notified filesystems    // registered as an active file system of some type.    //

    ExReleaseResourceLite( &IopDatabaseResource );

    //    // Increment the number of reasons that this driver cannot be unloaded.    //

    ObReferenceObject( DriverObject );

    return STATUS_SUCCESS;}

VOIDIopNotifyAlreadyRegisteredFileSystems(    IN PLIST_ENTRY  ListHead,    IN PDRIVER_FS_NOTIFICATION DriverNotificationRoutine,    IN BOOLEAN SkipRaw    )/*++

Routine Description:

    This routine calls the driver notification routine for filesystems    that have already been registered at the time of the call.

Arguments:

    ListHead - Pointer to the filesystem registration list head.    DriverNotificationRoutine - Pointer to the routine that has to be called.

Return Value:

    None.

--*/{    PLIST_ENTRY entry;    PDEVICE_OBJECT fsDeviceObject;

    entry = ListHead->Flink;    while (entry != ListHead) {

        //        // Skip raw filesystem notification        //        if ((entry->Flink == ListHead) && (SkipRaw)) {            break;        }

        fsDeviceObject = CONTAINING_RECORD( entry, DEVICE_OBJECT, Queue.ListEntry );        entry = entry->Flink;        DriverNotificationRoutine( fsDeviceObject, TRUE );    }}

注三:IoRegisterFileSystem函数是文件系统在DriverEntry中最后要调用的函数,主要是向IO管理器中注册一下,以后有卷需要Mount时通知我...VOIDIoRegisterFileSystem(    IN OUT PDEVICE_OBJECT DeviceObject    )

/*++

Routine Description:

    This routine inserts the device object for the file system which the device    object represents into the list of file systems in the system.

Arguments:

    DeviceObject - Pointer to device object for the file system.

Return Value:

    None.

--*/

{    PNOTIFICATION_PACKET nPacket;    PLIST_ENTRY entry;

    PAGED_CODE();

    //    // Allocate the I/O database resource for a write operation.    //

    (VOID) ExAcquireResourceExclusive( &IopDatabaseResource, TRUE );

    //    // Insert the device object into the appropriate file system queue based on    // the driver type in the device object.  Notice that if the device type is    // unrecognized, the file system is simply not registered.    //

    if (DeviceObject->DeviceType == FILE_DEVICE_NETWORK_FILE_SYSTEM) {        InsertHeadList( &IopNetworkFileSystemQueueHead,                        &DeviceObject->Queue.ListEntry );    } else if (DeviceObject->DeviceType == FILE_DEVICE_CD_ROM_FILE_SYSTEM) {        InsertHeadList( &IopCdRomFileSystemQueueHead,                        &DeviceObject->Queue.ListEntry );    } else if (DeviceObject->DeviceType == FILE_DEVICE_DISK_FILE_SYSTEM) {        InsertHeadList( &IopDiskFileSystemQueueHead,                        &DeviceObject->Queue.ListEntry );    } else if (DeviceObject->DeviceType == FILE_DEVICE_TAPE_FILE_SYSTEM) {        InsertHeadList( &IopTapeFileSystemQueueHead,                        &DeviceObject->Queue.ListEntry );    }

    //    // Ensure that this file system's device is operable.    //

    DeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;

    //    // Notify all of the registered drivers that this file system has been    // registered as an active file system of some type.    //

    //PS:看到了吧,如果你的filter调用了IoRegisterFsRegistrationChange,    //文件系统注册时就要通过你啦,TRUE-Load/FALSE-unload.    entry = IopFsNotifyChangeQueueHead.Flink;    while (entry != &IopFsNotifyChangeQueueHead) {        nPacket = CONTAINING_RECORD( entry, NOTIFICATION_PACKET, ListEntry );        entry = entry->Flink;        nPacket->NotificationRoutine( DeviceObject, TRUE );    }

    //    // Release the I/O database resource.    //

    ExReleaseResource( &IopDatabaseResource );

    //    // Increment the number of reasons that this driver cannot be unloaded.    //

    ExInterlockedAddUlong( &DeviceObject->ReferenceCount, 1, &IopDatabaseLock );}

注四:   有兴趣的话可以看看文件识别器,IO管理器,文件系统的实现.