static NTSTATUS UcaSetContext(_In_ PFLT_INSTANCE Instance, _In_ PVOID Target, _In_ FLT_CONTEXT_TYPE ContextType, _In_ PFLT_CONTEXT NewContext, _Outptr_opt_result_maybenull_ PFLT_CONTEXT *OldContext) { NTSTATUS Status; PAGED_CODE(); switch (ContextType) { case FLT_STREAM_CONTEXT: Status = FltSetStreamContext(Instance, (PFILE_OBJECT)Target, FLT_SET_CONTEXT_KEEP_IF_EXISTS, NewContext, OldContext); break; case FLT_FILE_CONTEXT: Status = FltSetFileContext(Instance, (PFILE_OBJECT)Target, FLT_SET_CONTEXT_KEEP_IF_EXISTS, NewContext, OldContext); break; case FLT_TRANSACTION_CONTEXT: Status = FltSetTransactionContext(Instance, (PKTRANSACTION)Target, FLT_SET_CONTEXT_KEEP_IF_EXISTS, NewContext, OldContext); break; case FLT_INSTANCE_CONTEXT: Status = FltSetInstanceContext(Instance, FLT_SET_CONTEXT_KEEP_IF_EXISTS, NewContext, OldContext); break; default: Status = STATUS_INVALID_PARAMETER; break; } return Status; }
/*++ Routine Description: 这个函数查找目标流的流上下文。 This routine finds the stream context for the target stream. Optionally, if the context does not exist this routing creates a new one and attaches the context to the stream. Arguments: Cbd - Supplies a pointer to the callbackData which declares the requested operation. CreateIfNotFound - Supplies if the stream must be created if missing StreamContext - Returns the stream context ContextCreated - Returns if a new context was created Return Value: Status --*/ NTSTATUS CtxFindOrCreateStreamContext ( __in PFLT_CALLBACK_DATA Cbd, __in BOOLEAN CreateIfNotFound, __deref_out PCTX_STREAM_CONTEXT *StreamContext, __out_opt PBOOLEAN ContextCreated ) { NTSTATUS status; PCTX_STREAM_CONTEXT streamContext; PCTX_STREAM_CONTEXT oldStreamContext; PAGED_CODE(); *StreamContext = NULL; if (ContextCreated != NULL) *ContextCreated = FALSE; // // First try to get the stream context. // DebugTrace( DEBUG_TRACE_STREAM_CONTEXT_OPERATIONS, ("[Ctx]: Trying to get stream context (FileObject = %p, Instance = %p)\n", Cbd->Iopb->TargetFileObject, Cbd->Iopb->TargetInstance) ); status = FltGetStreamContext( Cbd->Iopb->TargetInstance, Cbd->Iopb->TargetFileObject, &streamContext ); // // If the call failed because the context does not exist // and the user wants to creat a new one, the create a // new context // if (!NT_SUCCESS( status ) && (status == STATUS_NOT_FOUND) && CreateIfNotFound) { // // Create a stream context // DebugTrace( DEBUG_TRACE_STREAM_CONTEXT_OPERATIONS, ("[Ctx]: Creating stream context (FileObject = %p, Instance = %p)\n", Cbd->Iopb->TargetFileObject, Cbd->Iopb->TargetInstance) ); status = CtxCreateStreamContext( &streamContext ); if (!NT_SUCCESS( status )) { DebugTrace( DEBUG_TRACE_ERROR | DEBUG_TRACE_STREAM_CONTEXT_OPERATIONS, ("[Ctx]: Failed to create stream context with status 0x%x. (FileObject = %p, Instance = %p)\n", status, Cbd->Iopb->TargetFileObject, Cbd->Iopb->TargetInstance) ); return status; } // // Set the new context we just allocated on the file object // DebugTrace( DEBUG_TRACE_STREAM_CONTEXT_OPERATIONS, ("[Ctx]: Setting stream context %p (FileObject = %p, Instance = %p)\n", streamContext, Cbd->Iopb->TargetFileObject, Cbd->Iopb->TargetInstance) ); status = FltSetStreamContext( Cbd->Iopb->TargetInstance, Cbd->Iopb->TargetFileObject, FLT_SET_CONTEXT_KEEP_IF_EXISTS, streamContext, &oldStreamContext ); if (!NT_SUCCESS( status )) { DebugTrace( DEBUG_TRACE_STREAM_CONTEXT_OPERATIONS, ("[Ctx]: Failed to set stream context with status 0x%x. (FileObject = %p, Instance = %p)\n", status, Cbd->Iopb->TargetFileObject, Cbd->Iopb->TargetInstance) ); // // We release the context here because FltSetStreamContext failed // // If FltSetStreamContext succeeded then the context will be returned // to the caller. The caller will use the context and then release it // when he is done with the context. // DebugTrace( DEBUG_TRACE_STREAM_CONTEXT_OPERATIONS, ("[Ctx]: Releasing stream context %p (FileObject = %p, Instance = %p)\n", streamContext, Cbd->Iopb->TargetFileObject, Cbd->Iopb->TargetInstance) ); FltReleaseContext( streamContext ); if (status != STATUS_FLT_CONTEXT_ALREADY_DEFINED) { // // FltSetStreamContext failed for a reason other than the context already // existing on the stream. So the object now does not have any context set // on it. So we return failure to the caller. // DebugTrace( DEBUG_TRACE_ERROR | DEBUG_TRACE_STREAM_CONTEXT_OPERATIONS, ("[Ctx]: Failed to set stream context with status 0x%x != STATUS_FLT_CONTEXT_ALREADY_DEFINED. (FileObject = %p, Instance = %p)\n", status, Cbd->Iopb->TargetFileObject, Cbd->Iopb->TargetInstance) ); return status; } // // Race condition. Someone has set a context after we queried it. // Use the already set context instead // DebugTrace( DEBUG_TRACE_STREAM_CONTEXT_OPERATIONS, ("[Ctx]: Stream context already defined. Retaining old stream context %p (FileObject = %p, Instance = %p)\n", oldStreamContext, Cbd->Iopb->TargetFileObject, Cbd->Iopb->TargetInstance) ); // // Return the existing context. Note that the new context that we allocated has already been // realeased above. // streamContext = oldStreamContext; status = STATUS_SUCCESS; } else { if (ContextCreated != NULL) *ContextCreated = TRUE; } } *StreamContext = streamContext; return status; }
NTSTATUS CtxFindOrCreateStreamHandleContext ( __in PFLT_CALLBACK_DATA Cbd, __in BOOLEAN CreateIfNotFound, __deref_out PSTREAMHANDLE_CONTEXT *StreamHandleContext, __out_opt PBOOLEAN ContextCreated ) /*++ Routine Description: This routine finds the stream context for the target stream. Optionally, if the context does not exist this routing creates a new one and attaches the context to the stream. Arguments: Cbd - Supplies a pointer to the callbackData which declares the requested operation. CreateIfNotFound - Supplies if the stream must be created if missing StreamContext - Returns the stream context ContextCreated - Returns if a new context was created Return Value: Status --*/ { NTSTATUS status; PSTREAMHANDLE_CONTEXT streamHandleContext; PSTREAMHANDLE_CONTEXT oldStreamHandleContext; PAGED_CODE(); *StreamHandleContext = NULL; if (ContextCreated != NULL) *ContextCreated = FALSE; // // First try to get the stream context. // status = FltGetStreamHandleContext( Cbd->Iopb->TargetInstance, Cbd->Iopb->TargetFileObject, &streamHandleContext ); // // If the call failed because the context does not exist // and the user wants to creat a new one, the create a // new context // if (!NT_SUCCESS( status ) && (status == STATUS_NOT_FOUND) && CreateIfNotFound) { // // Create a stream context // status = CtxCreateStreamHandleContext( &streamHandleContext ); if (!NT_SUCCESS( status )) { return status; } // // Set the new context we just allocated on the file object // status = FltSetStreamContext( Cbd->Iopb->TargetInstance, Cbd->Iopb->TargetFileObject, FLT_SET_CONTEXT_KEEP_IF_EXISTS, streamHandleContext, &oldStreamHandleContext ); if (!NT_SUCCESS( status )) { // // We release the context here because FltSetStreamContext failed // // If FltSetStreamContext succeeded then the context will be returned // to the caller. The caller will use the context and then release it // when he is done with the context. // FltReleaseContext( streamHandleContext ); if (status != STATUS_FLT_CONTEXT_ALREADY_DEFINED) { // // FltSetStreamContext failed for a reason other than the context already // existing on the stream. So the object now does not have any context set // on it. So we return failure to the caller. // return status; } // // Race condition. Someone has set a context after we queried it. // Use the already set context instead // // // Return the existing context. Note that the new context that we allocated has already been // realeased above. // streamHandleContext = oldStreamHandleContext; status = STATUS_SUCCESS; } else { if (ContextCreated != NULL) *ContextCreated = TRUE; } } *StreamHandleContext = streamHandleContext; return status; }
NTSTATUS Ctx_FindOrCreateStreamContext ( __in PFLT_CALLBACK_DATA Data, __in PFLT_RELATED_OBJECTS FltObjects, __in BOOLEAN CreateIfNotFound, __deref_out PSTREAM_CONTEXT *StreamContext, __out_opt PBOOLEAN ContextCreated ) /*++ Routine Description: This routine finds the stream context for the target stream. Optionally, if the context does not exist this routing creates a new one and attaches the context to the stream. Arguments: Cbd - Supplies a pointer to the callbackData which declares the requested operation. CreateIfNotFound - Supplies if the stream must be created if missing StreamContext - Returns the stream context ContextCreated - Returns if a new context was created Return Value: Status --*/ { NTSTATUS status; PSTREAM_CONTEXT streamContext; PSTREAM_CONTEXT oldStreamContext; PAGED_CODE(); *StreamContext = NULL; if (ContextCreated != NULL) *ContextCreated = FALSE; // First try to get the stream context. status = FltGetStreamContext( Data->Iopb->TargetInstance, Data->Iopb->TargetFileObject,&streamContext ); if (!NT_SUCCESS( status ) && (status == STATUS_NOT_FOUND) && CreateIfNotFound) { status = iCtx_CreateStreamContext(FltObjects, &streamContext ); if (!NT_SUCCESS( status )) return status; status = FltSetStreamContext( Data->Iopb->TargetInstance, Data->Iopb->TargetFileObject, FLT_SET_CONTEXT_KEEP_IF_EXISTS, streamContext, &oldStreamContext ); if (!NT_SUCCESS( status )) { FltReleaseContext(streamContext); if (status != STATUS_FLT_CONTEXT_ALREADY_DEFINED) { // FltSetStreamContext failed for a reason other than the context already // existing on the stream. So the object now does not have any context set // on it. So we return failure to the caller. return status; } streamContext = oldStreamContext; status = STATUS_SUCCESS; } else { if (ContextCreated != NULL) *ContextCreated = TRUE; } } *StreamContext = streamContext; return status; }