Example #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;
}
Example #2
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;
}
VOID
CreateADirectory(PFLT_INSTANCE pInstance,
				PUNICODE_STRING pDirectoryPath)
{
	NTSTATUS status;
	OBJECT_ATTRIBUTES directoryAttributesObject;
	IO_STATUS_BLOCK directoryIoStatusBlock;
	LARGE_INTEGER allocate;
	HANDLE hDirectory;
	allocate.QuadPart = 0x1000;
	
	InitializeObjectAttributes(
		&directoryAttributesObject,
		pDirectoryPath,
		OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE,
		NULL,
		NULL
		);

	/* You can't use FltCreateFile 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 = ZwCreateFile(
		&hDirectory,
		0,
		&directoryAttributesObject,
		&directoryIoStatusBlock,
		&allocate,
		0,
		0,
		FILE_CREATE,
		FILE_DIRECTORY_FILE|FILE_SYNCHRONOUS_IO_NONALERT|FILE_WRITE_THROUGH,
		NULL,
		0
		);
	/*
	status = FltCreateFile(
		fileManager.pFilter,
		pInstance,
		&hDirectory,
		0,
		&directoryAttributesObject,
		&directoryIoStatusBlock,
		&allocate,
		0,
		0,
		FILE_CREATE,
		FILE_DIRECTORY_FILE|FILE_SYNCHRONOUS_IO_NONALERT|FILE_WRITE_THROUGH,
		NULL,
		0,
		0
		);
	*/
	if(NT_SUCCESS(status) && NT_SUCCESS(directoryIoStatusBlock.Status))
	{
		FltClose(hDirectory);
	} else {
		if(status != STATUS_OBJECT_NAME_COLLISION)
		{
			DbgPrint("CaptureFileMonitor: CreateADirectory ERROR %08x & %08x\n", status, directoryIoStatusBlock.Status);
		}
	}
}
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;
}
Example #5
0
NTSTATUS 
NcEnumerateDirectorySetupInjection (
    _Inout_ PNC_DIR_QRY_CONTEXT DirQryCtx,
    _In_ PCFLT_RELATED_OBJECTS FltObjects,
    _In_ PNC_INSTANCE_CONTEXT InstanceContext,
    _In_ PDIRECTORY_CONTROL_OFFSETS Offsets,
    _In_ FILE_INFORMATION_CLASS InformationClass
    )
/*++

Routine Description:

    Sets up directory enumeration context cache so that we are ready to
    perform injection.

Arguments:

    DirQryCtx - Pointer to directory query context (on the stream handle.)

    FltObjects - FltObjects structure for this operation.
    
    InstanceContext - Instance Context for this operation.

    Offsets - Offsets structure for this information class.

    InformationClass - The information class for this operation.

Return Value:

    Returns STATUS_SUCCESS on success, otherwise an appropriate error code.

--*/
{
    NTSTATUS Status;

    OBJECT_ATTRIBUTES RealParentAttributes;
    HANDLE RealParentHandle = 0; //close always
    PFILE_OBJECT RealParentFileObj = NULL;
    IO_STATUS_BLOCK RealParentStatusBlock;
    char * QueryBuffer = NULL; //free on error, when no injection
    ULONG QueryBufferLength = 0;
    USHORT NameLength;
    ULONG QueryBufferLengthRead;
    BOOLEAN IgnoreCase = !BooleanFlagOn( FltObjects->FileObject->Flags,
                                         FO_OPENED_CASE_SENSITIVE );

    PAGED_CODE();


    //
    //  If the user has specified a search string, and if our user mapping
    //  should not be returned in this search string, return success.  We
    //  don't need to inject anything.
    //

    if (DirQryCtx->SearchString.Length > 0 &&
        !FsRtlIsNameInExpression( &DirQryCtx->SearchString,
                                  &InstanceContext->Mapping.UserMapping.LongNamePath.FinalComponentName,
                                  IgnoreCase,
                                  NULL ) &&
        !FsRtlIsNameInExpression( &DirQryCtx->SearchString,
                                  &InstanceContext->Mapping.UserMapping.ShortNamePath.FinalComponentName,
                                  IgnoreCase,
                                  NULL )) {

        Status = STATUS_SUCCESS;
        goto NcEnumerateDirectorySetupCleanup;
    }

    //
    //  Initialize insertion info.
    //
    //  We have to insert the final component of the real mapping
    //  as the final component of the user mapping. To do this we
    //  will open the parent of the real mapping, and query the real
    //  mapping.
    //  Then we will overwrite the real mapping's name with
    //  the final component of the user mapping. This data will be
    //  stored in the DirQryCtx for later injection.
    //

    //
    //  Open parent of real mapping.
    //

    InitializeObjectAttributes( &RealParentAttributes,
                                &InstanceContext->Mapping.RealMapping.LongNamePath.ParentPath,
                                OBJ_KERNEL_HANDLE,
                                NULL,
                                NULL);

    Status = NcCreateFileHelper( NcGlobalData.FilterHandle,            // Filter
                                 FltObjects->Instance,                 // InstanceOffsets
                                 &RealParentHandle,                    // Returned Handle
                                 &RealParentFileObj,                   // Returned FileObject
                                 FILE_LIST_DIRECTORY|FILE_TRAVERSE,    // Desired Access
                                 &RealParentAttributes,                // object attributes
                                 &RealParentStatusBlock,               // Returned IOStatusBlock
                                 0,                                    // Allocation Size
                                 FILE_ATTRIBUTE_NORMAL,                // File Attributes
                                 0,                                    // Share Access
                                 FILE_OPEN,                            // Create Disposition
                                 FILE_DIRECTORY_FILE,                  // Create Options
                                 NULL,                                 // Ea Buffer
                                 0,                                    // EA Length
                                 IO_IGNORE_SHARE_ACCESS_CHECK,         // Flags
                                 FltObjects->FileObject );             // Transaction state
   
    if (!NT_SUCCESS( Status )) {

        goto NcEnumerateDirectorySetupCleanup;
    }

    //
    //  Allocate Buffer to store mapping data.
    //

    NameLength = Max( InstanceContext->Mapping.RealMapping.LongNamePath.FinalComponentName.Length,
                      InstanceContext->Mapping.UserMapping.LongNamePath.FinalComponentName.Length );

    QueryBufferLength = Offsets->FileNameDist + NameLength;

    QueryBuffer = ExAllocatePoolWithTag( PagedPool, QueryBufferLength, NC_DIR_QRY_CACHE_TAG );

    if (QueryBuffer == NULL) {

        Status = STATUS_INSUFFICIENT_RESOURCES;
        goto NcEnumerateDirectorySetupCleanup;
    }

    //
    //  Query the information from the parent of the real mapping.
    //

    Status = NcQueryDirectoryFile( FltObjects->Instance,
                                   RealParentFileObj,
                                   QueryBuffer,
                                   QueryBufferLength,
                                   InformationClass,
                                   TRUE,//Return single entry
                                   &InstanceContext->Mapping.RealMapping.LongNamePath.FinalComponentName,
                                   FALSE,//restart scan
                                   &QueryBufferLengthRead);

    if (Status == STATUS_NO_SUCH_FILE) {

        //
        //  The user mapping does not exist, this is allowed. It means we
        //  have nothing to inject.
        //

        DirQryCtx->InjectionEntry.Buffer = NULL;
        DirQryCtx->InjectionEntry.CurrentOffset = 0;

        ExFreePoolWithTag( QueryBuffer, NC_DIR_QRY_CACHE_TAG );
        QueryBuffer = NULL;

        Status = STATUS_SUCCESS;

    } else if (!NT_SUCCESS( Status )) {

        //
        //  An unexpected error occurred, return code.
        //

        goto NcEnumerateDirectorySetupCleanup;
        
    } else {

        //
        //  Now we have to munge the real mapping directory entry into a
        //  user mapping directory entry.
        //

        NcSetFileName( QueryBuffer,
                       InstanceContext->Mapping.UserMapping.LongNamePath.FinalComponentName.Buffer,
                       InstanceContext->Mapping.UserMapping.LongNamePath.FinalComponentName.Length,
                       Offsets,
                       TRUE );

        NcSetShortName( QueryBuffer,
                        InstanceContext->Mapping.UserMapping.ShortNamePath.FinalComponentName.Buffer,
                        InstanceContext->Mapping.UserMapping.ShortNamePath.FinalComponentName.Length,
                        Offsets );

        FLT_ASSERT( DirQryCtx->InjectionEntry.Buffer == NULL );

        //
        //  Set the injection entry up in the cache.
        //

        DirQryCtx->InjectionEntry.Buffer = QueryBuffer;
        DirQryCtx->InjectionEntry.CurrentOffset = 0;
    }

NcEnumerateDirectorySetupCleanup:

    if (!NT_SUCCESS( Status )) {

        if(QueryBuffer != NULL) {

            ExFreePoolWithTag( QueryBuffer, NC_DIR_QRY_CACHE_TAG );
        }

    }

    if (RealParentHandle != NULL) {

        FltClose( RealParentHandle );
    }

    if (RealParentFileObj != NULL) {

        ObDereferenceObject( RealParentFileObj );
    }

    return Status;
}
Example #6
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;
}
Example #7
0
VOID
FmmCloseMetadata (
    __in PFMM_INSTANCE_CONTEXT InstanceContext
    )
/*++

Routine Description:

    This routine closes the filters handle to the metadata file.

Arguments:

    InstanceContext - Instance context for this instance.

Return Value:

    Void.

Note:

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


--*/
{
    PAGED_CODE();

    ASSERT( InstanceContext->MetadataHandle );
    ASSERT( InstanceContext->MetadataFileObject );

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

    //
    //  Dereference the file object and close the file handle.
    //

    ObDereferenceObject( InstanceContext->MetadataFileObject );

    InstanceContext->MetadataFileObject = NULL;


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

    //
    //  Reset flag to indicate filter metadata is closed
    //

    ClearFlag( InstanceContext->Flags, INSTANCE_CONTEXT_F_METADATA_OPENED );

}