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