コード例 #1
0
ファイル: X70Fsd.c プロジェクト: wyrover/X70FSD
NTSTATUS GenerateFileName(IN PFLT_INSTANCE  Instance,
    IN PFILE_OBJECT  FileObject,
    IN PFLT_CALLBACK_DATA  CallbackData,
    IN FLT_FILE_NAME_OPTIONS  NameOptions,
    OUT PBOOLEAN  CacheFileNameInformation,
    OUT PFLT_NAME_CONTROL  FileName
) //上层的minifilter过滤驱动的名字请求进行处理
{
	NTSTATUS Status = STATUS_UNSUCCESSFUL;
	PFILE_OBJECT StreamObject = FileObject;
	PFLT_FILE_NAME_INFORMATION FileNameInformation = NULL;
	BOOLEAN bEncryptResource = FALSE;
	PFCB Fcb = FileObject->FsContext;
	PCCB Ccb = FileObject->FsContext2;

	FsRtlEnterFileSystem();

	try
	{
		if(IsMyFakeFcb(FileObject))
		{
			

			ExAcquireResourceSharedLite(Fcb->EncryptResource,TRUE);
			bEncryptResource = TRUE;

			if(BooleanFlagOn(Fcb->FcbState,SCB_STATE_SHADOW_CLOSE) || Ccb->StreamFileInfo.StreamObject == NULL)
			{
				try_return (Status = STATUS_FILE_DELETED);
			}
			else
			{			
				StreamObject = Ccb->StreamFileInfo.StreamObject;
			}
		}

		ClearFlag(NameOptions,FLT_FILE_NAME_REQUEST_FROM_CURRENT_PROVIDER);

		if(FlagOn(NameOptions,FLT_FILE_NAME_NORMALIZED))
		{
			ClearFlag(NameOptions,FLT_FILE_NAME_NORMALIZED);
			SetFlag(NameOptions,FLT_FILE_NAME_OPENED);
		}
		
		if (CallbackData) 
		{
			PFILE_OBJECT TemFileObject = CallbackData->Iopb->TargetFileObject;
			CallbackData->Iopb->TargetFileObject = StreamObject;

			FltSetCallbackDataDirty(CallbackData);

			Status = FltGetFileNameInformation(CallbackData,NameOptions, &FileNameInformation);
			
			CallbackData->Iopb->TargetFileObject = TemFileObject;
			FltClearCallbackDataDirty(CallbackData);
		} 
		else 
		{
			Status = FltGetFileNameInformationUnsafe(StreamObject,Instance, NameOptions, &FileNameInformation);
		}
		if(!NT_SUCCESS(Status))
		{
			try_return (Status);
		}
		Status = FltCheckAndGrowNameControl(FileName, FileNameInformation->Name.Length);

		if(!NT_SUCCESS(Status))
		{
			try_return (Status);
		}

		RtlCopyUnicodeString(&FileName->Name, &FileNameInformation->Name);

		if(FileNameInformation != NULL)
		{
			FltReleaseFileNameInformation(FileNameInformation);
		}
		Status = STATUS_SUCCESS;
try_exit: NOTHING;
	}
	finally
	{
		if(bEncryptResource)
		{
			ExReleaseResourceLite( Fcb->EncryptResource );
		}
	}
	FsRtlExitFileSystem();
	return Status;
}
コード例 #2
0
ファイル: ncnameprov.c プロジェクト: 340211173/Driver
NTSTATUS
NcGenerateFileName (
    _In_ PFLT_INSTANCE Instance,
    _In_ PFILE_OBJECT FileObject,
    _In_opt_ PFLT_CALLBACK_DATA Data,
    _In_ FLT_FILE_NAME_OPTIONS NameOptions,
    _Out_ PBOOLEAN CacheFileNameInformation,
    _Inout_ PFLT_NAME_CONTROL OutputNameControl
    )
{
    //
    //  Status vars
    //

    NTSTATUS Status;

    //
    //  State lookup vars
    //

    BOOLEAN Opened = (BOOLEAN)(FileObject->FsContext != NULL);                                       // True if file object is opened.
    BOOLEAN ReturnShortName = (BOOLEAN)(FltGetFileNameFormat(NameOptions) == FLT_FILE_NAME_SHORT);   // True if the user is requesting short name
    BOOLEAN ReturnOpenedName = (BOOLEAN)(FltGetFileNameFormat(NameOptions) == FLT_FILE_NAME_OPENED); // True if user is requesting opened name.
    BOOLEAN ReturnNormalizedName = (BOOLEAN)(FltGetFileNameFormat(NameOptions) == FLT_FILE_NAME_NORMALIZED); // True if user is requesting normalized name.
    BOOLEAN IgnoreCase;
    FLT_FILE_NAME_OPTIONS NameQueryMethod = FltGetFileNameQueryMethod( NameOptions );
    FLT_FILE_NAME_OPTIONS NameFlags = FLT_VALID_FILE_NAME_FLAGS & NameOptions;

    //
    //  File name information
    //

    PFLT_FILE_NAME_INFORMATION LowerNameInfo = NULL; // File name as reported by lower name provider. Will always be down real mapping.
    PFLT_FILE_NAME_INFORMATION ShortInfo = NULL;  // We will use ShortInfo to store the short name if needed.

    //
    //  Contexts
    //
    
    PNC_INSTANCE_CONTEXT InstanceContext = NULL;

    //
    //  Overlap
    //
    
    NC_PATH_OVERLAP RealOverlap;
    UNICODE_STRING RealRemainder = EMPTY_UNICODE_STRING;

    //
    //  Temp storage
    //
    
    UNICODE_STRING MungedName = EMPTY_UNICODE_STRING;
    
    //
    //  Temp pointer
    //
    
    PUNICODE_STRING Name = NULL; // Pointer to the name we are going to use.

    PAGED_CODE();

    FLT_ASSERT( IoGetTopLevelIrp() == NULL );

    //
    //  This should never happen, but let's be safe.
    //

    if (!ReturnShortName &&
        !ReturnOpenedName &&
        !ReturnNormalizedName) {

        FLT_ASSERT( FALSE );
        Status = STATUS_NOT_SUPPORTED;
        goto NcGenerateFileNameCleanup;
    }

    RealOverlap.EntireFlags = 0;

    //
    //  To prevent infinite recursion, calls to FltGetFileNameInformation 
    //  from generate file name callbacks should not target current provider.
    //

    ClearFlag( NameFlags, FLT_FILE_NAME_REQUEST_FROM_CURRENT_PROVIDER );

    //
    //  Fetch the instance context.
    //

    Status = FltGetInstanceContext( Instance, &InstanceContext );   

    if (!NT_SUCCESS( Status )) {

        goto NcGenerateFileNameCleanup;
    }

    //
    //  We need to know what the name provider under us thinks the file is called.
    //  If the caller wants the normalized name we query that, otherwise we query
    //  the opened name because we have to compare the full path of the file vs.
    //  the real mapping to determine if the file is mapped.
    //

    Status = NcGetFileNameInformation( Data,
                                       FileObject,
                                       Instance,
                                       (ReturnNormalizedName ? FLT_FILE_NAME_NORMALIZED
                                                             : FLT_FILE_NAME_OPENED) |
                                           NameQueryMethod |
                                           NameFlags,
                                       &LowerNameInfo );

    if (!NT_SUCCESS( Status )) {

        goto NcGenerateFileNameCleanup;
    }

    Status = FltParseFileNameInformation( LowerNameInfo );

    if (!NT_SUCCESS( Status )) {

        goto NcGenerateFileNameCleanup;
    }

    //
    //  Issues With Pre-open path:
    //
    //  1) Poison name cache below name provider:
    //    If a filter above a name provider calls FltGetFileNameInformation on a 
    //    file object in his precreate callback, fltmgr will call the name 
    //    provider's generate name callback before the name provider's pre create
    //    callback is invoked. Name providers by their nature change names in their
    //    pre-create. Because the name provider has not had the opportunity to 
    //    modify the name yet, we need to make sure that fltmgr does not cache the name we 
    //    return below us, so we set the FLT_FILE_NAME_DO_NOT_CACHE flag.
    //    //TODO: TRY TO GET ACROSS THAT THIS IS A NAME CHANGER PROBLEM, NOT ALL NAME PROVIDERS NEED TO.
    //

    if (!Opened) {

        SetFlag( NameFlags, FLT_FILE_NAME_DO_NOT_CACHE );

        if (Data) {

            //
            //  NT supports case sensitive and non-case sensitive naming in file systems.
            //  This is handled on a per-open basis. Weather an open is case senstive is 
            //  determined by the FO_OPENED_CASE_SENSITIVE flag on the file object.
            //  In pre-create the SL_CASE_SENSITIVE flag on the create IRP specifies the mode.
            //
            //  If this is on an unopened FileObject, it had better be pre-create so we know
            //  how to process the operation.  If we are queried on an unopened FileObject
            //  at any other time we have no way to handle the request.
            //

            FLT_ASSERT( Data->Iopb->MajorFunction == IRP_MJ_CREATE ||
                        Data->Iopb->MajorFunction == IRP_MJ_NETWORK_QUERY_OPEN );

            IgnoreCase = !BooleanFlagOn( Data->Iopb->OperationFlags, SL_CASE_SENSITIVE );

        } else {

            //
            //  If people do unsafe queries on preopened IOs, we cannot
            //  determine if the open is case sensitive or not.
            //  So we cannot determine if this open is down the mapping.
            //  fail.
            //

            FLT_ASSERT( FALSE );
            Status = STATUS_INVALID_PARAMETER;
            goto NcGenerateFileNameCleanup;

        }

    } else {

        //
        //  After a file has been opened, the case sensitivity is stored in the file object.
        //

        IgnoreCase = !BooleanFlagOn( FileObject->Flags, FO_OPENED_CASE_SENSITIVE );
    }

    //
    //  Calculate the overlap with the real mapping.
    //

    NcComparePath( &LowerNameInfo->Name,
                   &InstanceContext->Mapping.RealMapping,
                   &RealRemainder,
                   IgnoreCase,
                   TRUE,
                   &RealOverlap );

    //
    //  Whether we munge depends on what name is requested.
    //

    if (ReturnOpenedName ||
        ReturnNormalizedName) {

        if (Opened &&
            RealOverlap.InMapping) {

            //
            //  We munge the opened name if it overlaps with the real mapping.
            //  The returned path will be down the user mapping.
            //

            Status = NcConstructPath( &InstanceContext->Mapping.UserMapping,
                                      &RealRemainder,
                                      TRUE,
                                      &MungedName);

            if (!NT_SUCCESS( Status )) {

                goto NcGenerateFileNameCleanup;
            }

            Name = &MungedName;

        } else {

            //
            //  We return the queried result if the path is not in the
            //  mapping.
            //

            Name = &LowerNameInfo->Name;

        }

    } else if (ReturnShortName) {

        //
        //  Note that unlike opened names, a query for a shortname only returns
        //  the final component, not the full path.
        //

        // TODO: Assert not preopen

        if (RealOverlap.Match) {

            //
            //  The opened path is the mapping path.
            //  This means that if we queried the filesystem
            //  he would return the wrong path.
            //
            //  Luckily, we can just use the mapping.
            //

            Name = &InstanceContext->Mapping.UserMapping.ShortNamePath.FinalComponentName;

        } else {

            //
            //  We have to query below us to get the short name.
            //

            Status = NcGetFileNameInformation( Data,
                                               FileObject,
                                               Instance,
                                               FLT_FILE_NAME_SHORT | 
                                                   NameQueryMethod |
                                                   NameFlags,
                                               &ShortInfo );

            if (!NT_SUCCESS( Status )) {

                goto NcGenerateFileNameCleanup;
            }

            Status = FltParseFileNameInformation( ShortInfo );

            if (!NT_SUCCESS(Status)) {

                goto NcGenerateFileNameCleanup;
            }

            //
            //  Set name to returned name.
            //

            Name = &ShortInfo->Name;
        }
    }

    FLT_ASSERT( Name != NULL );

    //
    //  Try to grow the namechanger's record to accommodate the result.
    //

    Status = FltCheckAndGrowNameControl( OutputNameControl, Name->Length );

    if (NT_SUCCESS( Status )) {

        //
        //  Copy the new name into the buffer.
        //

        RtlCopyUnicodeString( &OutputNameControl->Name, Name );
        *CacheFileNameInformation = TRUE;
    }

NcGenerateFileNameCleanup:

    if (LowerNameInfo != NULL) {

        FltReleaseFileNameInformation( LowerNameInfo );
    }

    if (ShortInfo != NULL) {

        FltReleaseFileNameInformation( ShortInfo );
    }

    if (InstanceContext != NULL) {

        FltReleaseContext( InstanceContext );
    }

    if (MungedName.Buffer != NULL) {

        ExFreePoolWithTag( MungedName.Buffer, NC_GENERATE_NAME_TAG );
    }

    return Status;
}