1 /*++
2 
3 Copyright (c) Microsoft. All rights reserved.
4 
5 Module Name:
6 
7     FxValidateFunctions.cpp
8 
9 Abstract:
10 
11     Functions which validate external WDF data structures
12 
13 Author:
14 
15 
16 
17 Environment:
18 
19     Both kernel and user mode
20 
21 Revision History:
22 
23 
24 
25 
26 
27 
28 
29 
30 
31 
32 --*/
33 
34 #include "fxobjectpch.hpp"
35 
36 // We use DoTraceMessage
37 extern "C" {
38 #if defined(EVENT_TRACING)
39 #include "FxValidateFunctions.tmh"
40 #endif
41 }
42 
43 _Must_inspect_result_
44 NTSTATUS
45 FxValidateObjectAttributes(
46     __in PFX_DRIVER_GLOBALS FxDriverGlobals,
47     __in PWDF_OBJECT_ATTRIBUTES Attributes,
48     __in ULONG Flags
49     )
50 {
51     if (Attributes == NULL) {
52         if (Flags & FX_VALIDATE_OPTION_ATTRIBUTES_REQUIRED) {
53             DoTraceLevelMessage(
54                 FxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE,
55                 "WDF_OBJECT_ATTRIBUTES required, %!STATUS!",
56                 (ULONG) STATUS_WDF_PARENT_NOT_SPECIFIED);
57 
58             return STATUS_WDF_PARENT_NOT_SPECIFIED;
59         }
60         else {
61             return STATUS_SUCCESS;
62         }
63     }
64 
65     if (Attributes->Size != sizeof(WDF_OBJECT_ATTRIBUTES)) {
66         //
67         // Size is wrong, bail out
68         //
69         DoTraceLevelMessage(FxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGAPIERROR,
70                             "Attributes %p Size incorrect, expected %d, got %d, %!STATUS!",
71                             Attributes, sizeof(WDF_OBJECT_ATTRIBUTES),
72                             Attributes->Size, STATUS_INFO_LENGTH_MISMATCH);
73 
74         return STATUS_INFO_LENGTH_MISMATCH;
75     }
76 
77     if (Attributes->ContextTypeInfo != NULL) {
78 #pragma prefast(suppress:__WARNING_REDUNDANTTEST, "different structs of the same size")
79         if (Attributes->ContextTypeInfo->Size !=
80                                         sizeof(WDF_OBJECT_CONTEXT_TYPE_INFO) &&
81             Attributes->ContextTypeInfo->Size !=
82                                         sizeof(WDF_OBJECT_CONTEXT_TYPE_INFO_V1_0)) {
83             DoTraceLevelMessage(
84                 FxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGAPIERROR,
85                 "Attributes %p ContextTypeInfo %p Size %d incorrect, expected %d, %!STATUS!",
86                 Attributes, Attributes->ContextTypeInfo,
87                 Attributes->ContextTypeInfo->Size,
88                 sizeof(WDF_OBJECT_CONTEXT_TYPE_INFO), STATUS_INFO_LENGTH_MISMATCH);
89 
90             return STATUS_INFO_LENGTH_MISMATCH;
91         }
92 
93         //
94         // A ContextName != NULL and a ContextSize of 0 is allowed
95         //
96         if (Attributes->ContextTypeInfo->ContextSize > 0 &&
97             Attributes->ContextTypeInfo->ContextName == NULL) {
98 
99             DoTraceLevelMessage(
100                 FxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGAPIERROR,
101                 "Attributes %p ContextTypeInfo %p ContextSize %I64d is not zero, "
102                 "but ContextName is NULL, %!STATUS!",
103                 Attributes, Attributes->ContextTypeInfo,
104                 Attributes->ContextTypeInfo->ContextSize,
105                 STATUS_WDF_OBJECT_ATTRIBUTES_INVALID);
106 
107             return STATUS_WDF_OBJECT_ATTRIBUTES_INVALID;
108         }
109     }
110 
111     if (Attributes->ContextSizeOverride > 0) {
112         if (Attributes->ContextTypeInfo == NULL) {
113             //
114             // Can't specify additional size without a type
115             //
116             DoTraceLevelMessage(
117                 FxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGAPIERROR,
118                 "Attributes %p ContextSizeOverride of %I64d specified, but no type "
119                 "information, %!STATUS!",
120                 Attributes, Attributes->ContextSizeOverride,
121                 STATUS_WDF_OBJECT_ATTRIBUTES_INVALID);
122 
123             return STATUS_WDF_OBJECT_ATTRIBUTES_INVALID;
124         }
125         else if (Attributes->ContextSizeOverride <
126                                     Attributes->ContextTypeInfo->ContextSize) {
127             DoTraceLevelMessage(
128                 FxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGAPIERROR,
129                 "Attributes %p ContextSizeOverride %I64d < "
130                 "ContextTypeInfo->ContextSize %I64d, %!STATUS!",
131                 Attributes, Attributes->ContextSizeOverride,
132                 Attributes->ContextTypeInfo->ContextSize,
133                 STATUS_WDF_OBJECT_ATTRIBUTES_INVALID);
134 
135             return STATUS_WDF_OBJECT_ATTRIBUTES_INVALID;
136         }
137     }
138 
139     if (Flags & FX_VALIDATE_OPTION_PARENT_NOT_ALLOWED) {
140         if (Attributes->ParentObject != NULL) {
141             DoTraceLevelMessage(
142                 FxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGAPIERROR,
143                 "Attributes %p does not allow a parent object to be set, set to "
144                 "%p, %!STATUS!", Attributes, Attributes->ParentObject,
145                 STATUS_WDF_PARENT_ASSIGNMENT_NOT_ALLOWED);
146 
147             return STATUS_WDF_PARENT_ASSIGNMENT_NOT_ALLOWED;
148         }
149     }
150     else if ((Flags & FX_VALIDATE_OPTION_PARENT_REQUIRED_FLAG) &&
151              Attributes->ParentObject == NULL) {
152         DoTraceLevelMessage(
153             FxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE,
154             "ParentObject required in WDF_OBJECT_ATTRIBUTES %p, %!STATUS!",
155             Attributes, STATUS_WDF_PARENT_NOT_SPECIFIED);
156 
157         return STATUS_WDF_PARENT_NOT_SPECIFIED;
158     }
159 
160     // Enum range checks
161     if ((Attributes->ExecutionLevel == WdfExecutionLevelInvalid) ||
162         (Attributes->ExecutionLevel > WdfExecutionLevelDispatch)) {
163         DoTraceLevelMessage(
164             FxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGAPIERROR,
165             "Attributes %p execution level set to %d, out of range, %!STATUS!",
166             Attributes, Attributes->ExecutionLevel,
167             STATUS_WDF_OBJECT_ATTRIBUTES_INVALID);
168         return STATUS_WDF_OBJECT_ATTRIBUTES_INVALID;
169     }
170 
171     if ((Attributes->SynchronizationScope == WdfSynchronizationScopeInvalid) ||
172         (Attributes->SynchronizationScope > WdfSynchronizationScopeNone)) {
173         DoTraceLevelMessage(
174             FxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGAPIERROR,
175             "Attributes %p synchronization scope set to %d, out of range, %!STATUS!",
176             Attributes, Attributes->SynchronizationScope,
177             STATUS_WDF_OBJECT_ATTRIBUTES_INVALID);
178         return STATUS_WDF_OBJECT_ATTRIBUTES_INVALID;
179     }
180 
181     if ((Flags & FX_VALIDATE_OPTION_SYNCHRONIZATION_SCOPE_ALLOWED) == 0) {
182 
183         //
184         // If synchronization is not allowed for this object,
185         // check the requested level to ensure none was specified.
186         //
187         if ((Attributes->SynchronizationScope != WdfSynchronizationScopeInheritFromParent) &&
188             (Attributes->SynchronizationScope != WdfSynchronizationScopeNone)) {
189 
190             DoTraceLevelMessage(
191                 FxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGAPIERROR,
192                 "Attributes %p does not allow synchronization scope too be set, "
193                 "but was set to %!WDF_SYNCHRONIZATION_SCOPE!, %!STATUS!",
194                 Attributes, Attributes->SynchronizationScope,
195                 STATUS_WDF_SYNCHRONIZATION_SCOPE_INVALID);
196 
197             return STATUS_WDF_SYNCHRONIZATION_SCOPE_INVALID;
198         }
199     }
200 
201     if ((Flags & FX_VALIDATE_OPTION_EXECUTION_LEVEL_ALLOWED) == 0) {
202 
203         //
204         // If execution level restrictions are not allowed for this object,
205         // check the requested level to ensure none was specified.
206         //
207         if (Attributes->ExecutionLevel != WdfExecutionLevelInheritFromParent) {
208             DoTraceLevelMessage(
209                 FxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGAPIERROR,
210                 "Attributes %p does not allow execution level to be set, but was"
211                 " set to %!WDF_EXECUTION_LEVEL!, %!STATUS!",
212                 Attributes, Attributes->ExecutionLevel,
213                 STATUS_WDF_EXECUTION_LEVEL_INVALID);
214 
215             return STATUS_WDF_EXECUTION_LEVEL_INVALID;
216         }
217     }
218 
219     return STATUS_SUCCESS;
220 }
221