📄 operations.c
字号:
status = FmmReacquireMetadataFileReferences( Cbd );
if (!NT_SUCCESS( status )) {
DebugTrace( DEBUG_TRACE_ERROR | DEBUG_TRACE_METADATA_OPERATIONS,
("[Fmm]: Failed to re-open metadata with status 0x%x after a successful unlock.\n",
status) );
//
// Sanity - we are now in a bad state. The volume was unlocked
// but we have not been able to re-acquire references to
// our metadata file
//
// Ntfs dismounts and remounts the volume after an unlock. So we ignore
// failures to open the metadata with STATUS_INVALID_DEVICE_OBJECT_PARAMETER
// because the volume should have been remounted and the metadata file
// should have been opened on the newly mounted instance of that volume
//
// Note however, that if this is an implicit lock (used by autoXXX.exe) then
// ntfs will not automatically dismount the volume. It relies on the application
// to restart the system if it has made any changes to the volume. If the
// application has not made any changes then ntfs will simply continue on
// after the unlock without dismounting the volume. Hence we cannot assume
// that ntfs always dismounts the volume. We need to try to re-acquire
// a handle to our metadata file and ignore failure with error
// STATUS_INVALID_DEVICE_OBJECT_PARAMETER which indicates that the
// volume has dismounted
//
// Also it is always possible to fail with STATUS_INSUFFICIENT_RESOURCES
// so we should ignore that as well.
//
// It is also possible to fail if the instance context was in a transition state
// so we should ignore STATUS_FILE_LOCK_CONFLICT too.
//
ASSERT( (status == STATUS_INVALID_DEVICE_OBJECT_PARAMETER) ||
(status == STATUS_INSUFFICIENT_RESOURCES) ||
(status == STATUS_FILE_LOCK_CONFLICT) );
//
// There is little use updating the return status since it already has a
// failure code from the failed dismount
//
}
}
//
// We don't need to process a volume CleanUp any further
//
goto FmmPostCleanupCleanup;
}
//
// Here the filter can do any further processing it may want to do
// in the PostCleanUp Callback
//
FmmPostCleanupCleanup:
if (!NT_SUCCESS( status )) {
DebugTrace( DEBUG_TRACE_ERROR,
("[Fmm]: FmmPostCleanup -> Failed with status 0x%x \n",
status) );
//
// It does not make sense to fail in the the post op, since the operation has completed
//
}
DebugTrace( DEBUG_TRACE_ALL_IO,
("[Fmm]: FmmPostCleanup -> Exit (Cbd = %p, FileObject = %p)\n",
Cbd,
FltObjects->FileObject) );
return FLT_POSTOP_FINISHED_PROCESSING;
}
FLT_PREOP_CALLBACK_STATUS
FmmPreFSControl (
__inout PFLT_CALLBACK_DATA Cbd,
__in PCFLT_RELATED_OBJECTS FltObjects,
__deref_out_opt PVOID *CompletionContext
)
{
NTSTATUS status;
FLT_PREOP_CALLBACK_STATUS callbackStatus;
UNREFERENCED_PARAMETER( CompletionContext );
UNREFERENCED_PARAMETER( FltObjects );
PAGED_CODE();
DebugTrace( DEBUG_TRACE_ALL_IO,
("[Fmm]: FmmPreFsCtl -> Enter (FsControlCode = 0x%x, Cbd = %p, FileObject = %p)\n",
Cbd->Iopb->Parameters.FileSystemControl.Common.FsControlCode,
Cbd,
FltObjects->FileObject) );
//
// default to no post-op callback
//
callbackStatus = FLT_PREOP_SUCCESS_NO_CALLBACK;
if (Cbd->Iopb->MinorFunction != IRP_MN_USER_FS_REQUEST) {
goto FmmPreFSControlCleanup;
}
switch (Cbd->Iopb->Parameters.FileSystemControl.Common.FsControlCode) {
//
// System FSCTLs that we are interested in
//
case FSCTL_DISMOUNT_VOLUME:
case FSCTL_LOCK_VOLUME:
if (FmmTargetIsVolumeOpen( Cbd )) {
//
// Give up the metadata file handle and the metadata file object
//
status = FmmReleaseMetadataFileReferences( Cbd );
if ( NT_SUCCESS( status )) {
//
// Continue with the lock/dismount - we need to check if the
// lock operation suceeded in the post-op
//
callbackStatus = FLT_PREOP_SYNCHRONIZE;
} else {
//
// Fail the lock/dismount
//
DebugTrace( DEBUG_TRACE_ERROR | DEBUG_TRACE_METADATA_OPERATIONS,
("[Fmm]: Failed to release metadata file references with status 0x%x for a volume lock/dismount\n",
status) );
Cbd->IoStatus.Status = status;
callbackStatus = FLT_PREOP_COMPLETE;
}
}
break;
case FSCTL_UNLOCK_VOLUME:
//
// We need to handle unlock in the post-op
//
callbackStatus = FLT_PREOP_SYNCHRONIZE;
break;
}
FmmPreFSControlCleanup:
DebugTrace( DEBUG_TRACE_ALL_IO,
("[Fmm]: FmmPreFsCtl -> Exit (FsControlCode = 0x%x, Cbd = %p, FileObject = %p)\n",
Cbd->Iopb->Parameters.FileSystemControl.Common.FsControlCode,
Cbd,
FltObjects->FileObject) );
return callbackStatus;
}
FLT_POSTOP_CALLBACK_STATUS
FmmPostFSControl (
__inout PFLT_CALLBACK_DATA Cbd,
__in PCFLT_RELATED_OBJECTS FltObjects,
__in PVOID CompletionContext,
__in FLT_POST_OPERATION_FLAGS Flags
)
{
NTSTATUS status;
UNREFERENCED_PARAMETER( CompletionContext );
UNREFERENCED_PARAMETER( Flags );
PAGED_CODE();
DebugTrace( DEBUG_TRACE_ALL_IO,
("[Fmm]: FmmPostFsCtl -> Enter (FsControlCode = 0x%x, Cbd = %p, FileObject = %p)\n",
Cbd->Iopb->Parameters.FileSystemControl.Common.FsControlCode,
Cbd,
FltObjects->FileObject) );
if (!FlagOn(Flags,FLTFL_POST_OPERATION_DRAINING)) {
switch (Cbd->Iopb->Parameters.FileSystemControl.Common.FsControlCode) {
//
// System FSCTLs that we are interested in
//
case FSCTL_DISMOUNT_VOLUME:
if (FmmTargetIsVolumeOpen( Cbd )) {
if (NT_SUCCESS( Cbd->IoStatus.Status )) {
//
// Dismount succeeded - teardown our instance because its no longer valid.
// If we do not tear down this instance, it will stay around until the
// last handle for that volume is closed. This will cause the instance
// enumeration APIs to see multiple instances
//
status = FltDetachVolume( Globals.Filter, FltObjects->Volume, NULL );
if (!NT_SUCCESS( status )) {
DebugTrace( DEBUG_TRACE_ERROR,
("[Fmm]: Failed to detach instance with status 0x%x after a volume dismount\n",
status) );
//
// Doesn't make sense to update the status code in the post-op with a
// failure code since the operation has already been performed by the
// file system
//
}
} else {
//
// The dismount failed - reaquire our references to the metadata file
// handle and the metadata file object
//
status = FmmReacquireMetadataFileReferences( Cbd );
if (!NT_SUCCESS( status )) {
DebugTrace( DEBUG_TRACE_ERROR | DEBUG_TRACE_METADATA_OPERATIONS,
("[Fmm]: Failed to re-open metadata with status 0x%x after a failed dismount with status 0x%x\n",
status,
Cbd->IoStatus.Status) );
//
// Sanity - we are now in a bad state. The dismount has failed
// but we have not been able to re-acquire references to
// our metadata file
//
// It is always possible to fail with STATUS_INSUFFICIENT_RESOURCES
// so we should ignore that.
//
// It is also possible to fail if the instance context was in a transition state
// so we should ignore STATUS_FILE_LOCK_CONFLICT too.
//
ASSERT( (status == STATUS_INSUFFICIENT_RESOURCES) ||
(status == STATUS_FILE_LOCK_CONFLICT) );
//
// There is little use updating the return status since it already has a
// failure code from the failed dismount
//
}
}
}
break;
case FSCTL_LOCK_VOLUME:
if (FmmTargetIsVolumeOpen( Cbd )) {
if (!NT_SUCCESS( Cbd->IoStatus.Status )) {
//
// The lock failed - reaquired our references to the metadata file
// handle and the metadata file object
//
status = FmmReacquireMetadataFileReferences( Cbd );
if (!NT_SUCCESS( status )) {
DebugTrace( DEBUG_TRACE_ERROR | DEBUG_TRACE_METADATA_OPERATIONS,
("[Fmm]: Failed to re-open metadata with status 0x%x after a failed lock with status 0x%x\n",
status,
Cbd->IoStatus.Status) );
//
// Sanity - we are now in a bad state. The lock has failed
// but we have not been able to re-acquire references to
// our metadata file
//
// It is always possible to fail with STATUS_INSUFFICIENT_RESOURCES
// so we should ignore that.
//
// It is also possible to fail if the instance context was in a transition state
// so we should ignore STATUS_FILE_LOCK_CONFLICT too.
//
ASSERT( (status == STATUS_INSUFFICIENT_RESOURCES) ||
(status == STATUS_FILE_LOCK_CONFLICT) );
//
// There is little use updating the return status since it already has a
// failure code from the failed lock
//
}
} else {
//
// The lock operation suceeded - update the MetadataOpenTriggerFileObject in the
// instance context to the File Object on the lock operation suceeded because this
// the file object on close/unlock of which, we need to reacquire our metadata file
// references
//
status = FmmSetMetadataOpenTriggerFileObject( Cbd );
if (!NT_SUCCESS( status )) {
DebugTrace( DEBUG_TRACE_ERROR | DEBUG_TRACE_METADATA_OPERATIONS,
("[Fmm]: Failed to update MetadataOpenTriggerFileObject in the instance context with status 0x%x after a successful lock.\n",
status,
Cbd->IoStatus.Status) );
//
// Sanity - we are now in a bad state. We have failed to
// set the TriggerFileObject We may not be able to detect
// an unlock operation on which we need to re-acquire our
// metadata file references
//
ASSERT( status == STATUS_FILE_LOCK_CONFLICT );
//
// Doesn't make sense to update the status code in the
// post-op with a failure code since the operation has
// already been performed by the file system
//
}
}
}
break;
case FSCTL_UNLOCK_VOLUME:
if (NT_SUCCESS( Cbd->IoStatus.Status )) {
//
// The unlock suceeded - reaquired our references to the metadata file
// handle and the metadata file object
//
status = FmmReacquireMetadataFileReferences( Cbd );
if (!NT_SUCCESS( status )) {
DebugTrace( DEBUG_TRACE_ERROR | DEBUG_TRACE_METADATA_OPERATIONS,
("[Fmm]: Failed to re-open metadata with status 0x%x after a successful unlock.\n",
status) );
//
// Sanity - we are now in a bad state. The volume was unlocked
// but we have not been able to re-acquire references to
// our metadata file
//
// Ntfs dismounts and remounts the volume after an unlock. So we ignore
// failures to open the metadata with STATUS_INVALID_DEVICE_OBJECT_PARAMETER
// because the volume should have been remounted and the metadata file
// should have been opened on the newly mounted instance of that volume
//
// Note however, that if this is an implicit lock (used by autoXXX.exe) then
// ntfs will not automatically dismount the volume. It relies on the application
// to restart the system if it has made any changes to the volume. If the
// application has not made any changes then ntfs will simply continue on
// after the unlock without dismounting the volume. Hence we cannot assume
// that ntfs always dismounts the volume. We need to try to re-acquire
// a handle to our metadata file and ignore failure with error
// STATUS_INVALID_DEVICE_OBJECT_PARAMETER which indicates that the
// volume has dismounted
//
// Also it is always possible to fail with STATUS_INSUFFICIENT_RESOURCES
// so we should ignore that as well.
//
// It is also possible to fail if the instance context was in a transition state
// so we should ignore STATUS_FILE_LOCK_CONFLICT too.
//
ASSERT( (status == STATUS_INVALID_DEVICE_OBJECT_PARAMETER) ||
(status == STATUS_INSUFFICIENT_RESOURCES) ||
(status == STATUS_FILE_LOCK_CONFLICT) );
//
// There is little use updating the return status since it already has a
// failure code from the failed dismount
//
}
}
break;
}
}
DebugTrace( DEBUG_TRACE_ALL_IO,
("[Fmm]: FmmPostFsCtl -> Exit (FsControlCode = 0x%x, Cbd = %p, FileObject = %p)\n",
Cbd->Iopb->Parameters.FileSystemControl.Common.FsControlCode,
Cbd,
FltObjects->FileObject) );
return FLT_POSTOP_FINISHED_PROCESSING;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -