1 //
2 //    Copyright (C) Microsoft.  All rights reserved.
3 //
4 #include "../pnppriv.hpp"
5 
6 #include <initguid.h>
7 #include <wdmguid.h>
8 
9 extern "C" {
10 #if defined(EVENT_TRACING)
11 #include "FxPkgPnpUM.tmh"
12 #endif
13 }
14 
15 NTSTATUS
FilterResourceRequirements(__in IO_RESOURCE_REQUIREMENTS_LIST ** IoList)16 FxPkgPnp::FilterResourceRequirements(
17     __in IO_RESOURCE_REQUIREMENTS_LIST **IoList
18     )
19 {
20     UNREFERENCED_PARAMETER(IoList);
21     ASSERTMSG("Not implemented for UMDF\n", FALSE);
22 
23     return STATUS_NOT_IMPLEMENTED;
24 }
25 
26 _Must_inspect_result_
27 NTSTATUS
AllocateDmaEnablerList(VOID)28 FxPkgPnp::AllocateDmaEnablerList(
29     VOID
30     )
31 {
32     ASSERTMSG("Not implemented for UMDF\n", FALSE);
33 
34     return STATUS_NOT_IMPLEMENTED;
35 }
36 
37 VOID
AddDmaEnabler(__in FxDmaEnabler * Enabler)38 FxPkgPnp::AddDmaEnabler(
39     __in FxDmaEnabler* Enabler
40     )
41 {
42     UNREFERENCED_PARAMETER(Enabler);
43     ASSERTMSG("Not implemented for UMDF\n", FALSE);
44 }
45 
46 VOID
RemoveDmaEnabler(__in FxDmaEnabler * Enabler)47 FxPkgPnp::RemoveDmaEnabler(
48     __in FxDmaEnabler* Enabler
49     )
50 {
51     UNREFERENCED_PARAMETER(Enabler);
52     ASSERTMSG("Not implemented for UMDF\n", FALSE);
53 }
54 
55 NTSTATUS
UpdateWmiInstance(_In_ FxWmiInstanceAction Action,_In_ BOOLEAN ForS0Idle)56 FxPkgPnp::UpdateWmiInstance(
57     _In_ FxWmiInstanceAction Action,
58     _In_ BOOLEAN ForS0Idle
59     )
60 {
61     HRESULT hr;
62     NTSTATUS status;
63     IWudfDeviceStack* devStack;
64     WmiIdleWakeInstanceUpdate updateType;
65 
66     devStack = m_Device->GetDeviceStack();
67 
68     ASSERT(Action != InstanceActionInvalid);
69 
70     if (Action == AddInstance) {
71         updateType = ForS0Idle ? AddS0IdleInstance : AddSxWakeInstance;
72     } else {
73         updateType = ForS0Idle ? RemoveS0IdleInstance : RemoveSxWakeInstance;
74     }
75 
76     hr = devStack->UpdateIdleWakeWmiInstance(updateType);
77     if (S_OK == hr) {
78         status = STATUS_SUCCESS;
79     }
80     else {
81         PUMDF_VERSION_DATA driverVersion = devStack->GetMinDriverVersion();
82         BOOL preserveCompat =
83              devStack->ShouldPreserveIrpCompletionStatusCompatibility();
84 
85         status = CHostFxUtil::NtStatusFromHr(hr,
86                                              driverVersion->MajorNumber,
87                                              driverVersion->MinorNumber,
88                                              preserveCompat);
89     }
90 
91     if (!NT_SUCCESS(status)) {
92         DoTraceLevelMessage(GetDriverGlobals(),
93                             TRACE_LEVEL_ERROR,
94                             TRACINGPNP,
95                             "failed to send ioctl to update %s WMI instance "
96                             "%!STATUS!",
97                             ForS0Idle ? "S0Idle" : "SxWake",
98                             status);
99     }
100 
101     return status;
102 }
103 
104 NTSTATUS
ReadStateFromRegistry(_In_ PCUNICODE_STRING ValueName,_Out_ PULONG Value)105 FxPkgPnp::ReadStateFromRegistry(
106     _In_ PCUNICODE_STRING ValueName,
107     _Out_ PULONG Value
108     )
109 {
110     DWORD err;
111     NTSTATUS status;
112     DWORD data;
113     DWORD dataSize;
114     HKEY pwrPolKey = NULL;
115     IWudfDeviceStack* devStack;
116 
117     ASSERT(NULL != Value);
118     ASSERT(ValueName != NULL &&
119            ValueName->Length != 0 &&
120            ValueName->Buffer != NULL);
121 
122     *Value = 0;
123     devStack = m_Device->GetDeviceStack();
124 
125     err = RegOpenKeyEx(devStack->GetDeviceRegistryKey(),
126                        WUDF_POWER_POLICY_SETTINGS,
127                        0,
128                        KEY_READ,
129                        &pwrPolKey);
130     if (ERROR_SUCCESS != err) {
131         DoTraceLevelMessage(GetDriverGlobals(),
132                             TRACE_LEVEL_ERROR,
133                             TRACINGPNP,
134                             "RegOpenKeyEx returned error %d",
135                             err);
136         goto Clean;
137     }
138 
139     dataSize = sizeof(data);
140     err = RegQueryValueEx(pwrPolKey,
141                           ValueName->Buffer,
142                           NULL,
143                           NULL,
144                           (BYTE*) &data,
145                           &dataSize);
146     if (ERROR_SUCCESS != err) {
147         DoTraceLevelMessage(GetDriverGlobals(),
148                             TRACE_LEVEL_ERROR,
149                             TRACINGPNP,
150                             "failed to read registry, "
151                             "RegQueryValueEx returned error %d",
152                             err);
153         goto Clean;
154     }
155 
156     *Value = data;
157     err = ERROR_SUCCESS;
158 
159 Clean:
160     if (NULL != pwrPolKey) {
161         RegCloseKey(pwrPolKey);
162     }
163 
164     if (ERROR_SUCCESS == err) {
165         status = STATUS_SUCCESS;
166     }
167     else {
168         PUMDF_VERSION_DATA driverVersion = devStack->GetMinDriverVersion();
169         BOOL preserveCompat =
170              devStack->ShouldPreserveIrpCompletionStatusCompatibility();
171 
172         status = CHostFxUtil::NtStatusFromHr(HRESULT_FROM_WIN32(err),
173                                              driverVersion->MajorNumber,
174                                              driverVersion->MinorNumber,
175                                              preserveCompat);
176     }
177 
178     return status;
179 }
180 
181 VOID
WriteStateToRegistry(__in HANDLE RegKey,__in PUNICODE_STRING ValueName,__in ULONG Value)182 FxPkgPnp::WriteStateToRegistry(
183     __in HANDLE RegKey,
184     __in PUNICODE_STRING ValueName,
185     __in ULONG Value
186     )
187 {
188     DWORD err;
189     HRESULT hr;
190     HKEY hKey = NULL;
191     IWudfDeviceStack* devStack;
192     UMINT::WDF_PROPERTY_STORE_ROOT propertyStore;
193 
194     UNREFERENCED_PARAMETER(RegKey);
195 
196     ASSERT(ValueName != NULL &&
197            ValueName->Length != 0 &&
198            ValueName->Buffer != NULL);
199 
200     devStack = m_Device->GetDeviceStack();
201 
202     propertyStore.LengthCb = sizeof(UMINT::WDF_PROPERTY_STORE_ROOT);
203     propertyStore.RootClass = UMINT::WdfPropertyStoreRootClassHardwareKey;
204     propertyStore.Qualifier.HardwareKey.ServiceName = WUDF_POWER_POLICY_SETTINGS;
205 
206     hr = devStack->CreateRegistryEntry(&propertyStore,
207                                        UMINT::WdfPropertyStoreCreateIfMissing,
208                                        KEY_QUERY_VALUE | KEY_SET_VALUE,
209                                        NULL,
210                                        &hKey,
211                                        NULL);
212     if (FAILED(hr)) {
213         goto Clean;
214     }
215 
216     //
217     // Failure to save the user's idle/wake settings is not critical and we
218     // will continue on regardless. Hence we ignore the return value.
219     //
220     err = RegSetValueEx(hKey,
221                         ValueName->Buffer,
222                         0,
223                         REG_DWORD,
224                         (BYTE *) &Value,
225                         sizeof(Value));
226     if (err != ERROR_SUCCESS) {
227         DoTraceLevelMessage(GetDriverGlobals(),
228                             TRACE_LEVEL_ERROR,
229                             TRACINGPNP,
230                             "Failed to set Registry value "
231                             "for S0Idle/SxWake error %d",
232                             err);
233         goto Clean;
234     }
235 
236 Clean:
237     if (NULL != hKey) {
238         RegCloseKey(hKey);
239     }
240 }
241 
242 NTSTATUS
UpdateWmiInstanceForS0Idle(__in FxWmiInstanceAction Action)243 FxPkgPnp::UpdateWmiInstanceForS0Idle(
244     __in FxWmiInstanceAction Action
245     )
246 {
247     NTSTATUS status;
248 
249     //
250     // Send an IOCTL to redirector
251     // to add/remove S0Idle WMI instance.
252     //
253     status = UpdateWmiInstance(Action, TRUE);
254 
255     return status;
256 }
257 
258 VOID
ReadRegistryS0Idle(__in PCUNICODE_STRING ValueName,__out BOOLEAN * Enabled)259 FxPkgPnp::ReadRegistryS0Idle(
260     __in PCUNICODE_STRING ValueName,
261     __out BOOLEAN *Enabled
262     )
263 {
264     NTSTATUS status;
265     ULONG value;
266 
267     status = ReadStateFromRegistry(ValueName, &value);
268 
269     //
270     // Modify value of Enabled only if success
271     //
272     if (NT_SUCCESS(status)) {
273         //
274         // Normalize the ULONG value into a BOOLEAN
275         //
276         *Enabled = (value == FALSE) ? FALSE : TRUE;
277     }
278 }
279 
280 NTSTATUS
UpdateWmiInstanceForSxWake(__in FxWmiInstanceAction Action)281 FxPkgPnp::UpdateWmiInstanceForSxWake(
282     __in FxWmiInstanceAction Action
283     )
284 {
285     NTSTATUS status;
286 
287     //
288     // Send an IOCTL to redirector
289     // to add/remove SxWake WMI instance.
290     //
291     status = UpdateWmiInstance(Action, FALSE);
292 
293     return status;
294 }
295 
296 VOID
ReadRegistrySxWake(__in PCUNICODE_STRING ValueName,__out BOOLEAN * Enabled)297 FxPkgPnp::ReadRegistrySxWake(
298     __in PCUNICODE_STRING ValueName,
299     __out BOOLEAN *Enabled
300     )
301 {
302     NTSTATUS status;
303     ULONG value;
304 
305     status = ReadStateFromRegistry(ValueName, &value);
306 
307     //
308     // Modify value of Enabled only if success
309     //
310     if (NT_SUCCESS(status)) {
311         //
312         // Normalize the ULONG value into a BOOLEAN
313         //
314         *Enabled = (value == FALSE) ? FALSE : TRUE;
315     }
316 }
317 
318 VOID
PnpPassThroughQIWorker(__in MxDeviceObject * Device,__inout FxIrp * Irp,__inout FxIrp * ForwardIrp)319 PnpPassThroughQIWorker(
320     __in    MxDeviceObject* Device,
321     __inout FxIrp* Irp,
322     __inout FxIrp* ForwardIrp
323     )
324 {
325     UNREFERENCED_PARAMETER(Device);
326     UNREFERENCED_PARAMETER(Irp);
327     UNREFERENCED_PARAMETER(ForwardIrp);
328     ASSERTMSG("Not implemented for UMDF\n", FALSE);
329 }
330 
331 
332 VOID
RevokeDmaEnablerResources(__in FxDmaEnabler *)333 FxPkgPnp::RevokeDmaEnablerResources(
334     __in FxDmaEnabler * /* DmaEnabler */
335     )
336 {
337     // Do nothing
338 }
339 
340