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