白话IoRegisterFsRegistrationChange

       IoRegisterFsRegistrationChange()注册回调函数,监视文件系统的激活或者注销。 


status = IoRegisterFsRegistrationChange( DriverObject, SfFsNotification );

SfFsNotification 函数声明:

VOID
SfFsNotification (
    IN PDEVICE_OBJECT DeviceObject,
    IN BOOLEAN FsActive
    );

那么 IoRegisterFsRegistrationChange 到底做了什么呢?  上源码

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 <strong>STATUS_DEVICE_ALREADY_ATTACHED</strong>;
        }
    }

    //
    // 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 <strong>STATUS_INSUFFICIENT_RESOURCES</strong>;
    }

    //
    // 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;
}

这是一个结构体

typedef struct _NOTIFICATION_PACKET {
    LIST_ENTRY ListEntry;
    PDRIVER_OBJECT DriverObject;
    PDRIVER_FS_NOTIFICATION NotificationRoutine;
} NOTIFICATION_PACKET, *PNOTIFICATION_PACKET;

我们只看这个结构体就可以猜测到, 注册了通知的DriverObject 连接成一个链表。这个链表的头是

LIST_ENTRY IopFsNotifyChangeQueueHead;

IoRegisterFsRegistrationChange这个函数一共有3个返回情况

1 STATUS_DEVICE_ALREADY_ATTACHED

         首先探测注册有回调驱动的尾部,如果已经存在,则返回此状态。

2 STATUS_INSUFFICIENT_RESOURCES

        如果以上探测不存在或者该链表位空, 则申请分页内存,申请出错返回以上状态。

3 STATUS_SUCCESS

       只有以上2种情况都过了以后,才会来到这种状态。

       此时,将该结构体插入链表。并调用IopNotifyAlreadyRegisteredFileSystems去通知已经注册了的文件系统,此时会执行我们注册的回调函数SfFsNotification

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 );
    }
}

然后增加DriverObject的引用。

ObReferenceObject( DriverObject );












评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值