1 /*++
2 
3 Copyright (c) Microsoft Corporation
4 
5 Module Name:
6 
7     FxDeviceInit.cpp
8 
9 Abstract:
10     Internals for WDFDEVICE_INIT
11 
12 Author:
13 
14 
15 
16 Environment:
17 
18     Both kernel and user mode
19 
20 Revision History:
21 
22 --*/
23 
24 #include "coreprivshared.hpp"
25 
26 extern "C" {
27 // #include "FxDeviceInit.tmh"
28 }
29 
WDFDEVICE_INIT(__in FxDriver * Driver)30 WDFDEVICE_INIT::WDFDEVICE_INIT(
31     __in FxDriver* Driver
32     ) :
33     Driver(Driver)
34 {
35     DriverGlobals = Driver->GetDriverGlobals();
36 
37     ReadWriteIoType = WdfDeviceIoBuffered;
38     PowerPageable = TRUE;
39     Inrush = FALSE;
40     DeviceType = FILE_DEVICE_UNKNOWN;
41     Characteristics = FILE_DEVICE_SECURE_OPEN;
42 
43     RtlZeroMemory(&FileObject, sizeof(FileObject));
44     FileObject.AutoForwardCleanupClose = WdfUseDefault;
45 
46     DeviceName = NULL;
47     CreatedDevice = NULL;
48 
49     CreatedOnStack = FALSE;
50     Exclusive = FALSE;
51 
52     RequiresSelfIoTarget = FALSE;
53 
54     RemoveLockOptionFlags = 0;
55 
56     RtlZeroMemory(&PnpPower.PnpPowerEventCallbacks, sizeof(PnpPower.PnpPowerEventCallbacks));
57     RtlZeroMemory(&PnpPower.PolicyEventCallbacks, sizeof(PnpPower.PolicyEventCallbacks));
58     PnpPower.PnpStateCallbacks = NULL;
59     PnpPower.PowerStateCallbacks = NULL;
60     PnpPower.PowerPolicyStateCallbacks = NULL;
61 
62     PnpPower.PowerPolicyOwner = WdfUseDefault;
63 
64     InitType = FxDeviceInitTypeFdo;
65 
66     RtlZeroMemory(&Fdo.EventCallbacks, sizeof(Fdo.EventCallbacks));
67     RtlZeroMemory(&Fdo.ListConfig, sizeof(Fdo.ListConfig));
68     RtlZeroMemory(&Fdo.ListConfigAttributes, sizeof(Fdo.ListConfigAttributes));
69     Fdo.Filter = FALSE;
70 
71     RtlZeroMemory(&Pdo.EventCallbacks, sizeof(Pdo.EventCallbacks));
72     Pdo.Raw = FALSE;
73     Pdo.Static = FALSE;
74     Pdo.DeviceID = NULL;
75     Pdo.InstanceID = NULL;
76     Pdo.ContainerID = NULL;
77     Pdo.DefaultLocale = 0x0;
78     Pdo.DescriptionEntry = NULL;
79     Pdo.ForwardRequestToParent = FALSE;
80 
81     RtlZeroMemory(&Security, sizeof(Security));
82 
83     RtlZeroMemory(&RequestAttributes, sizeof(RequestAttributes));
84 
85     PreprocessInfo = NULL;
86 
87     IoInCallerContextCallback = NULL;
88 
89     InitializeListHead(&CxDeviceInitListHead);
90 
91     ReleaseHardwareOrderOnFailure = WdfReleaseHardwareOrderOnFailureEarly;
92 
93 #if (FX_CORE_MODE == FX_CORE_USER_MODE)
94 
95     DeviceControlIoType = WdfDeviceIoBuffered;
96     DirectTransferThreshold = 0;
97 
98     DevStack = NULL;
99 
100     KernelDeviceName = NULL;
101 
102     PdoKey = NULL;
103 
104     DevInstanceID = NULL;
105 
106     DriverID = 0;
107 #endif
108 }
109 
~WDFDEVICE_INIT()110 WDFDEVICE_INIT::~WDFDEVICE_INIT()
111 {
112     PLIST_ENTRY next;
113 
114     if (PnpPower.PnpStateCallbacks != NULL) {
115         delete PnpPower.PnpStateCallbacks;
116     }
117 
118     if (PnpPower.PowerStateCallbacks != NULL) {
119         delete PnpPower.PowerStateCallbacks;
120     }
121 
122     if (PnpPower.PowerPolicyStateCallbacks != NULL) {
123         delete PnpPower.PowerPolicyStateCallbacks;
124     }
125 
126     if (DeviceName != NULL) {
127         DeviceName->DeleteObject();
128     }
129     if (Pdo.DeviceID != NULL) {
130         Pdo.DeviceID->DeleteObject();
131     }
132     if (Pdo.InstanceID != NULL) {
133         Pdo.InstanceID->DeleteObject();
134     }
135     if (Pdo.ContainerID != NULL) {
136         Pdo.ContainerID->DeleteObject();
137     }
138 
139     FxDeviceText::_CleanupList(&Pdo.DeviceText);
140 
141     if (Security.Sddl != NULL) {
142         Security.Sddl->DeleteObject();
143     }
144     if (PreprocessInfo != NULL) {
145         delete PreprocessInfo;
146     }
147 
148     while(!IsListEmpty(&CxDeviceInitListHead)) {
149         next = RemoveHeadList(&CxDeviceInitListHead);
150         PWDFCXDEVICE_INIT cxInit;
151         cxInit = CONTAINING_RECORD(next, WDFCXDEVICE_INIT, ListEntry);
152         InitializeListHead(next);
153         delete cxInit;
154     }
155 
156 #if (FX_CORE_MODE == FX_CORE_USER_MODE)
157     delete [] KernelDeviceName;
158     delete [] ConfigRegistryPath;
159     delete [] DevInstanceID;
160 
161     if (PdoKey != NULL) {
162          RegCloseKey(PdoKey);
163          PdoKey = NULL;
164     }
165 #endif
166 
167 }
168 
169 _Must_inspect_result_
170 NTSTATUS
AssignName(__in PFX_DRIVER_GLOBALS FxDriverGlobals,__in const UNICODE_STRING * Name)171 WDFDEVICE_INIT::AssignName(
172     __in PFX_DRIVER_GLOBALS FxDriverGlobals,
173     __in const UNICODE_STRING* Name
174     )
175 {
176     if (DeviceName == NULL) {
177         DeviceName = new(FxDriverGlobals, WDF_NO_OBJECT_ATTRIBUTES)
178             FxString(FxDriverGlobals);
179 
180         if (DeviceName == NULL) {
181             NTSTATUS status;
182 
183             status = STATUS_INSUFFICIENT_RESOURCES;
184 
185             DoTraceLevelMessage(FxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE,
186                                 "DeviceName is NULL, %!STATUS!", status);
187 
188             return status;
189         }
190 
191         //
192         // Clear out the autogenerate flag since we have a specific name
193         //
194         Characteristics &= ~FILE_AUTOGENERATED_DEVICE_NAME;
195     }
196 
197     return DeviceName->Assign(Name);
198 }
199 
200 _Must_inspect_result_
201 PWDFDEVICE_INIT
_AllocateControlDeviceInit(__in FxDriver * Driver,__in const UNICODE_STRING * SDDLString)202 WDFDEVICE_INIT::_AllocateControlDeviceInit(
203     __in FxDriver* Driver,
204     __in const UNICODE_STRING* SDDLString
205     )
206 {
207     PFX_DRIVER_GLOBALS pFxDriverGlobals;
208     PWDFDEVICE_INIT pInit;
209     NTSTATUS status;
210 
211     pFxDriverGlobals = Driver->GetDriverGlobals();
212 
213     pInit = new(pFxDriverGlobals) WDFDEVICE_INIT(Driver);
214 
215     if (pInit == NULL) {
216         DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE,
217                             "WDFDRIVER 0x%p  couldn't allocate WDFDEVICE_INIT",
218                             Driver);
219         return NULL;
220     }
221 
222     pInit->InitType = FxDeviceInitTypeControlDevice;
223 
224     //
225     // Since we require and SDLL string, initialize to autogenerated  device
226     // name so the driver doesn't have to worry about creating a name if they
227     // don't want it (useful if creating a DO for WMI tracing for instance).
228     //
229     pInit->Characteristics |= FILE_AUTOGENERATED_DEVICE_NAME;
230 
231     pInit->Security.Sddl = new(pFxDriverGlobals, WDF_NO_OBJECT_ATTRIBUTES)
232         FxString(pFxDriverGlobals);
233 
234     if (pInit->Security.Sddl != NULL) {
235         status = pInit->Security.Sddl->Assign(SDDLString);
236     }
237     else {
238         status = STATUS_INSUFFICIENT_RESOURCES;
239         DoTraceLevelMessage(
240             pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE,
241             "WDFDRIVER 0x%p couldn't create Security String object %!STATUS!",
242             Driver, status);
243     }
244 
245     if (!NT_SUCCESS(status)) {
246         delete pInit;
247         pInit = NULL;
248     }
249 
250     return pInit;
251 }
252 
253 BOOLEAN
ShouldCreateSecure(VOID)254 WDFDEVICE_INIT::ShouldCreateSecure(
255     VOID
256     )
257 {
258     //
259     // Driver explicitly set a class or SDDL, we have to create a secure
260     // device.  This will be true for all control devices (SDDL required)
261     // and raw PDOs (class required), could be true for FDOs or filters as
262     // well.
263     //
264     if (Security.DeviceClassSet || Security.Sddl != NULL) {
265         return TRUE;
266     }
267 
268     //
269     // See if there is a name for the device
270     //
271     if (HasName()) {
272         if (IsPdoInit()) {
273 
274 
275 
276 
277 
278 
279 
280 
281 
282 
283 
284 
285 
286             ASSERT(Pdo.Raw == FALSE);
287 
288             DoTraceLevelMessage(
289                 DriverGlobals,
290                 TRACE_LEVEL_WARNING,
291                 TRACINGDEVICE,
292                 "WDFDRIVER 0x%p asked for a named device object, but the PDO "
293                 "will be created without a name because an SDDL string has not "
294                 "been specified for the PDO.",
295                 Driver
296                 );
297             return FALSE;
298         }
299         else {
300             //
301             // We are creating a named FDO or filter
302             //
303             ASSERT(IsFdoInit());
304             return TRUE;
305         }
306     }
307 
308     //
309     // No name involved (FDO or filter)
310     //
311     ASSERT(IsFdoInit());
312 
313     return FALSE;
314 }
315 
316 VOID
AddCxDeviceInit(__in PWDFCXDEVICE_INIT CxDeviceInit)317 WDFDEVICE_INIT::AddCxDeviceInit(
318     __in PWDFCXDEVICE_INIT CxDeviceInit
319     )
320 {
321     InsertHeadList(&CxDeviceInitListHead, &CxDeviceInit->ListEntry);
322 }
323 
324