Exemplo n.º 1
0
/*************************************************************************
MiniFilter callback routines.
*************************************************************************/
FLT_PREOP_CALLBACK_STATUS
PtPreOperationPassThrough (
						   __inout PFLT_CALLBACK_DATA Data,
						   __in PCFLT_RELATED_OBJECTS FltObjects,
						   __deref_out_opt PVOID *CompletionContext
						   )
						   /*++

						   Routine Description:

						   This routine is the main pre-operation dispatch routine for this
						   miniFilter. Since this is just a simple passThrough miniFilter it
						   does not do anything with the callbackData but rather return
						   FLT_PREOP_SUCCESS_WITH_CALLBACK thereby passing it down to the next
						   miniFilter in the chain.

						   This is non-pageable because it could be called on the paging path

						   Arguments:

						   Data - Pointer to the filter callbackData that is passed to us.

						   FltObjects - Pointer to the FLT_RELATED_OBJECTS data structure containing
						   opaque handles to this filter, instance, its associated volume and
						   file object.

						   CompletionContext - The context for the completion routine for this
						   operation.

						   Return Value:

						   The return value is the status of the operation.

						   --*/
{
	NTSTATUS status;
	FLT_PREOP_CALLBACK_STATUS FltStatus = FLT_PREOP_COMPLETE;

	UNREFERENCED_PARAMETER( FltObjects );
	UNREFERENCED_PARAMETER( CompletionContext );

	PT_DBG_PRINT( PTDBG_TRACE_ROUTINES,
		("PassThrough!PtPreOperationPassThrough: Entered\n") );

	if(IsMyFakeFcb(FltObjects->FileObject))
	{

		if(FLT_IS_FASTIO_OPERATION(Data)) 
		{
			/*DbgPrint("收到我们自己的fcb请求MajorFunction %x \n",Data->Iopb->MajorFunction );
			DbgPrint("收到我们自己的fcb请求MinorFunction  %x \n",Data->Iopb->MinorFunction  );
			DbgPrint("FastIo Passthru \n");*/
			FltStatus = FLT_PREOP_DISALLOW_FASTIO ;
			return FltStatus;
		}
		if(FLT_IS_IRP_OPERATION(Data))
		{
			DbgPrint("收到我们自己的fcb请求MajorFunction %x \n",Data->Iopb->MajorFunction );
			DbgPrint("收到我们自己的fcb请求MinorFunction  %x \n",Data->Iopb->MinorFunction  );
			DbgPrint("Irp Passthru \n");

			FltStatus = X70FsdPrePassThroughIrp(Data,FltObjects,CompletionContext);		
			return FltStatus;
		}
		if(FLT_IS_FS_FILTER_OPERATION(Data))
		{
			Data->IoStatus.Status = STATUS_INVALID_DEVICE_REQUEST;
			return FltStatus;
		}
	}

	//
	//  See if this is an operation we would like the operation status
	//  for.  If so request it.
	//
	//  NOTE: most filters do NOT need to do this.  You only need to make
	//        this call if, for example, you need to know if the oplock was
	//        actually granted.
	//

	if (PtDoRequestOperationStatus( Data )) {

		status = FltRequestOperationStatusCallback( Data,
			PtOperationStatusCallback,
			(PVOID)(++OperationStatusCtx) );
		if (!NT_SUCCESS(status)) {

			PT_DBG_PRINT( PTDBG_TRACE_OPERATION_STATUS,
				("PassThrough!PtPreOperationPassThrough: FltRequestOperationStatusCallback Failed, status=%08x\n",
				status) );
		}
	}

	return FLT_PREOP_SUCCESS_WITH_CALLBACK;
}
FLT_PREOP_CALLBACK_STATUS
OcCrFsmfPreOperation(
    __inout PFLT_CALLBACK_DATA Data,
    __in PCFLT_RELATED_OBJECTS FltObjects,
    __deref_out_opt PVOID *CompletionContext
    )
/*++

Routine Description:

    This routine is the main pre-operation dispatch routine for this
    miniFilter.
    This function could be called on the paging path!

Arguments:

    Data - Pointer to the filter callbackData that is passed to us.

    FltObjects - Pointer to the FLT_RELATED_OBJECTS data structure containing
        opaque handles to this filter, instance, its associated volume and
        file object.
        If FltObjects is NULL the call is from the FSD hooker!

    CompletionContext - The context for the completion routine for this
        operation.

Return Value:

    The return value is the status of the operation.

--*/
{
    PFILE_OBJECT         FileObject;
    POC_DEVICE_OBJECT    PtrOcDeviceObject;
    POC_FILE_OBJECT      OcFileObject = NULL;
    OC_MINIFLTR_DRV_NODE_CTX    Context = { 0x0 };
    BOOLEAN              RequestFromMinifilter = !OcCrFltIsEmulatedCall( FltObjects );

    ASSERT( KeGetCurrentIrql() <= APC_LEVEL );
    ASSERT( ( NULL==FltObjects )? ( FALSE==RequestFromMinifilter ): ( TRUE==RequestFromMinifilter ) );

    //
    // sanity check for case of buggy driver sending FSD requests at dispatch level
    //
    if( KeGetCurrentIrql() > APC_LEVEL )
        return FLT_PREOP_SUCCESS_NO_CALLBACK;

    //
    // I am interested only in the IRP based operations,
    // processing of non Irp based operations will result
    // in an overload due to an enormous cashed requests processing( Fast IO )
    //
    if( !FLT_IS_IRP_OPERATION( Data ) )
        return FLT_PREOP_SUCCESS_NO_CALLBACK;

#if DBG
    Context.Common.Signature = OC_NODE_CTX_SIGNATURE;
    Context.Common.Size = sizeof( Context );
#endif// DBG
    Context.Common.Flags = OcNodeCtxMinifilterDriverFlag;
    Context.Common.MiniFilterStatus = FLT_PREOP_SUCCESS_NO_CALLBACK;
    Context.Common.RequestData.Data = Data;
    Context.Common.OriginalDeviceObject = NULL;
    Context.Common.RequestCurrentParameters.UpperDevice = 0x1;
    Context.FltObjects = FltObjects;
    if( OcCrFltEmulIs32bitProcess( Data, FltObjects ) ){

        OcSetFlag( Context.Common.Flags, OcNodeCtx32bitProcessFlag );
    }

#if DBG
    *CompletionContext = NULL;
#endif//DBG

    //
    // process a special case - the close request, the close
    // request must be successful in any case, the returned
    // code is not checked by the system
    //
    if( IRP_MJ_CLOSE == Data->Iopb->MajorFunction ){

        //
        // remove the fileobject from the hash and delete it
        //
        OcCrProcessFileObjectCloseRequest( Data->Iopb->TargetFileObject );

        //
        // nothing to do with this request in a preoperation or postoperation callbacks
        //
        ASSERT( FLT_PREOP_SUCCESS_NO_CALLBACK == Context.Common.MiniFilterStatus );
        return Context.Common.MiniFilterStatus;
    }

    //
    // get a device object on which a FSD is mounted
    //
    FileObject = Data->Iopb->TargetFileObject;
    if( NULL != FileObject )
        PtrOcDeviceObject = OcCrGetDeviceObjectOnWhichFsdMounted( FileObject );
    else
        PtrOcDeviceObject = NULL;

    if( NULL == PtrOcDeviceObject )
        return Context.Common.MiniFilterStatus;

    //
    // if the device is not started yet then do nothing with it,
    // PnP requests are processed through the callbacks registered with
    // PnP filter
    //
    if( NotStarted == PtrOcDeviceObject->PnPState )
        return Context.Common.MiniFilterStatus;

    //
    // if FOs opened on this device are under control then
    // try to retrieve a FO from the FOs database
    //
    if( 0x1 == PtrOcDeviceObject->Flags.SpyFileObjects ){

        ASSERT( NULL == Context.FileObject );

        //
        // get the file object
        //
        Context.FileObject = OcCrRetriveReferencedFileObject( Data->Iopb->TargetFileObject );

        //
        // process the case when a FSD uses stream file
        // objects for supporting FOs' shared cache map, very often
        // this stream FO also backs a segment object and therefore 
        // is used for flushing mapped portions of a data stream
        // and processing page faults
        //
        if( NULL == Context.FileObject && 
            ( IRP_MJ_WRITE == Data->Iopb->MajorFunction || IRP_MJ_READ == Data->Iopb->MajorFunction ) ){

            NTSTATUS    RC;

            //
            // the function returns a referenced file object
            //
            RC = OcCrProcessFileObjectCreating( Data->Iopb->TargetFileObject,
                                                NULL,
                                                TRUE,
                                                &Context.FileObject );
            if( !NT_SUCCESS( RC ) )
                Context.FileObject = NULL;

        }//if( NULL == Context.FileObject && 
    }


    if( NULL != Context.FileObject && 
        FALSE == RequestFromMinifilter &&
        OcCrIsRequestInFsdDeviceQueue( PtrOcDeviceObject, Data, Context.FileObject ) ){

        //
        // the operation is already in the volume list
        //
        goto __exit;
    }

    //
    // get the access requested by the caller
    //
    Context.Common.SecurityParameters.RequestedAccess = OcCrGetFsdRequestedAccess( 
                                                &Context,
                                                PtrOcDeviceObject );

    //
    // rmemeber that the direct access has been required
    //
    if( DIRECT_DEVICE_OPEN & Context.Common.SecurityParameters.RequestedAccess )
        Context.Common.RequestCurrentParameters.DirectDeviceOpenRequest = 0x1;

    //
    // nothing to do if the requested access is 0x0 and 
    // the device should not be shadowed, i.e.
    // there is no need to track all file objects
    // opend on this device( this will be checked later )
    //
    if( DEVICE_NO_ANY_ACCESS == Context.Common.SecurityParameters.RequestedAccess && 
        IRP_MJ_CREATE != Data->Iopb->MajorFunction &&
        0x0 == PtrOcDeviceObject->Flags.SpyFileObjects ){

        goto __exit;
    }

    //
    // process the request through a whole devices stack,
    // check the status returned in Context.Common.MiniFilterStatus
    // after processing, each device in the stack checks 
    // whether the request is allowed, the top device
    // also checks whether the request should be logged or shadowed
    //
    OcCrTraverseTopDown( PtrOcDeviceObject,
                         OcCrNodeFunctionMinifilterDriver,
                         (PVOID)&Context );

    //
    // only these codes are processed in the current release
    //
    ASSERT( FLT_PREOP_COMPLETE == Context.Common.MiniFilterStatus ||
            FLT_PREOP_SUCCESS_WITH_CALLBACK == Context.Common.MiniFilterStatus ||
            FLT_PREOP_SUCCESS_NO_CALLBACK == Context.Common.MiniFilterStatus );

    //
    // if one of the following codes has been returned after traversing
    // the PnP tree then the request either must be completed
    // or postponed
    //
    if( FLT_PREOP_COMPLETE == Context.Common.MiniFilterStatus ||
        FLT_PREOP_DISALLOW_FASTIO == Context.Common.MiniFilterStatus ||
        FLT_PREOP_PENDING == Context.Common.MiniFilterStatus ){

            goto __exit;
    }

    //
    // Nobody has cancelled this request, continue processing
    //

    //
    // now check whether the request should be logged or shadowed
    // in case of logging only create request is processed to track 
    // file objects
    // If the operation is direct device open - track it in any case
    //
    if( ( 0x0 == Context.Common.RequestCurrentParameters.DirectDeviceOpenRequest ) && 
        !( 0x1 == Context.Common.SecurityParameters.LogRequest && IRP_MJ_CREATE == Data->Iopb->MajorFunction ) && 
        FALSE == OcIsOperationShadowedAsWriteRequest( &Context.Common.SecurityParameters ) && 
        FALSE == OcIsOperationShadowedAsReadRequest( &Context.Common.SecurityParameters ) ){

        goto __exit;
    }

    if( NULL == Context.FileObject && IRP_MJ_CREATE != Data->Iopb->MajorFunction ){

        //
        // nothing to do without file object if this is not a create request
        //
        goto __exit;
    }

    ASSERT( OcIsOperationLogged( &Context.Common.SecurityParameters ) ||
            OcIsOperationShadowedAsReadRequest( &Context.Common.SecurityParameters ) ||
            OcIsOperationShadowedAsWriteRequest( &Context.Common.SecurityParameters ) );

    //
    // Process the request.
    // This processing is related with the shadowing
    // and logging which require the file object spying
    // and buffers processing.
    //
    switch( Data->Iopb->MajorFunction ){

        case IRP_MJ_CREATE:
            {
                NTSTATUS    RC;
                POC_FILE_OBJECT_CREATE_INFO    RefCreationInfo = NULL;

                RC = OcCrProcessFoCreateRequest( &Context.Common,
                                                 Data,
                                                 PtrOcDeviceObject,
                                                 RequestFromMinifilter? OC_REQUEST_FROM_MINIFILTER: OC_REQUEST_FROM_HOOKED_FSD,
                                                 &RefCreationInfo );
                ASSERT( NT_SUCCESS( RC ) );
                if( !NT_SUCCESS( RC ) ){

                    ASSERT( NULL == RefCreationInfo );

                    Context.Common.MiniFilterStatus = FLT_PREOP_COMPLETE;
                    Data->IoStatus.Status = RC;
                    break;
                }//if( !NT_SUCCESS( RC ) )

                ASSERT( ( OcIsOperationShadowedAsWriteRequest( &Context.Common.SecurityParameters ) ==
                          ( 0x1 == RefCreationInfo->Flags.ShadowWriteRequests ) ) || 
                        ( OcIsOperationShadowedAsWriteRequest( &Context.Common.SecurityParameters ) ==
                          ( 0x1 == RefCreationInfo->Flags.ShadowReadRequests ) ) );

                //
                // the creation info object must be dereferenced in postoperetion callback
                //
                ASSERT( NULL == *CompletionContext );
                *CompletionContext = (PVOID)RefCreationInfo;
                Context.Common.MiniFilterStatus = FLT_PREOP_SUCCESS_WITH_CALLBACK;
            }
            break;

        case IRP_MJ_WRITE:
            {

            POC_OPERATION_OBJECT    OperationObject;
            NTSTATUS                RC;

            ASSERT( OcIsOperationLogged( &Context.Common.SecurityParameters ) || 
                    OcIsOperationShadowedAsWriteRequest( &Context.Common.SecurityParameters ) );

            RC = OcCrCreateOperationObjectForFsd( PtrOcDeviceObject,
                                                  &Context,
                                                  &OperationObject );
            if( !NT_SUCCESS( RC ) )
                break;

            if( OcIsOperationShadowedAsWriteRequest( &OperationObject->SecurityParameters ) ){

                RC = OcCrShadowRequest( OperationObject );
                ASSERT( NT_SUCCESS( RC ) );
                //
                // TO DO - the error processing for the write requests shadowing
                //
            }

            if( !NT_SUCCESS( RC ) ){

                //
                // remove the allocated object
                //
                OcObDereferenceObject( OperationObject );

                break;
            }

            //
            // return the operation object as a completion context,
            // remember that it has been referenced in OcObCreateObject
            //
            ASSERT( NT_SUCCESS( RC ) );
            ASSERT( NULL == *CompletionContext );
            *CompletionContext = (PVOID)OperationObject;
            Context.Common.MiniFilterStatus = FLT_PREOP_SUCCESS_WITH_CALLBACK;

            break;
            }

        case IRP_MJ_READ:
            {

            POC_OPERATION_OBJECT    OperationObject;
            NTSTATUS                RC;

            ASSERT( 0x1 == Context.Common.SecurityParameters.LogRequest || 
                    0x1 == Context.Common.SecurityParameters.ShadowReadRequest );

            RC = OcCrCreateOperationObjectForFsd( PtrOcDeviceObject,
                                                  &Context,
                                                  &OperationObject );
            if( !NT_SUCCESS( RC ) )
                break;

            //
            // shadowing for the read requests is done on completion
            //

            //
            // return the operation object as a completion context,
            // remember that it has been referenced in OcObCreateObject
            //
            ASSERT( NT_SUCCESS( RC ) );
            ASSERT( NULL == *CompletionContext );
            *CompletionContext = (PVOID)OperationObject;
            Context.Common.MiniFilterStatus = FLT_PREOP_SUCCESS_WITH_CALLBACK;

            break;
            }

    }//switch

__exit:

    //
    // free a reference made when FO was found in
    // the database ( see OcHsFindContextByKeyValue )
    //
    if( NULL != Context.FileObject )
        OcObDereferenceObject( Context.FileObject );

    OcObDereferenceObject( PtrOcDeviceObject );

    ASSERT( ( *CompletionContext != NULL )? 
             FLT_PREOP_SUCCESS_WITH_CALLBACK == Context.Common.MiniFilterStatus :
             FLT_PREOP_SUCCESS_WITH_CALLBACK != Context.Common.MiniFilterStatus );

    return Context.Common.MiniFilterStatus;
}