/*++ Copyright (c) Microsoft. All rights reserved. Module Name: FxValidateFunctions.cpp Abstract: Functions which validate external WDF data structures Author: Environment: Both kernel and user mode Revision History: --*/ #include "fxobjectpch.hpp" // We use DoTraceMessage extern "C" { #if defined(EVENT_TRACING) #include "FxValidateFunctions.tmh" #endif } _Must_inspect_result_ NTSTATUS FxValidateObjectAttributes( __in PFX_DRIVER_GLOBALS FxDriverGlobals, __in PWDF_OBJECT_ATTRIBUTES Attributes, __in ULONG Flags ) { if (Attributes == NULL) { if (Flags & FX_VALIDATE_OPTION_ATTRIBUTES_REQUIRED) { DoTraceLevelMessage( FxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE, "WDF_OBJECT_ATTRIBUTES required, %!STATUS!", (ULONG) STATUS_WDF_PARENT_NOT_SPECIFIED); return STATUS_WDF_PARENT_NOT_SPECIFIED; } else { return STATUS_SUCCESS; } } if (Attributes->Size != sizeof(WDF_OBJECT_ATTRIBUTES)) { // // Size is wrong, bail out // DoTraceLevelMessage(FxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGAPIERROR, "Attributes %p Size incorrect, expected %d, got %d, %!STATUS!", Attributes, sizeof(WDF_OBJECT_ATTRIBUTES), Attributes->Size, STATUS_INFO_LENGTH_MISMATCH); return STATUS_INFO_LENGTH_MISMATCH; } if (Attributes->ContextTypeInfo != NULL) { #pragma prefast(suppress:__WARNING_REDUNDANTTEST, "different structs of the same size") if (Attributes->ContextTypeInfo->Size != sizeof(WDF_OBJECT_CONTEXT_TYPE_INFO) && Attributes->ContextTypeInfo->Size != sizeof(WDF_OBJECT_CONTEXT_TYPE_INFO_V1_0)) { DoTraceLevelMessage( FxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGAPIERROR, "Attributes %p ContextTypeInfo %p Size %d incorrect, expected %d, %!STATUS!", Attributes, Attributes->ContextTypeInfo, Attributes->ContextTypeInfo->Size, sizeof(WDF_OBJECT_CONTEXT_TYPE_INFO), STATUS_INFO_LENGTH_MISMATCH); return STATUS_INFO_LENGTH_MISMATCH; } // // A ContextName != NULL and a ContextSize of 0 is allowed // if (Attributes->ContextTypeInfo->ContextSize > 0 && Attributes->ContextTypeInfo->ContextName == NULL) { DoTraceLevelMessage( FxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGAPIERROR, "Attributes %p ContextTypeInfo %p ContextSize %I64d is not zero, " "but ContextName is NULL, %!STATUS!", Attributes, Attributes->ContextTypeInfo, Attributes->ContextTypeInfo->ContextSize, STATUS_WDF_OBJECT_ATTRIBUTES_INVALID); return STATUS_WDF_OBJECT_ATTRIBUTES_INVALID; } } if (Attributes->ContextSizeOverride > 0) { if (Attributes->ContextTypeInfo == NULL) { // // Can't specify additional size without a type // DoTraceLevelMessage( FxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGAPIERROR, "Attributes %p ContextSizeOverride of %I64d specified, but no type " "information, %!STATUS!", Attributes, Attributes->ContextSizeOverride, STATUS_WDF_OBJECT_ATTRIBUTES_INVALID); return STATUS_WDF_OBJECT_ATTRIBUTES_INVALID; } else if (Attributes->ContextSizeOverride < Attributes->ContextTypeInfo->ContextSize) { DoTraceLevelMessage( FxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGAPIERROR, "Attributes %p ContextSizeOverride %I64d < " "ContextTypeInfo->ContextSize %I64d, %!STATUS!", Attributes, Attributes->ContextSizeOverride, Attributes->ContextTypeInfo->ContextSize, STATUS_WDF_OBJECT_ATTRIBUTES_INVALID); return STATUS_WDF_OBJECT_ATTRIBUTES_INVALID; } } if (Flags & FX_VALIDATE_OPTION_PARENT_NOT_ALLOWED) { if (Attributes->ParentObject != NULL) { DoTraceLevelMessage( FxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGAPIERROR, "Attributes %p does not allow a parent object to be set, set to " "%p, %!STATUS!", Attributes, Attributes->ParentObject, STATUS_WDF_PARENT_ASSIGNMENT_NOT_ALLOWED); return STATUS_WDF_PARENT_ASSIGNMENT_NOT_ALLOWED; } } else if ((Flags & FX_VALIDATE_OPTION_PARENT_REQUIRED_FLAG) && Attributes->ParentObject == NULL) { DoTraceLevelMessage( FxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE, "ParentObject required in WDF_OBJECT_ATTRIBUTES %p, %!STATUS!", Attributes, STATUS_WDF_PARENT_NOT_SPECIFIED); return STATUS_WDF_PARENT_NOT_SPECIFIED; } // Enum range checks if ((Attributes->ExecutionLevel == WdfExecutionLevelInvalid) || (Attributes->ExecutionLevel > WdfExecutionLevelDispatch)) { DoTraceLevelMessage( FxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGAPIERROR, "Attributes %p execution level set to %d, out of range, %!STATUS!", Attributes, Attributes->ExecutionLevel, STATUS_WDF_OBJECT_ATTRIBUTES_INVALID); return STATUS_WDF_OBJECT_ATTRIBUTES_INVALID; } if ((Attributes->SynchronizationScope == WdfSynchronizationScopeInvalid) || (Attributes->SynchronizationScope > WdfSynchronizationScopeNone)) { DoTraceLevelMessage( FxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGAPIERROR, "Attributes %p synchronization scope set to %d, out of range, %!STATUS!", Attributes, Attributes->SynchronizationScope, STATUS_WDF_OBJECT_ATTRIBUTES_INVALID); return STATUS_WDF_OBJECT_ATTRIBUTES_INVALID; } if ((Flags & FX_VALIDATE_OPTION_SYNCHRONIZATION_SCOPE_ALLOWED) == 0) { // // If synchronization is not allowed for this object, // check the requested level to ensure none was specified. // if ((Attributes->SynchronizationScope != WdfSynchronizationScopeInheritFromParent) && (Attributes->SynchronizationScope != WdfSynchronizationScopeNone)) { DoTraceLevelMessage( FxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGAPIERROR, "Attributes %p does not allow synchronization scope too be set, " "but was set to %!WDF_SYNCHRONIZATION_SCOPE!, %!STATUS!", Attributes, Attributes->SynchronizationScope, STATUS_WDF_SYNCHRONIZATION_SCOPE_INVALID); return STATUS_WDF_SYNCHRONIZATION_SCOPE_INVALID; } } if ((Flags & FX_VALIDATE_OPTION_EXECUTION_LEVEL_ALLOWED) == 0) { // // If execution level restrictions are not allowed for this object, // check the requested level to ensure none was specified. // if (Attributes->ExecutionLevel != WdfExecutionLevelInheritFromParent) { DoTraceLevelMessage( FxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGAPIERROR, "Attributes %p does not allow execution level to be set, but was" " set to %!WDF_EXECUTION_LEVEL!, %!STATUS!", Attributes, Attributes->ExecutionLevel, STATUS_WDF_EXECUTION_LEVEL_INVALID); return STATUS_WDF_EXECUTION_LEVEL_INVALID; } } return STATUS_SUCCESS; }