1 /*++
2 
3 Copyright (c) Microsoft Corporation
4 
5 Module Name:
6 
7     FxDeviceUm.cpp
8 
9 Abstract:
10 
11     This is the KM specific class implementation for the base Device class.
12 
13 Author:
14 
15 
16 
17 Environment:
18 
19     User mode only
20 
21 Revision History:
22 
23 --*/
24 
25 #include "coreprivshared.hpp"
26 
27 extern "C" {
28 #include "FxDeviceUm.tmh"
29 }
30 
31 VOID
DispatchUm(_In_ MdDeviceObject DeviceObject,_In_ MdIrp Irp,_In_opt_ IUnknown * Context)32 FxDevice::DispatchUm(
33     _In_ MdDeviceObject DeviceObject,
34     _In_ MdIrp Irp,
35     _In_opt_ IUnknown* Context
36     )
37 {
38     UNREFERENCED_PARAMETER(Context);
39 
40 
41 
42 
43 
44     (void) Dispatch(DeviceObject, Irp);
45 }
46 
47 VOID
DispatchWithLockUm(_In_ MdDeviceObject DeviceObject,_In_ MdIrp Irp,_In_opt_ IUnknown * Context)48 FxDevice::DispatchWithLockUm(
49     _In_ MdDeviceObject DeviceObject,
50     _In_ MdIrp Irp,
51     _In_opt_ IUnknown* Context
52     )
53 {
54     UNREFERENCED_PARAMETER(Context);
55 
56     (void) DispatchWithLock(DeviceObject, Irp);
57 }
58 
59 FxDevice*
GetFxDevice(__in MdDeviceObject DeviceObject)60 FxDevice::GetFxDevice(
61     __in MdDeviceObject DeviceObject
62     )
63 {
64     IWudfDevice2* device2;
65 
66 
67 
68 
69     device2 = static_cast<IWudfDevice2*> (DeviceObject);
70 
71     return (FxDevice *)device2->GetContext();
72 }
73 
74 _Must_inspect_result_
75 NTSTATUS
FdoInitialize(__in PWDFDEVICE_INIT DeviceInit)76 FxDevice::FdoInitialize(
77     __in PWDFDEVICE_INIT DeviceInit
78     )
79 {
80     PFX_DRIVER_GLOBALS pGlobals;
81     NTSTATUS status;
82     FxPkgFdo * pkgFdo;
83     HRESULT hr;
84     BOOLEAN bAttached = FALSE;
85 
86     pGlobals = GetDriverGlobals();
87 
88     if (DeviceInit->Fdo.EventCallbacks.EvtDeviceFilterAddResourceRequirements != NULL &&
89         DeviceInit->Fdo.EventCallbacks.EvtDeviceRemoveAddedResources == NULL) {
90         //
91         // Not allowed to add resources without filtering them out later
92         //
93         DoTraceLevelMessage(
94             pGlobals, TRACE_LEVEL_ERROR, TRACINGPNP,
95             "Must set EvtDeviceRemoveAddedResources if "
96             "EvtDeviceFilterAddResourceRequirements (%p) is set",
97             DeviceInit->Fdo.EventCallbacks.EvtDeviceFilterAddResourceRequirements);
98 
99         FxVerifierDbgBreakPoint(pGlobals);
100 
101         return STATUS_INVALID_DEVICE_STATE;
102     }
103 
104     //
105     // All FDOs cannot be deleted through the driver calling WdfObjectDelete
106     //
107     MarkNoDeleteDDI();
108 
109     m_PhysicalDevice.SetObject((MdDeviceObject)DeviceInit->Fdo.PhysicalDevice);
110 
111     //
112     // The PDO is known because it was used to bring up this FDO.
113     //
114     m_PdoKnown = TRUE;
115 
116     //
117     // Try to create and install the default packages that an FDO contains.
118     //
119 
120     // PnP
121     status = FxPkgFdo::_Create(pGlobals, (CfxDevice*)this, &pkgFdo);
122 
123     if (!NT_SUCCESS(status)) {
124         return status;
125     }
126     else {
127         m_PkgPnp = pkgFdo;
128     }
129 
130     InstallPackage(m_PkgPnp);
131 
132     status = SetFilter(DeviceInit->Fdo.Filter);
133     if (!NT_SUCCESS(status)) {
134         return status;
135     }
136 
137     status = GetFdoPkg()->Initialize(DeviceInit);
138     if (!NT_SUCCESS(status)) {
139         return status;
140     }
141 
142 
143     //
144     // Should be done after invoking Initialize so that FxPkgFdo::m_EnumInfo is
145     // already allocated.
146     //
147     if (DeviceInit->Fdo.ListConfig.Size > 0) {
148         status = GetFdoPkg()->CreateDefaultDeviceList(
149             &DeviceInit->Fdo.ListConfig,
150             DeviceInit->Fdo.ListConfigAttributes.Size > 0
151                 ? &DeviceInit->Fdo.ListConfigAttributes
152                 : NULL);
153 
154         if (!NT_SUCCESS(status)) {
155             return status;
156         }
157 
158         SetDeviceTelemetryInfoFlags(DeviceInfoHasDynamicChildren);
159     }
160 
161     //
162     // If the Size is zero then the driver writer never set any callbacks so we
163     // can skip this call.
164     //
165     if (DeviceInit->Fdo.EventCallbacks.Size != 0) {
166         status = GetFdoPkg()->RegisterCallbacks(&DeviceInit->Fdo.EventCallbacks);
167         if (!NT_SUCCESS(status)) {
168             return status;
169         }
170     }
171 
172     status = CreateDevice(DeviceInit);
173     if (NT_SUCCESS(status)) {
174         MdDeviceObject attachedDevice = NULL;
175 
176         //
177         // If this is an FDO then the PhysicalDevice field will be initialized,
178         // and we need to attach to the device stack.
179         //
180         //
181         // Attach the newly created host device object to existing stack.
182         // Insert the host device in the device chain for this device stack.
183         //
184         hr = DeviceInit->DevStack->AttachDevice(
185                                         m_DeviceObject.GetObject(),
186                                         &attachedDevice
187                                         );
188         if (S_OK == hr) {
189             status = STATUS_SUCCESS;
190         }
191         else {
192             //
193             // Catch if the host isn't obeying the COM contract that requires
194             // a NULL interface when FAILED(hr).
195             // Note that AttachDevice can return success with a NULL interface
196             // for the attached device when this device is the first in the
197             // stack.
198             //
199             FX_VERIFY(DRIVER(BadArgument, TODO), CHECK_NULL(attachedDevice));
200             status = FxDevice::NtStatusFromHr(DeviceInit->DevStack, hr);
201             goto exit;
202         }
203 
204         m_AttachedDevice.SetObject(attachedDevice);
205         bAttached = TRUE;
206 
207         if (m_AttachedDevice.GetObject() == NULL) {
208             //
209             // Note that AttachDevice can return success with a NULL interface
210             // for the attached device when this device is the first in the
211             // stack.
212             //
213 
214 
215 
216 
217             //
218             DO_NOTHING();
219         }
220 
221         if (NT_SUCCESS(status)) {
222             //
223             // If PPO, save newly created device as PPO in device stack
224             //
225             if (DeviceInit->IsPwrPolOwner()) {
226                 GetDeviceStack()->SetPPO(m_DeviceObject.GetObject());
227             }
228 
229             //
230             // If we are a filter device, inherit some state from the
231             // attached device.
232             //
233             if (m_Filter) {
234                 //
235                 // Set the IO type and power pageable status on our device based
236                 // on the attached device's settings.
237                 //
238                 SetFilterIoType();
239 
240                 if (m_AttachedDevice.GetObject() != NULL) {
241                     m_DeviceObject.SetFlags(m_DeviceObject.GetFlags() |
242                         (m_AttachedDevice.GetFlags() & (DO_POWER_PAGABLE | DO_POWER_INRUSH)));
243                 }
244 
245                 //
246                 // For devices other then filters, m_PowerPageableCapable gets
247                 // set in CreateDevice, but since this is determined for filters
248                 // by the device they have attached to, we must set this value
249                 // later as a special case only for filters.
250                 //
251                 if (m_DeviceObject.GetFlags() & DO_POWER_PAGABLE) {
252                     m_PowerPageableCapable = TRUE;
253                 }
254             }
255             else {
256                 //
257                 // We are not a filter, we dictate our own DO flags
258                 //
259 
260                 //
261                 // Power pageable and inrush are mutually exclusive
262                 //
263                 if (DeviceInit->PowerPageable) {
264                     m_DeviceObject.SetFlags(m_DeviceObject.GetFlags() | DO_POWER_PAGABLE);
265                 }
266                 else if (DeviceInit->Inrush) {
267                     m_DeviceObject.SetFlags(m_DeviceObject.GetFlags() | DO_POWER_INRUSH);
268                 }
269             }
270         }
271     }
272 
273     //
274     // Set buffer retrieval and I/O type values
275     //
276     m_RetrievalMode = UMINT::WdfDeviceIoBufferRetrievalDeferred;
277     m_ReadWriteIoType = DeviceInit->ReadWriteIoType;
278     m_IoctlIoType = DeviceInit->DeviceControlIoType;;
279     m_DirectTransferThreshold = DeviceInit->DirectTransferThreshold;
280 
281     //
282     // Read HwAccess settings from registry
283     //
284     RetrieveDeviceRegistrySettings();
285 
286     if (!NT_SUCCESS(status)) {
287         return status;
288     }
289 
290     status = m_PkgGeneral->PostCreateDeviceInitialize(DeviceInit);
291     if (!NT_SUCCESS(status)) {
292         return status;
293     }
294 
295     status = GetFdoPkg()->PostCreateDeviceInitialize();
296 
297     if (NT_SUCCESS(status)) {
298         //
299         // Do not clear the DO_DEVICE_INITIALIZING bit here.  Instead, either
300         // let the caller do it in their AddDevice or do it after the AddDevice
301         // callback returns.
302         //
303         // FinishInitializing();
304     }
305 
306     exit:
307 
308     //
309     // Let the device stack object hold the only reference to
310     // the host devices. The infrastructure guarantees that the device
311     // stack's lifetime is greater than the this object's lifetime.
312     // If the Attach failed, the object will be destroyed.
313     //
314     if (NULL != m_DeviceObject.GetObject()) {
315         m_DeviceObject.GetObject()->Release();
316     }
317 
318     if (NULL != m_AttachedDevice.GetObject()) {
319         m_AttachedDevice.GetObject()->Release();
320     }
321 
322     if (!NT_SUCCESS(status)) {
323         if (bAttached) {
324             DetachDevice();
325             bAttached = FALSE;
326         }
327 
328         //
329         // NULL out m_pIWudfDevice so that d'tor doesn't try to detach again.
330         //
331         m_DeviceObject.SetObject(NULL); // weak ref.
332         m_AttachedDevice.SetObject(NULL); // weak ref.
333     }
334 
335     return status;
336 }
337 
338 _Must_inspect_result_
339 NTSTATUS
CreateDevice(__in PWDFDEVICE_INIT DeviceInit)340 FxDevice::CreateDevice(
341     __in PWDFDEVICE_INIT DeviceInit
342     )
343 {
344     MdDeviceObject  pNewDeviceObject = NULL;
345     ULONG           characteristics;
346     NTSTATUS        status;
347     DEVICE_TYPE     devType;
348     HRESULT hr;
349     IWudfDevice2* pNewDeviceObject2;
350     IWudfDeviceStack2* pDevStack2;
351 
352     status = m_PkgGeneral->Initialize(DeviceInit);
353     if (!NT_SUCCESS(status)) {
354         return status;
355     }
356 
357 
358 
359 
360 
361 
362 
363 
364 
365 
366     UNREFERENCED_PARAMETER(devType);
367 
368     characteristics = DeviceInit->Characteristics;
369 
370     status = FxMessageDispatch::_CreateAndInitialize(GetDriverGlobals(),
371                                                      this,
372                                                      &m_Dispatcher);
373     if (!NT_SUCCESS(status)) {
374         return status;
375     }
376 
377     hr = DeviceInit->DevStack->QueryInterface(IID_IWudfDeviceStack2,
378                                              (PVOID*)&pDevStack2);
379     FX_VERIFY(INTERNAL, CHECK_QI(hr, pDevStack2));
380     if (FAILED(hr)) {
381         status = FxDevice::NtStatusFromHr(DeviceInit->DevStack, hr);
382         return status;
383     }
384     pDevStack2->Release(); // weak ref. is sufficient.
385 
386     //
387     // Create IWudfDevice
388     //
389     hr = pDevStack2->CreateDevice2(DeviceInit->DriverID,
390                                static_cast<IFxMessageDispatch*>(m_Dispatcher),
391                                sizeof(FxWdmDeviceExtension),
392                                &pNewDeviceObject2);
393     if (FAILED(hr)) {
394         status = FxDevice::NtStatusFromHr(DeviceInit->DevStack, hr);
395         return status;
396     }
397 
398     hr = pNewDeviceObject2->QueryInterface(IID_IWudfDevice,
399                                           (PVOID*)&pNewDeviceObject);
400     FX_VERIFY(INTERNAL, CHECK_QI(hr, pNewDeviceObject));
401     if (FAILED(hr)) {
402         status = FxDevice::NtStatusFromHr(DeviceInit->DevStack, hr);
403         return status;
404     }
405     pNewDeviceObject->Release();  // weak ref. is sufficient.
406 
407     if (NT_SUCCESS(status)) {
408 
409         //
410         // Initialize the remove lock and the event for use with the remove lock
411         // The event is initiatalized via IWudfDevice so the host can close the
412         // handle before destroying the allocated "WDM extension"
413         // In the KMDF implementation the "WDM device extension" is allocated by
414         // IoCreateDevice and destroyed when the WDM device object is deleted.
415         // In the kernel implementation the allocated extension only needs to be freed,
416         // where-as with UM the event handle needs to be closed as well.
417         //
418         FxWdmDeviceExtension* pWdmExt;
419         pWdmExt = _GetFxWdmExtension(pNewDeviceObject);
420 
421         Mx::MxInitializeRemoveLock(&pWdmExt->IoRemoveLock,
422                                GetDriverGlobals()->Tag,
423                                0,          // max min
424                                0);         // highwater mark
425 
426         status = pNewDeviceObject2->InitializeEventForRemoveLock(
427                                     &(pWdmExt->IoRemoveLock.RemoveEvent));
428         if (!NT_SUCCESS(status)) {
429             return status;
430         }
431         ASSERT(pWdmExt->IoRemoveLock.RemoveEvent);
432 
433         m_DeviceObject.SetObject(pNewDeviceObject);
434 
435         //
436         // Set the context
437         //
438         pNewDeviceObject2->SetContext(this);
439 
440         //
441         // capture input info
442         //
443         m_DevStack = DeviceInit->DevStack;
444 
445         //
446         // Hijack from deviceinit
447         //
448         m_PdoDevKey = DeviceInit->PdoKey;
449         DeviceInit->PdoKey = NULL;
450 
451         m_DeviceKeyPath = DeviceInit->ConfigRegistryPath;
452         DeviceInit->ConfigRegistryPath = NULL;
453 
454         m_KernelDeviceName = DeviceInit->KernelDeviceName;
455         DeviceInit->KernelDeviceName = NULL;
456 
457         m_DeviceInstanceId = DeviceInit->DevInstanceID;
458         DeviceInit->DevInstanceID = NULL;
459 
460         //
461         // Set some device object flags based on properties of DeviceInit.
462         //
463         // If we are a filter, we will set these flags later
464         // (in FxDevice::FdoInitialize) based on the device we are attached to.
465         //
466         if (m_Filter == FALSE) {
467             if (DeviceInit->ReadWriteIoType == WdfDeviceIoBuffered) {
468                 m_DeviceObject.SetFlags(m_DeviceObject.GetFlags() | DO_BUFFERED_IO);
469             }
470             else if (DeviceInit->ReadWriteIoType == WdfDeviceIoDirect) {
471                 m_DeviceObject.SetFlags(m_DeviceObject.GetFlags() | DO_DIRECT_IO);
472             }
473 
474             m_ReadWriteIoType = DeviceInit->ReadWriteIoType;
475             m_PowerPageableCapable = DeviceInit->PowerPageable;
476         }
477 
478         //
479         // Note: In case of UMDF the StackSize of the MdDeviceObject must
480         // be incremented prior to calling AttachDevice. It is because at the
481         // time of attaching the device the CWudfDevStack caches the stack
482         // size of devnode.
483         // This is unlike KMDF where it must be done after AttachDevice.
484         // Though the UMDF design can be modified to match KMDF solution, it
485         // seems simpler to adjust the stack size of UMDF prior to AttachDevice
486         //
487         if (m_SelfIoTargetNeeded) {
488             SetStackSize(GetStackSize()+1);
489         }
490     }
491 
492     return status;
493 }
494 
495 VOID
Destroy(VOID)496 FxDevice::Destroy(
497     VOID
498     )
499 {
500     //
501     // If there was a failure during create (AddDevice), we need to detach
502     // from stack so that we don't receive remove irp from host (since fx sm
503     // uses a simulated remove event to do remove related cleanup).
504     //
505     if (m_CleanupFromFailedCreate) {
506         if (m_DeviceObject.GetObject() != NULL) {
507             DeleteSymbolicLink();
508 
509             //
510             // The device object may not go away right away if there are pending
511             // references on it.  But we can't look up our FxDevice anymore, so
512             // lets clear the DeviceExtension pointer.
513             //
514             m_DeviceObject.SetDeviceExtension(NULL);
515         }
516 
517         //
518         // Since this can be called in the context of the destructor when the ref
519         // count is zero, use GetObjectHandleUnchecked() to get the handle value.
520         //
521         DoTraceLevelMessage(
522             GetDriverGlobals(), TRACE_LEVEL_INFORMATION, TRACINGDEVICE,
523             "Deleting !devobj %p, WDFDEVICE %p, attached to !devobj %p",
524             m_DeviceObject.GetObject(), GetObjectHandleUnchecked(),
525             m_AttachedDevice.GetObject());
526 
527         //
528         // This will detach the device from stack. Note that detach may cause
529         // the last ref on device object (IWudfDevice) to be released and
530         // therefore delete the device object.
531         //
532         DetachDevice();
533     }
534 }
535 
536 VOID
DestructorInternal(VOID)537 FxDevice::DestructorInternal(
538     VOID
539     )
540 {
541     if (m_DeviceObject.GetObject() != NULL) {
542         //
543         // The device object may not go away right away if there are pending
544         // references on it.  But we can't look up our FxDevice anymore, so
545         // lets clear the DeviceExtension pointer.
546         //
547         m_DeviceObject.SetDeviceExtension(NULL);
548     }
549 
550     //
551     // Since this can be called in the context of the destructor when the ref
552     // count is zero, use GetObjectHandleUnchecked() to get the handle value.
553     //
554     DoTraceLevelMessage(
555         GetDriverGlobals(), TRACE_LEVEL_INFORMATION, TRACINGDEVICE,
556         "Deleting !devobj %p, WDFDEVICE %p, attached to !devobj %p",
557         m_DeviceObject.GetObject(), GetObjectHandleUnchecked(),
558         m_AttachedDevice.GetObject());
559 
560     //
561     // This will detach the device from stack. Note that detach may cause
562     // the last ref on device object (IWudfDevice) to be released and
563     // therefore delete the device object.
564     //
565     DetachDevice();
566 
567     if (m_InteruptThreadpool) {
568         delete m_InteruptThreadpool;
569         m_InteruptThreadpool = NULL;
570     }
571 
572     delete [] m_KernelDeviceName;
573     m_KernelDeviceName = NULL;
574 
575     delete [] m_DeviceKeyPath;
576     m_DeviceKeyPath = NULL;
577 
578     delete [] m_DeviceInstanceId;
579     m_DeviceInstanceId = NULL;
580 
581     if (m_PdoDevKey) {
582         RegCloseKey(m_PdoDevKey);
583         this->m_PdoDevKey = NULL;
584     }
585 
586     if (m_Dispatcher) {
587         delete m_Dispatcher;
588         m_Dispatcher = NULL;
589     }
590 }
591 
592 VOID
GetPreferredTransferMode(_In_ MdDeviceObject DeviceObject,_Out_ UMINT::WDF_DEVICE_IO_BUFFER_RETRIEVAL * RetrievalMode,_Out_ WDF_DEVICE_IO_TYPE * RWPreference,_Out_ WDF_DEVICE_IO_TYPE * IoctlPreference)593 FxDevice::GetPreferredTransferMode(
594     _In_ MdDeviceObject DeviceObject,
595     _Out_ UMINT::WDF_DEVICE_IO_BUFFER_RETRIEVAL *RetrievalMode,
596     _Out_ WDF_DEVICE_IO_TYPE *RWPreference,
597     _Out_ WDF_DEVICE_IO_TYPE *IoctlPreference
598     )
599 /*++
600 
601   Routine Description:
602 
603     This method returns the i/o type information for the device to the
604     caller.
605 
606   Arguments:
607 
608     RetrievalMode - the retrival mode desired by this device
609 
610     RWPreference - the preferred r/w mode for the device
611 
612     IoctlPreference - the preferred ioctl mode for the device
613 
614   Return Value:
615 
616     None
617 
618 --*/
619 {
620     FxDevice* device;
621 
622     device = GetFxDevice(DeviceObject);
623 
624     *RetrievalMode = device->GetRetrievalMode();
625     *RWPreference = device->GetPreferredRWTransferMode();
626     *IoctlPreference = device->GetPreferredIoctlTransferMode();
627 }
628 
629 _Must_inspect_result_
630 NTSTATUS
PdoInitialize(__in PWDFDEVICE_INIT DeviceInit)631 FxDevice::PdoInitialize(
632     __in PWDFDEVICE_INIT DeviceInit
633     )
634 {
635     UNREFERENCED_PARAMETER(DeviceInit);
636     ASSERTMSG("Not implemented for UMDF\n", FALSE);
637     return STATUS_NOT_IMPLEMENTED;
638 }
639 
640 
641 _Must_inspect_result_
642 NTSTATUS
ControlDeviceInitialize(__in PWDFDEVICE_INIT DeviceInit)643 FxDevice::ControlDeviceInitialize(
644     __in PWDFDEVICE_INIT DeviceInit
645     )
646 {
647     UNREFERENCED_PARAMETER(DeviceInit);
648     ASSERTMSG("Not implemented for UMDF\n", FALSE);
649     return STATUS_NOT_IMPLEMENTED;
650 }
651 
652 VOID
AddChildList(__inout FxChildList * List)653 FxDevice::AddChildList(
654     __inout FxChildList* List
655     )
656 {
657     UNREFERENCED_PARAMETER(List);
658     ASSERTMSG("Not implemented for UMDF\n", FALSE);
659 }
660 
661 VOID
RemoveChildList(__inout FxChildList * List)662 FxDevice::RemoveChildList(
663     __inout FxChildList* List
664     )
665 {
666     UNREFERENCED_PARAMETER(List);
667     ASSERTMSG("Not implemented for UMDF\n", FALSE);
668 }
669 
670 _Must_inspect_result_
671 NTSTATUS
AllocateDmaEnablerList(VOID)672 FxDevice::AllocateDmaEnablerList(
673     VOID
674     )
675 {
676     ASSERTMSG("Not implemented for UMDF\n", FALSE);
677     return STATUS_NOT_IMPLEMENTED;
678 }
679 
680 VOID
AddDmaEnabler(__inout FxDmaEnabler * Enabler)681 FxDevice::AddDmaEnabler(
682     __inout FxDmaEnabler* Enabler
683     )
684 {
685     UNREFERENCED_PARAMETER(Enabler);
686     ASSERTMSG("Not implemented for UMDF\n", FALSE);
687 }
688 
689 VOID
RemoveDmaEnabler(__inout FxDmaEnabler * Enabler)690 FxDevice::RemoveDmaEnabler(
691     __inout FxDmaEnabler* Enabler
692     )
693 {
694     UNREFERENCED_PARAMETER(Enabler);
695     ASSERTMSG("Not implemented for UMDF\n", FALSE);
696 }
697 
698 NTSTATUS
ProcessWmiPowerQueryOrSetData(_In_ RdWmiPowerAction Action,_Out_ BOOLEAN * QueryResult)699 FxDevice::ProcessWmiPowerQueryOrSetData (
700     _In_ RdWmiPowerAction   Action,
701     _Out_ BOOLEAN *         QueryResult
702     )
703 /*++
704 
705   Routine Description:
706 
707     This method is called to process WMI set/Query data received from
708     reflector. Reflector sends this message when it receives a WMI Query or
709     Set Irp for this device for power guids.
710 
711   Arguments:
712 
713     Action - Enumeration of Set and Query actions for S0Idle and SxWake
714 
715     *QueryResult - receives the query result.
716 
717   Return Value:
718 
719     STATUS_SUCCESS if successful
720 
721     STATUS_INVALID_PARAMETER if the parameter values are invalid
722 
723 --*/
724 {
725     if (Action == ActionInvalid) {
726         return STATUS_INVALID_PARAMETER;
727     }
728 
729     if ((Action == QueryS0Idle || Action == QuerySxWake) && QueryResult == NULL) {
730         return STATUS_INVALID_PARAMETER;
731     }
732 
733     switch(Action)
734     {
735     case SetS0IdleEnable:
736         m_PkgPnp->PowerPolicySetS0IdleState(TRUE);
737         break;
738     case SetS0IdleDisable:
739         m_PkgPnp->PowerPolicySetS0IdleState(FALSE);
740         break;
741     case SetSxWakeEnable:
742         m_PkgPnp->PowerPolicySetSxWakeState(TRUE);
743         break;
744     case SetSxWakeDisable:
745         m_PkgPnp->PowerPolicySetSxWakeState(FALSE);
746         break;
747     case QueryS0Idle:
748         *QueryResult = m_PkgPnp->m_PowerPolicyMachine.m_Owner->m_IdleSettings.Enabled;
749         break;
750     case QuerySxWake:
751         *QueryResult = m_PkgPnp->m_PowerPolicyMachine.m_Owner->m_WakeSettings.Enabled;
752         break;
753     default:
754         ASSERT(FALSE);
755         break;
756     }
757 
758     return STATUS_SUCCESS;
759 }
760 
761 WUDF_INTERFACE_CONTEXT
RemoteInterfaceArrival(_In_ IWudfDevice * DeviceObject,_In_ LPCGUID DeviceInterfaceGuid,_In_ PCWSTR SymbolicLink)762 FxDevice::RemoteInterfaceArrival (
763     _In_    IWudfDevice *   DeviceObject,
764     _In_    LPCGUID         DeviceInterfaceGuid,
765     _In_    PCWSTR          SymbolicLink
766     )
767 {
768     UNREFERENCED_PARAMETER(DeviceObject);
769     UNREFERENCED_PARAMETER(DeviceInterfaceGuid);
770     UNREFERENCED_PARAMETER(SymbolicLink);
771 
772     ASSERTMSG("Not implemented for UMDF\n", FALSE);
773 
774     return NULL;
775 }
776 
777 void
RemoteInterfaceRemoval(_In_ IWudfDevice * DeviceObject,_In_ WUDF_INTERFACE_CONTEXT RemoteInterfaceID)778 FxDevice::RemoteInterfaceRemoval (
779     _In_    IWudfDevice *   DeviceObject,
780     _In_    WUDF_INTERFACE_CONTEXT RemoteInterfaceID
781     )
782 {
783     UNREFERENCED_PARAMETER(DeviceObject);
784     UNREFERENCED_PARAMETER(RemoteInterfaceID);
785 
786     ASSERTMSG("Not implemented for UMDF\n", FALSE);
787 }
788 
789 BOOL
TransportQueryId(_In_ IWudfDevice * DeviceObject,_In_ DWORD Id,_In_ PVOID DataBuffer,_In_ SIZE_T cbDataBufferSize)790 FxDevice::TransportQueryId (
791     _In_    IWudfDevice *   DeviceObject,
792     _In_    DWORD           Id,
793     _In_    PVOID           DataBuffer,
794     _In_    SIZE_T          cbDataBufferSize
795     )
796 {
797     UNREFERENCED_PARAMETER(DeviceObject);
798     UNREFERENCED_PARAMETER(Id);
799     UNREFERENCED_PARAMETER(DataBuffer);
800     UNREFERENCED_PARAMETER(cbDataBufferSize);
801 
802     ASSERTMSG("Not implemented for UMDF\n", FALSE);
803 
804     return FALSE;
805 }
806 
807 void
PoFxDevicePowerRequired(_In_ MdDeviceObject DeviceObject)808 FxDevice::PoFxDevicePowerRequired (
809     _In_ MdDeviceObject DeviceObject
810     )
811 {
812     GetFxDevice(DeviceObject)->m_PkgPnp->m_PowerPolicyMachine.m_Owner->
813          m_PoxInterface.PowerRequiredCallbackInvoked();
814 }
815 
816 void
PoFxDevicePowerNotRequired(_In_ MdDeviceObject DeviceObject)817 FxDevice::PoFxDevicePowerNotRequired (
818     _In_ MdDeviceObject DeviceObject
819     )
820 {
821     GetFxDevice(DeviceObject)->m_PkgPnp->m_PowerPolicyMachine.m_Owner->
822          m_PoxInterface.PowerNotRequiredCallbackInvoked();
823 }
824 
825 NTSTATUS
NtStatusFromHr(_In_ IWudfDeviceStack * DevStack,_In_ HRESULT Hr)826 FxDevice::NtStatusFromHr (
827     _In_ IWudfDeviceStack * DevStack,
828     _In_ HRESULT Hr
829     )
830 {
831     PUMDF_VERSION_DATA driverVersion = DevStack->GetMinDriverVersion();
832     BOOL preserveCompat =
833          DevStack->ShouldPreserveIrpCompletionStatusCompatibility();
834 
835     return CHostFxUtil::NtStatusFromHr(Hr,
836                                        driverVersion->MajorNumber,
837                                        driverVersion->MinorNumber,
838                                        preserveCompat
839                                        );
840 }
841 
842 NTSTATUS
NtStatusFromHr(_In_ HRESULT Hr)843 FxDevice::NtStatusFromHr (
844     _In_ HRESULT Hr
845     )
846 {
847    return FxDevice::NtStatusFromHr(GetDeviceStack(), Hr);
848 }
849 
850 VOID
RetrieveDeviceRegistrySettings(VOID)851 FxDevice::RetrieveDeviceRegistrySettings(
852     VOID
853     )
854 {
855     DWORD err;
856     HKEY wudfKey = NULL;
857     DWORD data;
858     DWORD dataSize;
859 
860     err = RegOpenKeyEx(m_PdoDevKey,
861                        WUDF_SUB_KEY,
862                        0,
863                        KEY_READ,
864                        &wudfKey);
865     if (ERROR_SUCCESS != err) {
866         DoTraceLevelMessage(GetDriverGlobals(), TRACE_LEVEL_ERROR, TRACINGPNP,
867              "Failed to open hw registry key to read hw access settings");
868         goto clean0;
869     }
870 
871     //
872     // Read FX_DIRECT_HARDWARE_ACCESS value
873     //
874     dataSize = sizeof(data);
875     data = 0;
876     err = RegQueryValueEx(wudfKey,
877                           FX_DIRECT_HARDWARE_ACCESS,
878                           NULL,
879                           NULL,
880                           (BYTE*) &data,
881                           &dataSize);
882 
883     if (ERROR_SUCCESS == err) {
884         if (((WDF_DIRECT_HARDWARE_ACCESS_TYPE)data) < WdfDirectHardwareAccessMax) {
885             //
886             // save the setting only if it is valid
887             //
888             m_DirectHardwareAccess = (WDF_DIRECT_HARDWARE_ACCESS_TYPE)data;
889         }
890         else {
891             DoTraceLevelMessage(GetDriverGlobals(), TRACE_LEVEL_ERROR, TRACINGPNP,
892                      "invalid direct hardware access value in registry %u",
893                      (WDF_DIRECT_HARDWARE_ACCESS_TYPE)data);
894         }
895     }
896     else if (ERROR_FILE_NOT_FOUND != err) {
897         DoTraceLevelMessage(GetDriverGlobals(), TRACE_LEVEL_ERROR, TRACINGPNP,
898              "Failed to read direct hardware access value in registry");
899     }
900 
901     DoTraceLevelMessage(GetDriverGlobals(), TRACE_LEVEL_INFORMATION, TRACINGPNP,
902         "DirectHardwareAccess = %u", m_DirectHardwareAccess);
903 
904 
905     //
906     // Read FX_REGISTER_ACCESS_MODE value
907     //
908     dataSize = sizeof(data);
909     data = 0;
910     err = RegQueryValueEx(wudfKey,
911                           FX_REGISTER_ACCESS_MODE,
912                           NULL,
913                           NULL,
914                           (BYTE*) &data,
915                           &dataSize);
916     if (ERROR_SUCCESS == err) {
917         if (((WDF_REGISTER_ACCESS_MODE_TYPE)data) < WdfRegisterAccessMax) {
918             //
919             // save the setting only if it is valid
920             //
921             m_RegisterAccessMode = (WDF_REGISTER_ACCESS_MODE_TYPE)data;
922         }
923         else {
924             DoTraceLevelMessage(GetDriverGlobals(), TRACE_LEVEL_ERROR, TRACINGPNP,
925                  "Invalid Register Access mode value in registry %u",
926                  (WDF_REGISTER_ACCESS_MODE_TYPE)data);
927         }
928     }
929     else if (ERROR_FILE_NOT_FOUND != err) {
930         DoTraceLevelMessage(GetDriverGlobals(), TRACE_LEVEL_ERROR, TRACINGPNP,
931              "Failed to read Register Access mode value in registry");
932     }
933 
934     DoTraceLevelMessage(GetDriverGlobals(), TRACE_LEVEL_INFORMATION, TRACINGPNP,
935         "RegisterAccessMode = %u", m_RegisterAccessMode);
936 
937     //
938     // Read FX_FILE_OBJECT_POLICY
939     //
940     dataSize = sizeof(data);
941     data = 0;
942     err = RegQueryValueEx(wudfKey,
943                           FX_FILE_OBJECT_POLICY,
944                           NULL,
945                           NULL,
946                           (BYTE*) &data,
947                           &dataSize);
948     if (ERROR_SUCCESS == err) {
949         if (((WDF_FILE_OBJECT_POLICY_TYPE)data) < WdfFileObjectPolicyMax) {
950             //
951             // save the setting only if it is valid
952             //
953             m_FileObjectPolicy = (WDF_FILE_OBJECT_POLICY_TYPE)data;
954         }
955         else {
956             DoTraceLevelMessage(GetDriverGlobals(), TRACE_LEVEL_ERROR, TRACINGPNP,
957                  "Invalid File object Policy value in registry %u",
958                  (WDF_FILE_OBJECT_POLICY_TYPE)data);
959         }
960     }
961     else if (ERROR_FILE_NOT_FOUND != err) {
962         DoTraceLevelMessage(GetDriverGlobals(), TRACE_LEVEL_ERROR, TRACINGPNP,
963              "Failed to read File Object Policy value in registry");
964     }
965 
966     DoTraceLevelMessage(GetDriverGlobals(), TRACE_LEVEL_INFORMATION, TRACINGPNP,
967         "FileObjectPolicy = %u", m_FileObjectPolicy);
968 
969     //
970     // Read FX_FS_CONTEXT_USE_POLICY
971     //
972     dataSize = sizeof(data);
973     data = 0;
974     err = RegQueryValueEx(wudfKey,
975                           FX_FS_CONTEXT_USE_POLICY,
976                           NULL,
977                           NULL,
978                           (BYTE*) &data,
979                           &dataSize);
980     if (ERROR_SUCCESS == err) {
981         if (((WDF_FS_CONTEXT_USE_POLICY_TYPE)data) < WdfFsContextUsePolicyMax) {
982             //
983             // save the setting only if it is valid
984             //
985             m_FsContextUsePolicy = (WDF_FS_CONTEXT_USE_POLICY_TYPE)data;
986         }
987         else {
988             DoTraceLevelMessage(GetDriverGlobals(), TRACE_LEVEL_ERROR, TRACINGPNP,
989                  "Invalid Fs Context Use Policy value in registry %u",
990                  (WDF_FILE_OBJECT_POLICY_TYPE)data);
991         }
992     }
993     else if (ERROR_FILE_NOT_FOUND != err) {
994         DoTraceLevelMessage(GetDriverGlobals(), TRACE_LEVEL_ERROR, TRACINGPNP,
995              "Failed to read Fs Context Use Policy value in registry");
996     }
997 
998     DoTraceLevelMessage(GetDriverGlobals(), TRACE_LEVEL_INFORMATION, TRACINGPNP,
999         "FsContextUsePolicy = %u", m_FsContextUsePolicy);
1000 
1001 
1002 clean0:
1003 
1004     if (NULL != wudfKey) {
1005         RegCloseKey(wudfKey);
1006     }
1007 
1008     return;
1009 }
1010 
1011 NTSTATUS
_OpenDeviceRegistryKey(_In_ PFX_DRIVER_GLOBALS FxDriverGlobals,_In_ IWudfDeviceStack * DeviceStack,_In_ PWSTR DriverName,_In_ ULONG DevInstKeyType,_In_ ACCESS_MASK DesiredAccess,_Out_ PHANDLE DevInstRegKey)1012 FxDevice::_OpenDeviceRegistryKey(
1013     _In_ PFX_DRIVER_GLOBALS FxDriverGlobals,
1014     _In_ IWudfDeviceStack* DeviceStack,
1015     _In_ PWSTR DriverName,
1016     _In_ ULONG DevInstKeyType,
1017     _In_ ACCESS_MASK DesiredAccess,
1018     _Out_ PHANDLE DevInstRegKey
1019     )
1020 {
1021     NTSTATUS status;
1022     HRESULT hr;
1023 
1024     UMINT::WDF_PROPERTY_STORE_ROOT root;
1025     UMINT::WDF_PROPERTY_STORE_RETRIEVE_FLAGS flags = UMINT::WdfPropertyStoreNormal;
1026     PWSTR subpath = NULL;
1027 
1028 
1029 
1030 
1031     #define WDF_REGKEY_DEVICE_SUBKEY 256
1032     #define WDF_REGKEY_DRIVER_SUBKEY 256
1033 
1034     root.LengthCb = sizeof(UMINT::WDF_PROPERTY_STORE_ROOT);
1035 
1036     if (DevInstKeyType & PLUGPLAY_REGKEY_CURRENT_HWPROFILE)
1037     {
1038         ASSERTMSG("Not available in UMDF\n", FALSE);
1039     }
1040     else if (DevInstKeyType & PLUGPLAY_REGKEY_DEVICE)
1041     {
1042         root.RootClass = UMINT::WdfPropertyStoreRootClassHardwareKey;
1043 
1044         if (DevInstKeyType & WDF_REGKEY_DEVICE_SUBKEY)
1045         {
1046             root.Qualifier.HardwareKey.ServiceName = DriverName;
1047             flags = UMINT::WdfPropertyStoreCreateIfMissing;
1048         }
1049         else
1050         {
1051             root.Qualifier.HardwareKey.ServiceName = WDF_PROPERTY_STORE_HARDWARE_KEY_ROOT;
1052         }
1053     }
1054     else if (DevInstKeyType & PLUGPLAY_REGKEY_DRIVER)
1055     {
1056         root.RootClass = UMINT::WdfPropertyStoreRootClassSoftwareKey;
1057 
1058         if (DevInstKeyType & WDF_REGKEY_DRIVER_SUBKEY)
1059         {
1060             subpath = DriverName;
1061             flags = UMINT::WdfPropertyStoreCreateIfMissing;
1062         }
1063         else
1064         {
1065             subpath = L"\\";
1066         }
1067     }
1068     else if (DevInstKeyType & FX_PLUGPLAY_REGKEY_DEVICEMAP)
1069     {
1070         root.RootClass = UMINT::WdfPropertyStoreRootClassLegacyHardwareKey;
1071 
1072         //
1073         // Legacy keys must always be opened volatile for UMDF
1074         //
1075         flags = UMINT::WdfPropertyStoreCreateVolatile;
1076 
1077         subpath = NULL;
1078         root.Qualifier.LegacyHardwareKey.LegacyMapName = DriverName;
1079     }
1080 
1081     hr = ((IWudfDeviceStack*)DeviceStack)->CreateRegistryEntry(&root,
1082                                                                flags,
1083                                                                DesiredAccess,
1084                                                                subpath,
1085                                                                (PHKEY)DevInstRegKey,
1086                                                                NULL);
1087     status = FxDevice::NtStatusFromHr(DeviceStack, hr);
1088 
1089     return status;
1090 }
1091 
1092 NTSTATUS
_GetDeviceProperty(_In_ PVOID DeviceStack,_In_ DEVICE_REGISTRY_PROPERTY DeviceProperty,_In_ ULONG BufferLength,_Out_opt_ PVOID PropertyBuffer,_Out_opt_ PULONG ResultLength)1093 FxDevice::_GetDeviceProperty(
1094     _In_       PVOID DeviceStack,
1095     _In_       DEVICE_REGISTRY_PROPERTY DeviceProperty,
1096     _In_       ULONG BufferLength,
1097     _Out_opt_  PVOID PropertyBuffer,
1098     _Out_opt_  PULONG ResultLength
1099     )
1100 {
1101     HRESULT hr;
1102     NTSTATUS status;
1103 
1104     DEVPROPTYPE propType;
1105     const DEVPROPKEY *propKey = NULL;
1106 
1107     //
1108     // {cccccccc-cccc-cccc-cccc-cccccccccccc}
1109     // 2 brackets + 4 dashes + 32 characters + UNICODE_NULL
1110     //
1111     GUID guidBuffer = {0};
1112     ULONG guidChLen = 2 + 4 + 32 + 1;
1113     ULONG guidCbLen = guidChLen * sizeof(WCHAR);
1114     BOOLEAN convertGuidToString = FALSE;
1115 
1116     PVOID buffer = PropertyBuffer;
1117     ULONG bufferLen = BufferLength;
1118     ULONG resultLen = 0;
1119 
1120     UMINT::WDF_PROPERTY_STORE_ROOT rootSpecifier;
1121     rootSpecifier.LengthCb = sizeof(UMINT::WDF_PROPERTY_STORE_ROOT);
1122     rootSpecifier.RootClass = UMINT::WdfPropertyStoreRootClassHardwareKey;
1123     rootSpecifier.Qualifier.HardwareKey.ServiceName = NULL;
1124 
1125     //
1126     // Map DEVICE_REGISTRY_PROPERTY enums to DEVPROPKEYs
1127     //
1128     switch (DeviceProperty)
1129     {
1130         case DevicePropertyDeviceDescription:
1131             propKey = &DEVPKEY_Device_DeviceDesc;
1132             break;
1133         case DevicePropertyHardwareID:
1134             propKey = &DEVPKEY_Device_HardwareIds;
1135             break;
1136         case DevicePropertyCompatibleIDs:
1137             propKey = &DEVPKEY_Device_CompatibleIds;
1138             break;
1139         case DevicePropertyBootConfiguration:
1140             ASSERTMSG("Not available in UMDF\n", FALSE);
1141             break;
1142         case DevicePropertyBootConfigurationTranslated:
1143             ASSERTMSG("Not available in UMDF\n", FALSE);
1144             break;
1145         case DevicePropertyClassName:
1146             propKey = &DEVPKEY_Device_Class;
1147             break;
1148         case DevicePropertyClassGuid:
1149             propKey = &DEVPKEY_Device_ClassGuid;
1150             convertGuidToString = TRUE;
1151             break;
1152         case DevicePropertyDriverKeyName:
1153             propKey = &DEVPKEY_NAME;
1154             break;
1155         case DevicePropertyManufacturer:
1156             propKey = &DEVPKEY_Device_Manufacturer;
1157             break;
1158         case DevicePropertyFriendlyName:
1159             propKey = &DEVPKEY_Device_FriendlyName;
1160             break;
1161         case DevicePropertyLocationInformation:
1162             propKey = &DEVPKEY_Device_LocationInfo;
1163             break;
1164         case DevicePropertyPhysicalDeviceObjectName:
1165             propKey = &DEVPKEY_Device_PDOName;
1166             break;
1167         case DevicePropertyBusTypeGuid:
1168             propKey = &DEVPKEY_Device_BusTypeGuid;
1169             break;
1170         case DevicePropertyLegacyBusType:
1171             propKey = &DEVPKEY_Device_LegacyBusType;
1172             break;
1173         case DevicePropertyBusNumber:
1174             propKey = &DEVPKEY_Device_BusNumber;
1175             break;
1176         case DevicePropertyEnumeratorName:
1177             propKey = &DEVPKEY_Device_EnumeratorName;
1178             break;
1179         case DevicePropertyAddress:
1180             propKey = &DEVPKEY_Device_Address;
1181             break;
1182         case DevicePropertyUINumber:
1183             propKey = &DEVPKEY_Device_UINumber;
1184             break;
1185         case DevicePropertyInstallState:
1186             propKey = &DEVPKEY_Device_InstallState;
1187             break;
1188         case DevicePropertyRemovalPolicy:
1189             propKey = &DEVPKEY_Device_RemovalPolicy;
1190             break;
1191         case DevicePropertyResourceRequirements:
1192             ASSERTMSG("Not available in UMDF\n", FALSE);
1193             break;
1194         case DevicePropertyAllocatedResources:
1195             ASSERTMSG("Not available in UMDF\n", FALSE);
1196             break;
1197         case DevicePropertyContainerID:
1198             propKey = &DEVPKEY_Device_ContainerId;
1199             convertGuidToString = TRUE;
1200             break;
1201     }
1202 
1203     FX_VERIFY(DRIVER(BadArgument, TODO), CHECK_NOT_NULL(propKey));
1204 
1205     if (convertGuidToString)
1206     {
1207         buffer = &guidBuffer;
1208         bufferLen = sizeof(GUID);
1209     }
1210 
1211     hr = ((IWudfDeviceStack*)DeviceStack)->GetUnifiedPropertyData(&rootSpecifier,
1212                                                                   propKey,
1213                                                                   0,
1214                                                                   0,
1215                                                                   bufferLen,
1216                                                                   &propType,
1217                                                                   &resultLen,
1218                                                                   buffer);
1219     if (S_OK == hr)
1220     {
1221         status = STATUS_SUCCESS;
1222 
1223         //
1224         // Some DEVICE_REGISTRY_PROPERTY values are GUID strings,
1225         // while their DEVPROPKEY equivalents are GUID structs. To preserve
1226         // KMDF-UMDF DDI parity, we convert select GUID structs to wchar strings.
1227         //
1228         if (convertGuidToString)
1229         {
1230             if (PropertyBuffer == NULL || BufferLength < guidCbLen)
1231             {
1232                 status = STATUS_BUFFER_TOO_SMALL;
1233             }
1234             else
1235             {
1236                 hr = StringCchPrintf((PWSTR)PropertyBuffer,
1237                                      guidChLen,
1238                                      L"{%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}",
1239                                      guidBuffer.Data1, guidBuffer.Data2, guidBuffer.Data3,
1240                                      guidBuffer.Data4[0], guidBuffer.Data4[1],
1241                                      guidBuffer.Data4[2], guidBuffer.Data4[3],
1242                                      guidBuffer.Data4[4], guidBuffer.Data4[5],
1243                                      guidBuffer.Data4[6], guidBuffer.Data4[7]);
1244                 if (hr != S_OK)
1245                 {
1246                     status = STATUS_UNSUCCESSFUL;
1247                 }
1248             }
1249         }
1250     }
1251     else if (HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER) == hr)
1252     {
1253         status = STATUS_BUFFER_TOO_SMALL;
1254     }
1255     else
1256     {
1257         status = STATUS_UNSUCCESSFUL;
1258     }
1259 
1260     if (ResultLength)
1261     {
1262         *ResultLength = convertGuidToString ? guidCbLen : resultLen;
1263     }
1264 
1265     return status;
1266 }
1267 
1268 VOID
DetachDevice(VOID)1269 FxDevice::DetachDevice(
1270     VOID
1271     )
1272 {
1273     //
1274     // Note that UMDF host's DetachDevice has a different interface than
1275     // IoDetachDevice. DetachDevice takes the current device object as parameter
1276     // instead of target device.
1277     //
1278     if (m_DevStack != NULL &&  m_DeviceObject.GetObject() != NULL) {
1279         Mx::MxDetachDevice(m_DeviceObject.GetObject());
1280         m_AttachedDevice.SetObject(NULL);
1281 
1282         //
1283         // This was a weak ref. Set it to NULL. m_DeviceObject (IWudfDevice)'s
1284         // lifetime is managed by host through a ref taken during Attach.
1285         //
1286         m_DeviceObject.SetObject(NULL);
1287     }
1288 }
1289 
1290 VOID
InvalidateDeviceState(VOID)1291 FxDevice::InvalidateDeviceState(
1292     VOID
1293     )
1294 {
1295     GetMxDeviceObject()->InvalidateDeviceState(GetDeviceObject());
1296 }
1297 
1298 NTSTATUS
CreateSymbolicLink(_In_ PFX_DRIVER_GLOBALS FxDriverGlobals,_In_ PCUNICODE_STRING SymbolicLinkName)1299 FxDevice::CreateSymbolicLink(
1300     _In_ PFX_DRIVER_GLOBALS FxDriverGlobals,
1301     _In_ PCUNICODE_STRING SymbolicLinkName
1302     )
1303 {
1304     HRESULT hr;
1305     NTSTATUS status;
1306 
1307     status = FxDuplicateUnicodeString(FxDriverGlobals,
1308                                       SymbolicLinkName,
1309                                       &m_SymbolicLinkName);
1310 
1311     if (!NT_SUCCESS(status)) {
1312         DoTraceLevelMessage(
1313             FxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE,
1314             "WDFDEVICE %p allocate buffer for symbolic name failed, %!STATUS!",
1315             GetHandle(), status);
1316 
1317         return status;
1318     }
1319 
1320     hr = GetDeviceStack()->CreateSymbolicLink(SymbolicLinkName->Buffer, NULL);
1321     if (SUCCEEDED(hr)) {
1322         status = STATUS_SUCCESS;
1323     }
1324     else {
1325         status = NtStatusFromHr(hr);
1326         ASSERT(NT_SUCCESS(status) == FALSE);
1327 
1328         FxPoolFree(m_SymbolicLinkName.Buffer);
1329 
1330         RtlZeroMemory(&m_SymbolicLinkName,
1331                       sizeof(m_SymbolicLinkName));
1332 
1333         DoTraceLevelMessage(FxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE,
1334                             "WDFDEVICE %p  create symbolic link failed, %!STATUS!",
1335                             GetHandle(), status);
1336     }
1337 
1338     return status;
1339 }
1340 
1341 VOID
DeleteSymbolicLink(VOID)1342 FxDevice::DeleteSymbolicLink(
1343     VOID
1344     )
1345 {
1346     if (m_SymbolicLinkName.Buffer != NULL) {
1347         //
1348         // There is no IoDeleteSymbolicLink equivalent exposed by UMDF host.
1349         // Reflector takes care of deleteing the symbolic link on removal.
1350         // So just free the string now.
1351         //
1352         FxPoolFree(m_SymbolicLinkName.Buffer);
1353         RtlZeroMemory(&m_SymbolicLinkName, sizeof(m_SymbolicLinkName));
1354     }
1355 }
1356 
1357 NTSTATUS
AssignProperty(_In_ PVOID PropertyData,_In_ FxPropertyType FxPropertyType,_In_ DEVPROPTYPE Type,_In_ ULONG BufferLength,_In_opt_ PVOID PropertyBuffer)1358 FxDevice::AssignProperty (
1359     _In_ PVOID PropertyData,
1360     _In_ FxPropertyType FxPropertyType,
1361     _In_ DEVPROPTYPE Type,
1362     _In_ ULONG BufferLength,
1363     _In_opt_ PVOID PropertyBuffer
1364     )
1365 {
1366     NTSTATUS status;
1367     HRESULT hr;
1368     const DEVPROPKEY * propertyKey;
1369     LCID lcid;
1370     ULONG flags;
1371 
1372     //
1373     // call into host to assign the property
1374     //
1375     UMINT::WDF_PROPERTY_STORE_ROOT rootSpecifier = {0};
1376 
1377     if (FxPropertyType == FxInterfaceProperty) {
1378         PWDF_DEVICE_INTERFACE_PROPERTY_DATA interfaceData =
1379             (PWDF_DEVICE_INTERFACE_PROPERTY_DATA) PropertyData;
1380 
1381         rootSpecifier.LengthCb = sizeof(UMINT::WDF_PROPERTY_STORE_ROOT);
1382         rootSpecifier.RootClass = UMINT::WdfPropertyStoreRootClassDeviceInterfaceKey;
1383         rootSpecifier.Qualifier.DeviceInterfaceKey.InterfaceGUID =
1384             interfaceData->InterfaceClassGUID;
1385         if (interfaceData->ReferenceString != NULL) {
1386             rootSpecifier.Qualifier.DeviceInterfaceKey.ReferenceString =
1387                 interfaceData->ReferenceString->Buffer;
1388         }
1389         propertyKey = interfaceData->PropertyKey;
1390         lcid = interfaceData->Lcid;
1391         flags = interfaceData->Flags;
1392     }
1393     else {
1394         PWDF_DEVICE_PROPERTY_DATA deviceData =
1395             (PWDF_DEVICE_PROPERTY_DATA) PropertyData;
1396 
1397         ASSERT(FxPropertyType == FxDeviceProperty);
1398 
1399         rootSpecifier.LengthCb = sizeof(UMINT::WDF_PROPERTY_STORE_ROOT);
1400         rootSpecifier.RootClass = UMINT::WdfPropertyStoreRootClassHardwareKey;
1401         propertyKey = deviceData->PropertyKey;
1402         lcid = deviceData->Lcid;
1403         flags = deviceData->Flags;
1404     }
1405 
1406     hr = GetDeviceStack()->SetUnifiedPropertyData(&rootSpecifier,
1407                                                   propertyKey,
1408                                                   lcid,
1409                                                   flags,
1410                                                   Type,
1411                                                   BufferLength,
1412                                                   PropertyBuffer);
1413     if (S_OK == hr) {
1414         status = STATUS_SUCCESS;
1415     }
1416     else {
1417         status = NtStatusFromHr(hr);
1418         DoTraceLevelMessage(
1419             GetDriverGlobals(), TRACE_LEVEL_ERROR, TRACINGPNP,
1420             "WDFDEVICE %p failed to assign interface property, %!STATUS!",
1421             GetHandle(), status);
1422     }
1423 
1424     return status;
1425 }
1426 
1427 _Must_inspect_result_
1428 NTSTATUS
_OpenKey(_In_ PFX_DRIVER_GLOBALS FxDriverGlobals,_In_opt_ PWDFDEVICE_INIT DeviceInit,_In_opt_ FxDevice * Device,_In_ ULONG DeviceInstanceKeyType,_In_ ACCESS_MASK DesiredAccess,_In_opt_ PWDF_OBJECT_ATTRIBUTES KeyAttributes,_Out_ WDFKEY * Key)1429 FxDevice::_OpenKey(
1430     _In_ PFX_DRIVER_GLOBALS FxDriverGlobals,
1431     _In_opt_ PWDFDEVICE_INIT DeviceInit,
1432     _In_opt_ FxDevice* Device,
1433     _In_ ULONG DeviceInstanceKeyType,
1434     _In_ ACCESS_MASK DesiredAccess,
1435     _In_opt_ PWDF_OBJECT_ATTRIBUTES KeyAttributes,
1436     _Out_ WDFKEY* Key
1437     )
1438 {
1439     FxRegKey* pKey;
1440     WDFKEY keyHandle;
1441     HANDLE hKey = NULL;
1442     NTSTATUS status;
1443     IWudfDeviceStack* deviceStack;
1444     PWSTR driverName;
1445 
1446     status = FxValidateObjectAttributes(FxDriverGlobals, KeyAttributes);
1447     if (!NT_SUCCESS(status)) {
1448         return status;
1449     }
1450 
1451     status = _ValidateOpenKeyParams(FxDriverGlobals, DeviceInit, Device);
1452     if (!NT_SUCCESS(status)) {
1453         return status;
1454     }
1455 
1456     _Analysis_assume_(DeviceInit != NULL || Device != NULL);
1457 
1458     if (DeviceInit != NULL) {
1459         deviceStack = DeviceInit->DevStack;
1460         driverName = DeviceInit->ConfigRegistryPath;
1461     }
1462     else {
1463         deviceStack = Device->m_DevStack;
1464         driverName = Device->m_DeviceKeyPath;
1465     }
1466 
1467     pKey = new(FxDriverGlobals, KeyAttributes) FxRegKey(FxDriverGlobals);
1468 
1469     if (pKey == NULL) {
1470         return STATUS_INSUFFICIENT_RESOURCES;
1471     }
1472 
1473     if (Device != NULL) {
1474         pKey->SetDeviceBase(Device);
1475     }
1476 
1477     status = pKey->Commit(KeyAttributes, (WDFOBJECT*)&keyHandle);
1478 
1479     if (NT_SUCCESS(status)) {
1480         status = _OpenDeviceRegistryKey(FxDriverGlobals,
1481                                         deviceStack,
1482                                         driverName,
1483                                         DeviceInstanceKeyType,
1484                                         DesiredAccess,
1485                                         &hKey);
1486         if (NT_SUCCESS(status)) {
1487             pKey->SetHandle(hKey);
1488             *Key = keyHandle;
1489         }
1490     }
1491 
1492     if (!NT_SUCCESS(status)) {
1493         //
1494         // No object is being returned, make sure the destroy callback will not
1495         // be called.
1496         //
1497         pKey->DeleteFromFailedCreate();
1498     }
1499 
1500     return status;
1501 }
1502 
1503 _Must_inspect_result_
1504 NTSTATUS
OpenSettingsKey(__out HANDLE * Key,__in ACCESS_MASK DesiredAccess)1505 FxDevice::OpenSettingsKey(
1506     __out HANDLE* Key,
1507     __in ACCESS_MASK DesiredAccess
1508     )
1509 {
1510     NTSTATUS status;
1511     FxAutoRegKey parent;
1512     MdDeviceObject pdo;
1513 
1514     //
1515     // We need a PDO to open this reg key.  in the case of failure to create
1516     // a static PDO, we will go down this path in the pnp state machine, so we
1517     // must check for validity always.
1518     //
1519     pdo = GetSafePhysicalDevice();
1520 
1521     if (pdo == NULL) {
1522         return STATUS_INVALID_DEVICE_STATE;
1523     }
1524 
1525     status = _OpenDeviceRegistryKey(GetDriverGlobals(),
1526                                     m_DevStack,
1527                                     m_DeviceKeyPath,
1528                                     PLUGPLAY_REGKEY_DEVICE,
1529                                     DesiredAccess,
1530                                     &parent.m_Key);
1531     if (NT_SUCCESS(status)) {
1532         DECLARE_CONST_UNICODE_STRING(wdf, L"WDF");
1533 
1534         //
1535         // Create the key if it does not already exist
1536         //
1537         status = FxRegKey::_Create(parent.m_Key,
1538                                    &wdf,
1539                                    Key,
1540                                    DesiredAccess);
1541     }
1542 
1543     return status;
1544 }
1545 
1546 _Must_inspect_result_
1547 NTSTATUS
_QueryPropertyEx(_In_ PFX_DRIVER_GLOBALS DriverGlobals,_In_opt_ PWDFDEVICE_INIT DeviceInit,_In_opt_ FxDevice * Device,_In_ PVOID PropertyData,_In_ FxPropertyType FxPropertyType,_In_ ULONG BufferLength,_Out_ PVOID PropertyBuffer,_Out_ PULONG ResultLength,_Out_ PDEVPROPTYPE PropertyType)1548 FxDevice::_QueryPropertyEx (
1549     _In_ PFX_DRIVER_GLOBALS DriverGlobals,
1550     _In_opt_ PWDFDEVICE_INIT DeviceInit,
1551     _In_opt_ FxDevice* Device,
1552     _In_ PVOID PropertyData,
1553     _In_ FxPropertyType FxPropertyType,
1554     _In_ ULONG BufferLength,
1555     _Out_ PVOID PropertyBuffer,
1556     _Out_ PULONG ResultLength,
1557     _Out_ PDEVPROPTYPE PropertyType
1558     )
1559 {
1560     NTSTATUS status;
1561     HRESULT hr;
1562     DEVPROPTYPE propType;
1563     ULONG requiredLength = 0;
1564     const DEVPROPKEY * propertyKey;
1565     LCID lcid;
1566     ULONG flags;
1567     IWudfDeviceStack* devStack;
1568 
1569     *ResultLength = 0;
1570     *PropertyType = 0;
1571 
1572     status = FxDevice::_ValidateOpenKeyParams(DriverGlobals,
1573                                               DeviceInit,
1574                                               Device);
1575     if (!NT_SUCCESS(status)) {
1576         return status;
1577     }
1578 
1579     _Analysis_assume_(DeviceInit != NULL || Device != NULL);
1580 
1581     if (DeviceInit != NULL) {
1582         devStack = DeviceInit->DevStack;
1583     }
1584     else {
1585         devStack = Device->m_DevStack;
1586     }
1587 
1588     UMINT::WDF_PROPERTY_STORE_ROOT rootSpecifier = {0};
1589 
1590     if (FxPropertyType == FxInterfaceProperty) {
1591         PWDF_DEVICE_INTERFACE_PROPERTY_DATA interfaceData =
1592             (PWDF_DEVICE_INTERFACE_PROPERTY_DATA) PropertyData;
1593 
1594         rootSpecifier.LengthCb = sizeof(UMINT::WDF_PROPERTY_STORE_ROOT);
1595         rootSpecifier.RootClass = UMINT::WdfPropertyStoreRootClassDeviceInterfaceKey;
1596         rootSpecifier.Qualifier.DeviceInterfaceKey.InterfaceGUID =
1597             interfaceData->InterfaceClassGUID;
1598         if (interfaceData->ReferenceString != NULL) {
1599             rootSpecifier.Qualifier.DeviceInterfaceKey.ReferenceString =
1600                 interfaceData->ReferenceString->Buffer;
1601         }
1602         propertyKey = interfaceData->PropertyKey;
1603         lcid = interfaceData->Lcid;
1604         flags = interfaceData->Flags;
1605     }
1606     else {
1607         PWDF_DEVICE_PROPERTY_DATA deviceData =
1608             (PWDF_DEVICE_PROPERTY_DATA) PropertyData;
1609 
1610         ASSERT(FxPropertyType == FxDeviceProperty);
1611 
1612         rootSpecifier.LengthCb = sizeof(UMINT::WDF_PROPERTY_STORE_ROOT);
1613         rootSpecifier.RootClass = UMINT::WdfPropertyStoreRootClassHardwareKey;
1614         propertyKey = deviceData->PropertyKey;
1615         lcid = deviceData->Lcid;
1616         flags = deviceData->Flags;
1617     }
1618 
1619     hr = devStack->GetUnifiedPropertyData(&rootSpecifier,
1620                                                propertyKey,
1621                                                lcid,
1622                                                flags,
1623                                                BufferLength,
1624                                                &propType,
1625                                                &requiredLength,
1626                                                PropertyBuffer);
1627 
1628     if (hr == (HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER))) {
1629         status = STATUS_BUFFER_TOO_SMALL;
1630         *ResultLength = requiredLength;
1631         *PropertyType = propType;
1632     }
1633     else if (hr == S_OK) {
1634         status = STATUS_SUCCESS;
1635         *ResultLength = requiredLength;
1636         *PropertyType = propType;
1637     }
1638     else {
1639         status = NtStatusFromHr(devStack, hr);
1640         ASSERT(NT_SUCCESS(status) == FALSE);
1641         DoTraceLevelMessage(DriverGlobals, TRACE_LEVEL_ERROR, TRACINGPNP,
1642                             "Query for unified property buffer failed, %!STATUS!",
1643                             status);
1644     }
1645 
1646     return status;
1647 }
1648 
1649 _Must_inspect_result_
1650 NTSTATUS
_QueryProperty(_In_ PFX_DRIVER_GLOBALS FxDriverGlobals,_In_opt_ PWDFDEVICE_INIT DeviceInit,_In_opt_ FxDevice * Device,_In_opt_ MdDeviceObject RemotePdo,_In_ DEVICE_REGISTRY_PROPERTY DeviceProperty,_In_ ULONG BufferLength,_Out_opt_ PVOID PropertyBuffer,_Out_opt_ PULONG ResultLength)1651 FxDevice::_QueryProperty(
1652     _In_ PFX_DRIVER_GLOBALS FxDriverGlobals,
1653     _In_opt_ PWDFDEVICE_INIT DeviceInit,
1654     _In_opt_ FxDevice* Device,
1655     _In_opt_ MdDeviceObject RemotePdo,
1656     _In_ DEVICE_REGISTRY_PROPERTY DeviceProperty,
1657     _In_ ULONG BufferLength,
1658     _Out_opt_ PVOID PropertyBuffer,
1659     _Out_opt_ PULONG ResultLength
1660     )
1661 {
1662     NTSTATUS status;
1663     IWudfDeviceStack* deviceStack;
1664 
1665     UNREFERENCED_PARAMETER(RemotePdo);
1666 
1667     status = FxDevice::_ValidateOpenKeyParams(FxDriverGlobals,
1668                                               DeviceInit,
1669                                               Device);
1670     if (!NT_SUCCESS(status)) {
1671         return status;
1672     }
1673 
1674     _Analysis_assume_(DeviceInit != NULL || Device != NULL);
1675 
1676     if (DeviceInit != NULL) {
1677         deviceStack = DeviceInit->DevStack;
1678     }
1679     else {
1680         deviceStack = Device->m_DevStack;
1681     }
1682 
1683     status = _GetDeviceProperty(deviceStack,
1684                                 DeviceProperty,
1685                                 BufferLength,
1686                                 PropertyBuffer,
1687                                 ResultLength);
1688     return status;
1689 }
1690 
1691 _Must_inspect_result_
1692 NTSTATUS
FxValidateInterfacePropertyData(_In_ PWDF_DEVICE_INTERFACE_PROPERTY_DATA PropertyData)1693 FxDevice::FxValidateInterfacePropertyData(
1694     _In_ PWDF_DEVICE_INTERFACE_PROPERTY_DATA PropertyData
1695     )
1696 {
1697     NTSTATUS status;
1698     PFX_DRIVER_GLOBALS pFxDriverGlobals = GetDriverGlobals();
1699 
1700     if (PropertyData->Size != sizeof(WDF_DEVICE_INTERFACE_PROPERTY_DATA)) {
1701         status = STATUS_INFO_LENGTH_MISMATCH;
1702         DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGPNP,
1703                      "PropertyData size (%d) incorrect, expected %d, %!STATUS!",
1704                      PropertyData->Size,
1705                      sizeof(WDF_DEVICE_INTERFACE_PROPERTY_DATA), status);
1706         return status;
1707     }
1708 
1709     FxPointerNotNull(pFxDriverGlobals, PropertyData->InterfaceClassGUID);
1710 
1711     status = FxVerifierCheckIrqlLevel(pFxDriverGlobals, PASSIVE_LEVEL);
1712     if (!NT_SUCCESS(status)) {
1713         FxVerifierDbgBreakPoint(pFxDriverGlobals);
1714         return status;
1715     }
1716 
1717     if (PropertyData->ReferenceString != NULL) {
1718         status = FxValidateUnicodeString(pFxDriverGlobals,
1719                                          PropertyData->ReferenceString);
1720         if (!NT_SUCCESS(status)) {
1721             FxVerifierDbgBreakPoint(pFxDriverGlobals);
1722             return status;
1723         }
1724     }
1725 
1726     //
1727     // check if the interface has been registered with WDF
1728     //
1729     if (IsInterfaceRegistered(PropertyData->InterfaceClassGUID,
1730                                        PropertyData->ReferenceString) == FALSE) {
1731         status = STATUS_INVALID_PARAMETER;
1732         DoTraceLevelMessage(
1733             pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGPNP,
1734             "WDFDEVICE %p cannot assign interface property for an interface not"
1735             " yet registered with WDF, %!STATUS!",
1736             GetHandle(), status);
1737         return status;
1738     }
1739 
1740     return status;
1741 }
1742 
1743 VOID
GetDeviceStackIoType(_Out_ WDF_DEVICE_IO_TYPE * ReadWriteIoType,_Out_ WDF_DEVICE_IO_TYPE * IoControlIoType)1744 FxDevice::GetDeviceStackIoType (
1745     _Out_ WDF_DEVICE_IO_TYPE* ReadWriteIoType,
1746     _Out_ WDF_DEVICE_IO_TYPE* IoControlIoType
1747     )
1748 {
1749     UMINT::WDF_DEVICE_IO_BUFFER_RETRIEVAL retrievalMode;
1750 
1751     GetDeviceStack()->GetDeviceStackPreferredTransferMode(
1752                     &retrievalMode,
1753                     (UMINT::WDF_DEVICE_IO_TYPE*)ReadWriteIoType,
1754                     (UMINT::WDF_DEVICE_IO_TYPE*)IoControlIoType
1755                     );
1756 }
1757 
1758 VOID
RetrieveDeviceInfoRegistrySettings(_Out_ PCWSTR * GroupId,_Out_ PUMDF_DRIVER_REGSITRY_INFO DeviceRegInfo)1759 FxDevice::RetrieveDeviceInfoRegistrySettings(
1760     _Out_ PCWSTR* GroupId,
1761     _Out_ PUMDF_DRIVER_REGSITRY_INFO DeviceRegInfo
1762     )
1763 {
1764     DWORD Err;
1765     DWORD Data;
1766     HKEY wudfKey = NULL;
1767     DWORD DataSize;
1768     DWORD type;
1769     PWSTR buffer;
1770     DWORD bufferSize;
1771 
1772     ASSERT(GroupId != NULL);
1773     ASSERT(DeviceRegInfo != NULL);
1774 
1775     ZeroMemory(DeviceRegInfo, sizeof(UMDF_DRIVER_REGSITRY_INFO));
1776     type = REG_NONE;
1777 
1778     if (m_PdoDevKey == NULL) {
1779         DoTraceLevelMessage(GetDriverGlobals(), TRACE_LEVEL_ERROR, TRACINGPNP,
1780                      "Handle to hardware key not yet available");
1781         return;
1782     }
1783 
1784     Err = RegOpenKeyEx(m_PdoDevKey,
1785                        WUDF_SUB_KEY,
1786                        0,
1787                        KEY_READ,
1788                        &wudfKey);
1789     if (ERROR_SUCCESS != Err) {
1790         DoTraceLevelMessage(GetDriverGlobals(), TRACE_LEVEL_ERROR, TRACINGPNP,
1791                      "Failed to open hw registry key to read hw access settings");
1792         goto clean0;
1793     }
1794 
1795     //
1796     // Read WDF_KERNEL_MODE_CLIENT_POLICY value
1797     //
1798     DataSize = sizeof(Data);
1799     Data = 0;
1800     Err = RegQueryValueEx(wudfKey,
1801                           FX_KERNEL_MODE_CLIENT_POLICY,
1802                           NULL,
1803                           NULL,
1804                           (BYTE*) &Data,
1805                           &DataSize);
1806 
1807     if (ERROR_SUCCESS == Err) {
1808         if (((WDF_KERNEL_MODE_CLIENT_POLICY_TYPE)Data) == WdfAllowKernelModeClients) {
1809             DeviceRegInfo->IsKernelModeClientAllowed = TRUE;
1810         }
1811     }
1812     else if (ERROR_FILE_NOT_FOUND != Err) {
1813         DoTraceLevelMessage(GetDriverGlobals(), TRACE_LEVEL_ERROR, TRACINGPNP,
1814                      "Failed to read kernel mode client policy value in registry");
1815     }
1816 
1817     //
1818     // Read WDF_FILE_OBJECT_POLICY value
1819     //
1820     DataSize = sizeof(Data);
1821     Data = 0;
1822     Err = RegQueryValueEx(wudfKey,
1823                           FX_FILE_OBJECT_POLICY,
1824                           NULL,
1825                           NULL,
1826                           (BYTE*) &Data,
1827                           &DataSize);
1828     if (ERROR_SUCCESS == Err) {
1829         if (((WDF_FILE_OBJECT_POLICY_TYPE)Data) == WdfAllowNullAndUnknownFileObjects) {
1830             DeviceRegInfo->IsNullFileObjectAllowed = TRUE;
1831         }
1832     }
1833     else if (ERROR_FILE_NOT_FOUND != Err) {
1834         DoTraceLevelMessage(GetDriverGlobals(), TRACE_LEVEL_ERROR, TRACINGPNP,
1835                      "Failed to read file object policy value in registry");
1836     }
1837 
1838     //
1839     // Read WDF_METHOD_NEITHER_ACTION value
1840     //
1841     DataSize = sizeof(Data);
1842     Data = 0;
1843     Err = RegQueryValueEx(wudfKey,
1844                           FX_METHOD_NEITHER_ACTION,
1845                           NULL,
1846                           NULL,
1847                           (BYTE*) &Data,
1848                           &DataSize);
1849     if (ERROR_SUCCESS == Err) {
1850         if (((WDF_METHOD_NEITHER_ACTION_TYPE)Data) == WdfMethodNeitherAction_Copy) {
1851             DeviceRegInfo->IsMethodNeitherActionCopy = TRUE;
1852         }
1853     }
1854     else if (ERROR_FILE_NOT_FOUND != Err) {
1855         DoTraceLevelMessage(GetDriverGlobals(), TRACE_LEVEL_ERROR, TRACINGPNP,
1856                      "Failed to read method neither action value in registry");
1857     }
1858 
1859     //
1860     // Read WDF_PROCESS_SHARING_ENABLED value
1861     //
1862     DataSize = sizeof(Data);
1863     Data = 0;
1864     Err = RegQueryValueEx(wudfKey,
1865                           FX_PROCESS_SHARING_ENABLED,
1866                           NULL,
1867                           NULL,
1868                           (BYTE*) &Data,
1869                           &DataSize);
1870     if (ERROR_SUCCESS == Err) {
1871         if (((WDF_PROCESS_SHARING_TYPE)Data) == WdfProcessSharingDisabled) {
1872             DeviceRegInfo->IsHostProcessSharingDisabled = TRUE;
1873         }
1874     }
1875     else if (ERROR_FILE_NOT_FOUND != Err) {
1876         DoTraceLevelMessage(GetDriverGlobals(), TRACE_LEVEL_ERROR, TRACINGPNP,
1877                      "Failed to read method neither action value in registry");
1878     }
1879 
1880     //
1881     // Read Group ID
1882     //
1883     buffer = NULL;
1884     bufferSize = 0;
1885     *GroupId = NULL;
1886 
1887     Err = RegQueryValueEx(wudfKey,
1888                           FX_DEVICE_GROUP_ID,
1889                           0,
1890                           &type,
1891                           (LPBYTE) buffer,
1892                           &bufferSize);
1893     if (ERROR_MORE_DATA == Err) {
1894 
1895         buffer = new WCHAR[bufferSize/sizeof(buffer[0])];
1896         if (buffer == NULL) {
1897             Err = ERROR_NOT_ENOUGH_MEMORY;
1898             DoTraceLevelMessage(GetDriverGlobals(), TRACE_LEVEL_ERROR, TRACINGPNP,
1899                          "Failed to allocate memory for string buffer");
1900         }
1901         else {
1902 
1903             buffer[0] = L'\0';
1904             Err = RegQueryValueEx(wudfKey,
1905                                   FX_DEVICE_GROUP_ID,
1906                                   0,
1907                                   &type,
1908                                   (LPBYTE) buffer,
1909                                   &bufferSize);
1910             if (Err == ERROR_SUCCESS) {
1911                 if (type != REG_SZ) {
1912                     Err = ERROR_INVALID_PARAMETER;
1913                 }
1914                 else {
1915                     //
1916                     // according to the string data returned by RegQueryValueEx()
1917                     // is not always null terminated.
1918                     //
1919                     buffer[bufferSize/sizeof(buffer[0]) - 1] = L'\0';
1920                 }
1921             }
1922 
1923             if (Err == ERROR_SUCCESS) {
1924                 *GroupId = buffer;
1925             }
1926             else {
1927                 delete [] buffer;
1928                 buffer = NULL;
1929             }
1930         }
1931     }
1932     else if (ERROR_FILE_NOT_FOUND != Err) {
1933         DoTraceLevelMessage(GetDriverGlobals(), TRACE_LEVEL_ERROR, TRACINGPNP,
1934                      "Failed to read Group id value in registry");
1935     }
1936 
1937 
1938 clean0:
1939 
1940     if (NULL != wudfKey) {
1941         RegCloseKey(wudfKey);
1942     }
1943 
1944     return;
1945 }
1946 
1947 _Must_inspect_result_
1948 NTSTATUS
OpenDevicemapKeyWorker(_In_ PFX_DRIVER_GLOBALS pFxDriverGlobals,_In_ PCUNICODE_STRING KeyName,_In_ ACCESS_MASK DesiredAccess,_In_ FxRegKey * pKey)1949 FxDevice::OpenDevicemapKeyWorker(
1950     _In_ PFX_DRIVER_GLOBALS pFxDriverGlobals,
1951     _In_ PCUNICODE_STRING KeyName,
1952     _In_ ACCESS_MASK DesiredAccess,
1953     _In_ FxRegKey* pKey
1954     )
1955 {
1956 
1957     NTSTATUS status;
1958     HANDLE hKey = NULL;
1959 
1960     status = _OpenDeviceRegistryKey(pFxDriverGlobals,
1961                                     m_DevStack,
1962                                     KeyName->Buffer,
1963                                     FX_PLUGPLAY_REGKEY_DEVICEMAP,
1964                                     DesiredAccess,
1965                                     &hKey);
1966     if (NT_SUCCESS(status)) {
1967         pKey->SetHandle(hKey);
1968     }
1969 
1970     return status;
1971 }
1972 
1973