Пример #1
1
EXTERN_C static NTSTATUS ScvnpWriteFile(_In_ PCFLT_RELATED_OBJECTS FltObjects,
                                        _In_ const wchar_t *OutPathW,
                                        _In_ void *Buffer,
                                        _In_ ULONG BufferSize,
                                        _In_ ULONG CreateDisposition) {
  PAGED_CODE();

  UNICODE_STRING outPath = {};
  RtlInitUnicodeString(&outPath, OutPathW);
  OBJECT_ATTRIBUTES objAttr = RTL_INIT_OBJECT_ATTRIBUTES(
      &outPath, OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE);

  HANDLE fileHandle = nullptr;
  IO_STATUS_BLOCK ioStatus = {};
  auto status = FltCreateFile(
      FltObjects->Filter, FltObjects->Instance, &fileHandle, GENERIC_WRITE,
      &objAttr, &ioStatus, nullptr, FILE_ATTRIBUTE_NORMAL, 0, CreateDisposition,
      FILE_SEQUENTIAL_ONLY | FILE_SYNCHRONOUS_IO_NONALERT |
          FILE_NON_DIRECTORY_FILE,
      nullptr, 0, 0);
  if (status == STATUS_OBJECT_NAME_COLLISION ||
      status == STATUS_DELETE_PENDING) {
    return status;
  }
  if (!NT_SUCCESS(status)) {
    LOG_ERROR_SAFE("FltCreateFile failed (%08x) for %S", status, OutPathW);
    return status;
  }

  PFILE_OBJECT fileObject = nullptr;
  status = ObReferenceObjectByHandle(fileHandle, 0, nullptr, KernelMode,
                                     reinterpret_cast<void **>(&fileObject),
                                     nullptr);
  if (!NT_SUCCESS(status)) {
    LOG_ERROR_SAFE("ObReferenceObjectByHandle failed (%08x) for %S", status,
                   OutPathW);
    goto End;
  }

  status = FltWriteFile(FltObjects->Instance, fileObject, nullptr, BufferSize,
                        Buffer, 0, nullptr, nullptr, nullptr);
  if (!NT_SUCCESS(status)) {
    LOG_ERROR_SAFE("FltWriteFile failed (%08x) for %S", status, OutPathW);
    goto End;
  }

End:
  if (fileObject) {
    ObDereferenceObject(fileObject);
  }
  if (fileHandle) {
    FltClose(fileHandle);
  }
  return status;
}
Пример #2
0
/*---------------------------------------------------------
函数名称:	FileCreateForHeaderWriting
函数描述:	在文件被打开前先通过该对象打开文件
输入参数:
			pfiInstance					过滤器实例
			pfniFileNameInformation		文件名信息
			phFileHandle				保存文件句柄的空间

输出参数:
			phFileHandle 文件句柄
返回值:		
			STATUS_SUCCESS					成功	
			STATUS_OBJECT_NAME_NOT_FOUND	未查询到名称

其他:		如果查询名称失败(根本无名称)将返回
			STATUS_OBJECT_NAME_NOT_FOUND


			打开后需要使用FltClose关闭文件

更新维护:	2011.5.2     最初版本
---------------------------------------------------------*/
NTSTATUS 
FileCreateForHeaderWriting(
	__in PFLT_INSTANCE pfiInstance,
	__in PUNICODE_STRING puniFileName,
	__out HANDLE * phFileHandle
	)
{
	//对象属性,用于打开文件时使用
	OBJECT_ATTRIBUTES oaObjectAttributes;

	//文件路径长度
	ULONG ulPathLength;

	//返回的Io状态
	IO_STATUS_BLOCK ioStatusBlock;

	//返回的状态
	NTSTATUS statusRet;

	//
	//填充数据
	//
	
	InitializeObjectAttributes(
		&oaObjectAttributes,
		puniFileName,
		OBJ_KERNEL_HANDLE|OBJ_CASE_INSENSITIVE,
		NULL,
		NULL
		);


	//
	//为了兼容Windows Xp,使用FltCreateFile
	//

	return FltCreateFile(
		pfltGlobalFilterHandle,
		pfiInstance,
		phFileHandle,
		FILE_READ_DATA|FILE_WRITE_DATA,
		&oaObjectAttributes,
		&ioStatusBlock,
		NULL,
		FILE_ATTRIBUTE_NORMAL,
		FILE_SHARE_READ,
		FILE_OPEN,
		FILE_NON_DIRECTORY_FILE,
		NULL,
		0,
		IO_IGNORE_SHARE_ACCESS_CHECK
		);
}
Пример #3
0
BOOLEAN
getSizeModified(
_In_ PFLT_INSTANCE instance,
_In_ PUNICODE_STRING fileName,
_Inout_ LONGLONG *size,
_Inout_ LONGLONG *modified
)
{
	NTSTATUS status;
	HANDLE FileHandle = NULL;
	OBJECT_ATTRIBUTES objectAttributes;
	IO_STATUS_BLOCK ioStatus;
	FILE_BASIC_INFORMATION basicFileInfo;
	FILE_STANDARD_INFORMATION standardFileInfo;

	InitializeObjectAttributes(&objectAttributes,
		fileName,
		OBJ_CASE_INSENSITIVE | OBJ_OPENIF,
		NULL,
		NULL);

	status = FltCreateFile(
		ClaimsmanData.Filter,
		instance,
		&FileHandle,
		FILE_READ_DATA | FILE_READ_ATTRIBUTES,
		&objectAttributes,
		&ioStatus,
		NULL,
		FILE_ATTRIBUTE_NORMAL,
		FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
		FILE_OPEN,
		FILE_SYNCHRONOUS_IO_NONALERT,
		NULL,
		0,
		IO_NO_PARAMETER_CHECKING
		);
	if (!NT_SUCCESS(status)) {
		return FALSE;
	}

	status = ZwQueryInformationFile(FileHandle,
		&ioStatus,
		&basicFileInfo,
		sizeof(FILE_BASIC_INFORMATION),
		FileBasicInformation);

	if (!NT_SUCCESS(status)) {
		ZwClose(FileHandle);
		return FALSE;
	}

		status = ZwQueryInformationFile(FileHandle,
		&ioStatus,
		&standardFileInfo,
		sizeof(FILE_STANDARD_INFORMATION),
		FileStandardInformation);
		
	if (!NT_SUCCESS(status)) {
		ZwClose(FileHandle);
		return FALSE;
	}


	*modified = (basicFileInfo.ChangeTime.QuadPart - DIFF_TO_UNIX_EPOCH) / 10000;
	*size = standardFileInfo.EndOfFile.QuadPart;

	ZwClose(FileHandle);
	return TRUE;
}
Пример #4
0
EXTERN_C static NTSTATUS ScvnpReadFile(_In_ PFLT_CALLBACK_DATA Data,
                                       _In_ PCFLT_RELATED_OBJECTS FltObjects,
                                       _Out_ void *Buffer,
                                       _In_ ULONG BufferSize) {
  PAGED_CODE();

  // Use an existing file object when it is NOT IRP_MJ_CLEANUP.
  if (Data->Iopb->MajorFunction != IRP_MJ_CLEANUP) {
    LARGE_INTEGER byteOffset = {};
    auto status = FltReadFile(FltObjects->Instance, FltObjects->FileObject,
                              &byteOffset, BufferSize, Buffer,
                              FLTFL_IO_OPERATION_DO_NOT_UPDATE_BYTE_OFFSET,
                              nullptr, nullptr, nullptr);
    if (!NT_SUCCESS(status)) {
      LOG_ERROR_SAFE("FltReadFile failed (%08x)", status);
      return status;
    }
    return status;
  }

  PFILE_OBJECT fileObject = nullptr;

  // Make a new file object since the file is already out of the current IO
  // path.
  PFLT_FILE_NAME_INFORMATION fileNameInformation = nullptr;
  auto status = FltGetFileNameInformationUnsafe(
      FltObjects->FileObject, FltObjects->Instance, FLT_FILE_NAME_NORMALIZED,
      &fileNameInformation);
  if (!NT_SUCCESS(status)) {
    return status;
  }

  OBJECT_ATTRIBUTES objAttr = RTL_INIT_OBJECT_ATTRIBUTES(
      &fileNameInformation->Name, OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE);

  HANDLE fileHandle = nullptr;
  IO_STATUS_BLOCK ioStatus = {};
  status = FltCreateFile(
      FltObjects->Filter, FltObjects->Instance, &fileHandle, GENERIC_READ,
      &objAttr, &ioStatus, nullptr, FILE_ATTRIBUTE_NORMAL,
      FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, FILE_OPEN_IF,
      FILE_SEQUENTIAL_ONLY | FILE_SYNCHRONOUS_IO_NONALERT |
          FILE_NON_DIRECTORY_FILE,
      nullptr, 0, 0);
  if (!NT_SUCCESS(status)) {
    LOG_ERROR_SAFE("FltCreateFile failed (%08x) for %wZ", status,
                   &fileNameInformation->Name);
    goto End;
  }

  status = ObReferenceObjectByHandle(fileHandle, 0, nullptr, KernelMode,
                                     reinterpret_cast<void **>(&fileObject),
                                     nullptr);
  if (!NT_SUCCESS(status)) {
    LOG_ERROR_SAFE("ObReferenceObjectByHandle failed (%08x) for %wZ", status,
                   &fileNameInformation->Name);
    goto End;
  }

  status = FltReadFile(FltObjects->Instance, fileObject, nullptr, BufferSize,
                       Buffer, 0, nullptr, nullptr, nullptr);
  if (!NT_SUCCESS(status)) {
    LOG_ERROR_SAFE("FltReadFile failed (%08x) for %wZ", status,
                   &fileNameInformation->Name);
    goto End;
  }

End:
  if (fileObject) {
    ObDereferenceObject(fileObject);
  }
  if (fileHandle) {
    FltClose(fileHandle);
  }
  if (fileNameInformation) {
    FltReleaseFileNameInformation(fileNameInformation);
  }
  return status;
}
Пример #5
0
NTSTATUS
CopyFile(
		 PFLT_CALLBACK_DATA Data,
		 PCFLT_RELATED_OBJECTS FltObjects,
		 PUNICODE_STRING pCompleteFileName
		 )
{
	NTSTATUS status;
	UNICODE_STRING tempDeletedFilePath;
	OBJECT_ATTRIBUTES tempDeletedObject;
	IO_STATUS_BLOCK ioStatusTempDeleted;
	LARGE_INTEGER allocate;
	FILE_STANDARD_INFORMATION fileStandardInformation;
	HANDLE tempDeletedHandle;
	ULONG returnedLength;
	allocate.QuadPart = 0x10000;

	
	
	InitializeObjectAttributes(
		&tempDeletedObject,
		pCompleteFileName,
		OBJ_CASE_INSENSITIVE,
		NULL,
		NULL
		);
	status = FltQueryInformationFile(
		FltObjects->Instance,
		Data->Iopb->TargetFileObject,
		&fileStandardInformation,
		sizeof(FILE_STANDARD_INFORMATION),
		FileStandardInformation,
		&returnedLength
		);
	if(NT_SUCCESS(status))
	{
		allocate.QuadPart = fileStandardInformation.AllocationSize.QuadPart;
	} else {
		DbgPrint("CaptureFileMonitor: ERROR - Could not get files allocation size\n");
		return status;
	}

	status = FltCreateFile(
		FltObjects->Filter,
		NULL,
		&tempDeletedHandle,
		GENERIC_WRITE,
		&tempDeletedObject,
		&ioStatusTempDeleted,
		&allocate,
		FILE_ATTRIBUTE_NORMAL,
		0,
		FILE_CREATE,
		FILE_NON_DIRECTORY_FILE,
		NULL,
		0,
		0
		);

	if(NT_SUCCESS(status))
	{
		PVOID handleFileObject;
		PVOID pFileBuffer;
		LARGE_INTEGER offset;
	
		ULONG bytesRead = 0;
		ULONG bytesWritten = 0;
		offset.QuadPart = 0;
		status = ObReferenceObjectByHandle(
			tempDeletedHandle,
			0,
			NULL,
			KernelMode,
			&handleFileObject,
			NULL);
		if(!NT_SUCCESS(status))
		{
			DbgPrint("CaptureFileMonitor: ERROR - ObReferenceObjectByHandle - FAILED - %08x\n", status);
			return status;
		}
		
		pFileBuffer = ExAllocatePoolWithTag(NonPagedPool, 65536, FILE_POOL_TAG);
		
		if(pFileBuffer != NULL)
		{
			ObReferenceObject(Data->Iopb->TargetFileObject);
			do {
				IO_STATUS_BLOCK IoStatusBlock;
				bytesWritten = 0;
				status = FltReadFile(
					FltObjects->Instance,
					Data->Iopb->TargetFileObject,
					&offset,
					65536,
					pFileBuffer,
					FLTFL_IO_OPERATION_DO_NOT_UPDATE_BYTE_OFFSET,
					&bytesRead ,
					NULL,
					NULL
					);
			
				if(NT_SUCCESS(status) && bytesRead > 0)
				{
					/* You can't use FltWriteFile here */
					/* Instance may not be the same instance we want to write to eg a
					   flash drive writing a file to a ntfs partition */
					status = ZwWriteFile(
						tempDeletedHandle,
						NULL,
						NULL,
						NULL,
						&IoStatusBlock,
						pFileBuffer,
						bytesRead,
						&offset,
						NULL
						);
					if(NT_SUCCESS(status))
					{
						//DbgPrint("WriteFile: FltReadFile - %08x\n", status);
					}
					/*
					status = FltWriteFile(
						FltObjects->Instance,
						handleFileObject,
						&offset,
						bytesRead,
						pFileBuffer,
						FLTFL_IO_OPERATION_DO_NOT_UPDATE_BYTE_OFFSET,
						&bytesWritten,
						NULL,
						NULL
						);
						*/
				} else {
					//DbgPrint("CopyFile: FltReadFile - %08x\n", status);
					break;
				}
				offset.QuadPart += bytesRead;
			} while(bytesRead == 65536);
			ObDereferenceObject(Data->Iopb->TargetFileObject);
			ExFreePoolWithTag(pFileBuffer, FILE_POOL_TAG);
		}
		ObDereferenceObject(handleFileObject);
		FltClose(tempDeletedHandle);
	} else {
		if(status != STATUS_OBJECT_NAME_COLLISION)
		{
			DbgPrint("CaptureFileMonitor: ERROR - FltCreateFile FAILED - %08x\n",status);
			return status;
		}
	}
	return STATUS_SUCCESS;
}
Пример #6
0
/*---------------------------------------------------------
函数名称:	FileCreateByObjectNotCreated
函数描述:	在文件被打开前先通过该对象打开文件
输入参数:
			pfiInstance					过滤器实例
			pfoFileObject				文件对象
			pfpParameters				IRP参数
			phFileHandle				保存文件句柄的空间
			ulDesiredAccess				期望的权限

输出参数:
			phFileHandle 文件句柄
返回值:		
			STATUS_SUCCESS					成功	
			STATUS_OBJECT_NAME_NOT_FOUND	未查询到名称

其他:		如果查询名称失败(根本无名称)将返回
			STATUS_OBJECT_NAME_NOT_FOUND

			如果要同传入的文件对象权限一致,ulDesiredAccess
			可以置为NULL

			打开后需要使用FltClose关闭文件

更新维护:	2011.5.2     最初版本
			2011.7.28    修改了部分参数
			2012.1.2     Bug:返回值为成功打开,但句柄无效
---------------------------------------------------------*/
NTSTATUS 
FileCreateByObjectNotCreated(
	__in PFLT_INSTANCE pfiInstance,
	__in PFLT_FILE_NAME_INFORMATION pfniFileNameInformation,
	__in PFLT_PARAMETERS pfpParameters,
	__in_opt ULONG ulDesiredAccess,
	__out HANDLE * phFileHandle
	)
{
	//读取的数据内容 用于同加密标识比较
	WCHAR wBufferRead[ENCRYPTION_HEAD_LOGO_SIZE] = {0};

	//文件属性
	ULONG  FileAttributes;

	//共享权限
	ULONG  ShareAccess;

	//打开处理
	ULONG  CreateDisposition;
	
	//打开选项	
	ULONG  CreateOptions;

	//对象属性,用于打开文件时使用
	OBJECT_ATTRIBUTES oaObjectAttributes;

	//文件路径长度
	ULONG ulPathLength;

	//返回的Io状态
	IO_STATUS_BLOCK ioStatusBlock;

	//返回的状态
	NTSTATUS statusRet;

	//
	//填充数据
	//
	
	InitializeObjectAttributes(
		&oaObjectAttributes,
		&pfniFileNameInformation->Name,
		OBJ_KERNEL_HANDLE|OBJ_CASE_INSENSITIVE,
		NULL,
		NULL
		);

	CreateDisposition	= pfpParameters->Create.Options>>24;
	CreateOptions		= pfpParameters->Create.Options & 0x00ffffff;
	ShareAccess			= pfpParameters->Create.ShareAccess;
	FileAttributes		= pfpParameters->Create.FileAttributes;

	//
	//保存访问权限的值 如果没有设置
	//
	if(!ulDesiredAccess){
		ulDesiredAccess = 
			pfpParameters -> Create.SecurityContext -> DesiredAccess;
	}

	//
	//为了兼容Windows Xp,使用FltCreateFile
	//

	return FltCreateFile(
		pfltGlobalFilterHandle,
		pfiInstance,
		phFileHandle,
		ulDesiredAccess,
		&oaObjectAttributes,
		&ioStatusBlock,
		NULL,
		FileAttributes,
		ShareAccess,
		CreateDisposition,
		CreateOptions,
		NULL,
		NULL,
		IO_IGNORE_SHARE_ACCESS_CHECK
		);
}
Пример #7
0
NTSTATUS
FmmOpenMetadata (
    __in PFMM_INSTANCE_CONTEXT InstanceContext,
    __in BOOLEAN CreateIfNotPresent
    )
/*++

Routine Description:

    This routine opens or creates the Fmm metadata on the specified instance.

Arguments:

    InstanceContext     - Supplies the instance context for this instance.
    CreateIfNotPresent  - Supplies if the directory entry must be created if it is not present

Return Value:

    Returns the status of this operation.

Note:

    The caller must hold the instance context resource exclusive when this routine is called.

--*/
{
    OBJECT_ATTRIBUTES objectAttributes;
    IO_STATUS_BLOCK ioStatus;
    UNICODE_STRING fileName;
    NTSTATUS status;
    ULONG length;

    PAGED_CODE();

    DebugTrace( DEBUG_TRACE_METADATA_OPERATIONS,
                ("[Fmm]: Opening metadata file ... (Volume = %p, CreateIfNotPresent = %X)\n",
                 InstanceContext->Volume,
                 CreateIfNotPresent) );

    status = STATUS_SUCCESS;
    fileName.Buffer = NULL;

    //
    //  Get the volume name and construct the full metadata filename.
    //


    length = FMM_DEFAULT_VOLUME_NAME_LENGTH + FMM_METADATA_FILE_NAME_LENGTH;

#pragma warning(push)
#pragma warning(disable:4127) //  Conditional expression is constant
    while (TRUE) {

#pragma warning(pop)

        fileName.MaximumLength = (USHORT)length;

        status = FmmAllocateUnicodeString( &fileName );

        if (!NT_SUCCESS( status )) {

            goto FmmOpenMetadataCleanup;
        }

        status = FltGetVolumeName( InstanceContext->Volume, &fileName, &length );

        if (NT_SUCCESS( status )) {

            status = RtlAppendUnicodeToString( &fileName, FMM_METADATA_FILE_NAME );

            if (NT_SUCCESS( status )) {

                break;
            }
        } else {

            DebugTrace( DEBUG_TRACE_METADATA_OPERATIONS | DEBUG_TRACE_ERROR,
                        ("[Fmm]: Failed to get volume name (Volume = %p, Status = 0x%x)\n",
                         InstanceContext->Volume,
                         status) );
        }


        if (status != STATUS_BUFFER_TOO_SMALL) {

            goto FmmOpenMetadataCleanup;;
        }

        //
        //  Free the filename buffer since a bigger one will be allocated
        //  above
        //

        FmmFreeUnicodeString( &fileName );

        length += FMM_METADATA_FILE_NAME_LENGTH;
    }


    //
    //  Initialize the object attributes and open the file.
    //

    InitializeObjectAttributes( &objectAttributes,
                                &fileName,
                                OBJ_KERNEL_HANDLE,
                                NULL,
                                NULL );




RetryFltCreateFile:


    DebugTrace( DEBUG_TRACE_METADATA_OPERATIONS,
                ("[Fmm]: Calling FltCreateFile for metadata file %wZ (Volume = %p, Status = 0x%x)\n",
                 &fileName,
                 InstanceContext->Volume,
                 status) );


    //
    //  Mark the beginning of a file system operation
    //

    FmmBeginFileSystemOperation( InstanceContext );

    status = FltCreateFile( Globals.Filter,
                            InstanceContext->Instance,
                            &InstanceContext->MetadataHandle,
                            FILE_ALL_ACCESS,
                            &objectAttributes,
                            &ioStatus,
                            (PLARGE_INTEGER) NULL,
                            FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN,
                            FILE_SHARE_READ,
                            (CreateIfNotPresent ? FILE_OPEN_IF : FILE_OPEN),
                            0L,
                            NULL,
                            0L,
                            0 );

    //
    //  Mark the end of a file system operation
    //

    FmmEndFileSystemOperation( InstanceContext );


    if (!NT_SUCCESS( status )) {

        DebugTrace( DEBUG_TRACE_METADATA_OPERATIONS | DEBUG_TRACE_ERROR,
                    ("[Fmm]: FltCreateFile failure for metadata file %wZ (Volume = %p, Status = 0x%x)\n",
                     &fileName,
                     InstanceContext->Volume,
                     status) );

        if (CreateIfNotPresent && (status == STATUS_OBJECT_PATH_NOT_FOUND)) {

            //
            //  We need to create the metadata file and the creation failed
            //  because the SystemVolumeInformation folder does not exist.
            //  So, create the folder and try again.
            //

            DebugTrace( DEBUG_TRACE_METADATA_OPERATIONS,
                        ("[Fmm]: Creating SystemVolumeInformation folder for metadata file %wZ (Volume = %p, Status = 0x%x)\n",
                         &fileName,
                         InstanceContext->Volume,
                         status) );


            //
            //  Mark the beginning of a file system operation
            //

            FmmBeginFileSystemOperation( InstanceContext );

            status = FltCreateSystemVolumeInformationFolder( InstanceContext->Instance );

            //
            //  Mark the end of a file system operation
            //

            FmmEndFileSystemOperation( InstanceContext );



            if (NT_SUCCESS( status )) {

                //
                //  We have sucessfully created the SystemVolumeInformation folder
                //  Try to create the metadata file again
                //

                goto RetryFltCreateFile;
            } else {

                DebugTrace( DEBUG_TRACE_METADATA_OPERATIONS | DEBUG_TRACE_ERROR,
                            ("[Fmm]: FltCreateSystemVolumeInformationFolder failure for metadata file %wZ (Volume = %p, Status = 0x%x)\n",
                             &fileName,
                             InstanceContext->Volume,
                             status) );
            }
        }

        goto FmmOpenMetadataCleanup;
    }

    //
    //  Retrieve the FileObject from the handle created
    //

    status = ObReferenceObjectByHandle( InstanceContext->MetadataHandle,
                                        STANDARD_RIGHTS_REQUIRED,
                                        *IoFileObjectType,
                                        KernelMode,
                                        &InstanceContext->MetadataFileObject,
                                        NULL );
    if (!NT_SUCCESS( status )) {

        DebugTrace( DEBUG_TRACE_METADATA_OPERATIONS | DEBUG_TRACE_ERROR,
                    ("[Fmm]: Failure to get file object from handle for metadata file %wZ (Volume = %p, Status = 0x%x)\n",
                     &fileName,
                     InstanceContext->Volume,
                     status) );

        goto FmmOpenMetadataCleanup;
    }

    if (ioStatus.Information == FILE_CREATED) {

        //
        //  New metadata was created
        //

        DebugTrace( DEBUG_TRACE_METADATA_OPERATIONS,
                    ("[Fmm]: Created new metadata file %wZ (Volume = %p, Status = 0x%x)\n",
                     &fileName,
                     InstanceContext->Volume,
                     status) );

        //
        //  The filter may want to do some initialization on the newly created
        //  metadata file here like adding a header to the file
        //

    }
    else {

        //
        //  Existing metadata was opened
        //

        DebugTrace( DEBUG_TRACE_METADATA_OPERATIONS,
                    ("[Fmm]: Opened existing metadata file %wZ (Volume = %p, Status = 0x%x)\n",
                     &fileName,
                     InstanceContext->Volume,
                     status) );

        //
        //  The filter may want to do some sanity checks on the metadata file here
        //  like validating the header of the file
        //

    }

    //
    //  Here the filter may read the metadata contents and initialize
    //  its in memory data structures with the data from the metadata
    //  file
    //


FmmOpenMetadataCleanup:

    if (!NT_SUCCESS( status )) {

        DebugTrace( DEBUG_TRACE_METADATA_OPERATIONS | DEBUG_TRACE_ERROR,
                    ("[Fmm]: Failed to open metadata (Volume = %p, Status = 0x%x)\n",
                     InstanceContext->Volume,
                     status) );

        //
        //  CLose the handle and dereference the file object
        //

        if (InstanceContext->MetadataHandle) {


            //
            //  Mark the beginning of a file system operation
            //

            FmmBeginFileSystemOperation( InstanceContext );

            FltClose( InstanceContext->MetadataHandle );

            //
            //  Mark the end of a file system operation
            //

            FmmEndFileSystemOperation( InstanceContext );

            InstanceContext->MetadataHandle = NULL;

            if (InstanceContext->MetadataFileObject) {

                ObDereferenceObject( InstanceContext->MetadataFileObject );
                InstanceContext->MetadataFileObject = NULL;
            }
        }
    } else {

        DebugTrace( DEBUG_TRACE_METADATA_OPERATIONS,
                    ("[Fmm]: Metadata successfully opened (Volume = %p)\n",
                     InstanceContext->Volume) );

        //
        //  Set flags to indicate successful open of filter metadata
        //

        SetFlag( InstanceContext->Flags, INSTANCE_CONTEXT_F_METADATA_OPENED );

    }

    if (fileName.Buffer != NULL) {

        FmmFreeUnicodeString( &fileName );
    }

    return status;
}