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