垃圾堆——windowssky
人生就象一场旅行 不必在乎目的地 在乎的是沿途的风景以及看风景的心情
<2007年8月>
2930311234
567891011
12131415161718
19202122232425
2627282930311
2345678

留言簿(14)

随笔分类

随笔档案

文章档案

相册

NDIS IFS

内核研究

基础知识

安全技术

操作系统

病毒技术

网络技术

逆向工程

驱动开发

搜索

最新评论

阅读排行榜

评论排行榜

 
VC知识库BLOG   首页  新随笔  联系  聚合  登录 
  随笔-21 文章-0 评论-25 Trackbacks-1

注一:
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管理器,文件系统的实现.



以前写的,今天整理了一下,阐述中有错误望指教,谢谢!


posted on 2007-08-08 16:55 垃圾一堆 阅读(4858) 评论(12)  编辑 收藏
Comments
标题  
姓名  
主页
验证码 *
内容   
  登录  使用高级评论  Top
[使用Ctrl+Enter键可以直接提交]