Recognizer & FS & Filter

注一:
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的作用和实现)

//win2000
NTSTATUS
IoRegisterFsRegistrationChange(
    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;
}

 

//win2003
NTSTATUS
IoRegisterFsRegistrationChange(
    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;
}


VOID
IopNotifyAlreadyRegisteredFileSystems(
    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时通知我...

VOID
IoRegisterFileSystem(
    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管理器,文件系统的实现.

你可能感兴趣的:(Recognizer & FS & Filter)