Reactos
1/*++
2
3Copyright (c) Microsoft Corporation
4
5Module Name:
6
7 FxRegistryAPI.cpp
8
9Abstract:
10
11 This module implements registry access in the framework
12
13Author:
14
15
16
17Environment:
18
19 Both kernel and user mode
20
21Revision History:
22
23--*/
24
25#include "fxsupportpch.hpp"
26
27extern "C" {
28// #include "FxRegistryAPI.tmh"
29#define RtlSizeTToULong RtlULongPtrToULong
30}
31
32extern "C" {
33//
34// Not in a public header that we can reach, but is documented
35//
36NTSYSAPI
37NTSTATUS
38NTAPI
39ZwDeleteValueKey(
40 __in IN HANDLE Key,
41 __in IN PUNICODE_STRING ValueName
42 );
43}
44
45
46//
47// Extern "C" the entire file
48//
49extern "C" {
50
51_Must_inspect_result_
52__drv_maxIRQL(PASSIVE_LEVEL)
53NTSTATUS
54NTAPI
55WDFEXPORT(WdfRegistryOpenKey)(
56 __in
57 PWDF_DRIVER_GLOBALS DriverGlobals,
58 __in_opt
59 WDFKEY ParentKey,
60 __in
61 PCUNICODE_STRING KeyName,
62 __in
63 ACCESS_MASK DesiredAccess,
64 __in_opt
65 PWDF_OBJECT_ATTRIBUTES KeyAttributes,
66 __out
67 WDFKEY* Key
68 )
69{
70 DDI_ENTRY();
71
72 FxRegKey* pKey;
73 PFX_DRIVER_GLOBALS pFxDriverGlobals;
74 NTSTATUS status;
75 WDFKEY keyHandle;
76 HANDLE parentHandle;
77
78 pFxDriverGlobals = GetFxDriverGlobals(DriverGlobals);
79 keyHandle = NULL;
80
81 if (ParentKey != NULL) {
82 FxRegKey* pParent;
83
84 FxObjectHandleGetPtrAndGlobals(pFxDriverGlobals,
85 ParentKey,
86 FX_TYPE_REG_KEY,
87 (PVOID*) &pParent,
88 &pFxDriverGlobals);
89
90 parentHandle = pParent->GetHandle();
91 }
92 else {
93 parentHandle = NULL;
94
95 //
96 // Get the parent's globals if it is present
97 //
98 if (NT_SUCCESS(FxValidateObjectAttributesForParentHandle(pFxDriverGlobals,
99 KeyAttributes))) {
100 FxObject* pParent;
101
102 FxObjectHandleGetPtrAndGlobals(pFxDriverGlobals,
103 KeyAttributes->ParentObject,
104 FX_TYPE_OBJECT,
105 (PVOID*)&pParent,
106 &pFxDriverGlobals);
107 }
108 }
109
110 FxPointerNotNull(pFxDriverGlobals, KeyName);
111 FxPointerNotNull(pFxDriverGlobals, Key);
112
113 *Key = NULL;
114
115 status = FxVerifierCheckIrqlLevel(pFxDriverGlobals, PASSIVE_LEVEL);
116 if (!NT_SUCCESS(status)) {
117 return status;
118 }
119
120 status = FxValidateObjectAttributes(pFxDriverGlobals, KeyAttributes);
121 if (!NT_SUCCESS(status)) {
122 return status;
123 }
124
125 status = FxValidateUnicodeString(pFxDriverGlobals, KeyName);
126 if (!NT_SUCCESS(status)) {
127 return status;
128 }
129
130 pKey = new (pFxDriverGlobals, KeyAttributes) FxRegKey(pFxDriverGlobals);
131 if (pKey == NULL) {
132 status = STATUS_INSUFFICIENT_RESOURCES;
133
134 DoTraceLevelMessage(
135 pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGERROR,
136 "Could not allocate memory for a WDFKEY, %!STATUS!", status);
137
138 return status;
139 }
140
141 status = pKey->Commit(KeyAttributes, (WDFOBJECT*)&keyHandle);
142
143 if (NT_SUCCESS(status)) {
144 status = pKey->Open(parentHandle, KeyName, DesiredAccess);
145
146 if (NT_SUCCESS(status)) {
147 *Key = keyHandle;
148 }
149 else {
150 DoTraceLevelMessage(
151 pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGERROR,
152 "new WDFKEY object open failed, %!STATUS!", status);
153 }
154 }
155
156 if (!NT_SUCCESS(status)) {
157 pKey->DeleteFromFailedCreate();
158 pKey = NULL;
159 }
160
161 return status;
162}
163
164_Must_inspect_result_
165__drv_maxIRQL(PASSIVE_LEVEL)
166NTSTATUS
167NTAPI
168WDFEXPORT(WdfRegistryCreateKey)(
169 __in
170 PWDF_DRIVER_GLOBALS DriverGlobals,
171 __in_opt
172 WDFKEY ParentKey,
173 __in
174 PCUNICODE_STRING KeyName,
175 __in
176 ACCESS_MASK DesiredAccess,
177 __in
178 ULONG CreateOptions,
179 __out_opt
180 PULONG CreateDisposition,
181 __in_opt
182 PWDF_OBJECT_ATTRIBUTES KeyAttributes,
183 __out
184 WDFKEY* Key
185 )
186{
187 DDI_ENTRY();
188
189 PFX_DRIVER_GLOBALS pFxDriverGlobals;
190 FxRegKey* pKey;
191 NTSTATUS status;
192 WDFKEY keyHandle;
193 HANDLE parentHandle;
194
195 pFxDriverGlobals = GetFxDriverGlobals(DriverGlobals);
196
197 if (ParentKey != NULL) {
198 FxRegKey* pParent;
199
200 FxObjectHandleGetPtrAndGlobals(pFxDriverGlobals,
201 ParentKey,
202 FX_TYPE_REG_KEY,
203 (PVOID*) &pParent,
204 &pFxDriverGlobals);
205
206 parentHandle = pParent->GetHandle();
207 }
208 else {
209 parentHandle = NULL;
210
211 //
212 // Get the parent's globals if it is present
213 //
214 if (NT_SUCCESS(FxValidateObjectAttributesForParentHandle(pFxDriverGlobals,
215 KeyAttributes))) {
216 FxObject* pParent;
217
218 FxObjectHandleGetPtrAndGlobals(pFxDriverGlobals,
219 KeyAttributes->ParentObject,
220 FX_TYPE_OBJECT,
221 (PVOID*)&pParent,
222 &pFxDriverGlobals);
223 }
224 }
225
226 FxPointerNotNull(pFxDriverGlobals, KeyName);
227 FxPointerNotNull(pFxDriverGlobals, Key);
228
229 *Key = NULL;
230 keyHandle = NULL;
231
232 status = FxVerifierCheckIrqlLevel(pFxDriverGlobals, PASSIVE_LEVEL);
233 if (!NT_SUCCESS(status)) {
234 return status;
235 }
236
237 status = FxValidateObjectAttributes(pFxDriverGlobals, KeyAttributes);
238 if (!NT_SUCCESS(status)) {
239 return status;
240 }
241
242 status = FxValidateUnicodeString(pFxDriverGlobals, KeyName);
243 if (!NT_SUCCESS(status)) {
244 return status;
245 }
246
247 pKey = new (pFxDriverGlobals, KeyAttributes) FxRegKey(pFxDriverGlobals);
248
249 if (pKey == NULL) {
250 status = STATUS_INSUFFICIENT_RESOURCES;
251 DoTraceLevelMessage(
252 pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGERROR,
253 "Could not allocate memory for WDFKEY, %!STATUS!", status);
254
255 return status;
256 }
257
258 status = pKey->Commit(KeyAttributes, (WDFOBJECT*)&keyHandle);
259
260 if (NT_SUCCESS(status)) {
261 status = pKey->Create(parentHandle,
262 KeyName,
263 DesiredAccess,
264 CreateOptions,
265 CreateDisposition);
266
267 if (NT_SUCCESS(status)) {
268 *Key = keyHandle;
269 }
270 else {
271 DoTraceLevelMessage(
272 pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGERROR,
273 "Registry key creation failed, %!STATUS!", status);
274 }
275 }
276
277 if (!NT_SUCCESS(status)) {
278 pKey->DeleteFromFailedCreate();
279 pKey = NULL;
280 }
281
282 return status;
283}
284
285__drv_maxIRQL(PASSIVE_LEVEL)
286VOID
287NTAPI
288WDFEXPORT(WdfRegistryClose)(
289 __in
290 PWDF_DRIVER_GLOBALS DriverGlobals,
291 __in
292 WDFKEY Key
293 )
294{
295 DDI_ENTRY();
296
297 PFX_DRIVER_GLOBALS pFxDriverGlobals;
298 FxRegKey* pKey;
299 NTSTATUS status;
300
301 FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals),
302 Key,
303 FX_TYPE_REG_KEY,
304 (PVOID*) &pKey,
305 &pFxDriverGlobals);
306
307 status = FxVerifierCheckIrqlLevel(pFxDriverGlobals, PASSIVE_LEVEL);
308 if (!NT_SUCCESS(status)) {
309 FxVerifierDbgBreakPoint(pFxDriverGlobals);
310 return;
311 }
312
313 pKey->Close();
314
315 pKey->DeleteObject();
316}
317
318__drv_maxIRQL(PASSIVE_LEVEL)
319HANDLE
320NTAPI
321WDFEXPORT(WdfRegistryWdmGetHandle)(
322 __in
323 PWDF_DRIVER_GLOBALS DriverGlobals,
324 __in
325 WDFKEY Key
326 )
327{
328 DDI_ENTRY();
329
330 FxRegKey* pKey;
331
332 FxObjectHandleGetPtr(GetFxDriverGlobals(DriverGlobals),
333 Key,
334 FX_TYPE_REG_KEY,
335 (PVOID*) &pKey);
336
337 return pKey->GetHandle();
338}
339
340_Must_inspect_result_
341__drv_maxIRQL(PASSIVE_LEVEL)
342NTSTATUS
343NTAPI
344WDFEXPORT(WdfRegistryRemoveKey)(
345 __in
346 PWDF_DRIVER_GLOBALS DriverGlobals,
347 __in
348 WDFKEY Key
349 )
350{
351 DDI_ENTRY();
352
353 PFX_DRIVER_GLOBALS pFxDriverGlobals;
354 FxRegKey* pKey;
355 NTSTATUS status;
356
357 FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals),
358 Key,
359 FX_TYPE_REG_KEY,
360 (PVOID*) &pKey,
361 &pFxDriverGlobals);
362
363 status = FxVerifierCheckIrqlLevel(pFxDriverGlobals, PASSIVE_LEVEL);
364 if (!NT_SUCCESS(status)) {
365 return status;
366 }
367
368 status = Mx::MxDeleteKey(pKey->GetHandle());
369
370 if (NT_SUCCESS(status)) {
371 //
372 // pKey->GetHandle() is now useless, delete the Fx object
373 //
374 pKey->DeleteObject();
375 }
376
377 return status;
378}
379
380_Must_inspect_result_
381__drv_maxIRQL(PASSIVE_LEVEL)
382NTSTATUS
383NTAPI
384WDFEXPORT(WdfRegistryRemoveValue)(
385 __in
386 PWDF_DRIVER_GLOBALS DriverGlobals,
387 __in
388 WDFKEY Key,
389 __in
390 PCUNICODE_STRING ValueName
391 )
392{
393 DDI_ENTRY();
394
395 PFX_DRIVER_GLOBALS pFxDriverGlobals;
396 FxRegKey* pKey;
397 NTSTATUS status;
398
399 FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals),
400 Key,
401 FX_TYPE_REG_KEY,
402 (PVOID*) &pKey,
403 &pFxDriverGlobals);
404
405 status = FxVerifierCheckIrqlLevel(pFxDriverGlobals, PASSIVE_LEVEL);
406 if (!NT_SUCCESS(status)) {
407 return status;
408 }
409
410 status = FxValidateUnicodeString(pFxDriverGlobals, ValueName);
411 if (!NT_SUCCESS(status)) {
412 return status;
413 }
414
415 FxPointerNotNull(pFxDriverGlobals, ValueName);
416
417 status = ZwDeleteValueKey(pKey->GetHandle(), (PUNICODE_STRING) ValueName);
418
419 return status;
420}
421
422_Must_inspect_result_
423__drv_maxIRQL(PASSIVE_LEVEL)
424NTSTATUS
425NTAPI
426WDFEXPORT(WdfRegistryQueryValue)(
427 __in
428 PWDF_DRIVER_GLOBALS DriverGlobals,
429 __in
430 WDFKEY Key,
431 __in
432 PCUNICODE_STRING ValueName,
433 __in
434 ULONG ValueLength,
435 __out_bcount_opt( ValueLength)
436 PVOID Value,
437 __out_opt
438 PULONG ValueLengthQueried,
439 __out_opt
440 PULONG ValueType
441 )
442{
443 DDI_ENTRY();
444
445 PFX_DRIVER_GLOBALS pFxDriverGlobals;
446 FxRegKey* pKey;
447 NTSTATUS status;
448
449 FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals),
450 Key,
451 FX_TYPE_REG_KEY,
452 (PVOID*) &pKey,
453 &pFxDriverGlobals);
454
455 FxPointerNotNull(pFxDriverGlobals, ValueName);
456
457 status = FxVerifierCheckIrqlLevel(pFxDriverGlobals, PASSIVE_LEVEL);
458 if (!NT_SUCCESS(status)) {
459 return status;
460 }
461
462 status = FxValidateUnicodeString(pFxDriverGlobals, ValueName);
463 if (!NT_SUCCESS(status)) {
464 return status;
465 }
466
467 status = FxRegKey::_QueryValue(pFxDriverGlobals,
468 pKey->GetHandle(),
469 ValueName,
470 ValueLength,
471 Value,
472 ValueLengthQueried,
473 ValueType);
474 if (!NT_SUCCESS(status)) {
475 UCHAR traceLevel = TRACE_LEVEL_ERROR;
476
477 //
478 // Label message as Verbose if this is the known pattern of
479 // passing a 0-length NULL buffer to query the required buffer size.
480 //
481 if (status == STATUS_BUFFER_OVERFLOW && Value == NULL && ValueLength == 0) {
482 traceLevel = TRACE_LEVEL_VERBOSE;
483 }
484
485 DoTraceLevelMessage(pFxDriverGlobals, traceLevel, TRACINGERROR,
486 "WDFKEY %p QueryValue failed, %!STATUS!",
487 Key, status);
488 }
489
490 return status;
491}
492
493_Must_inspect_result_
494__drv_maxIRQL(PASSIVE_LEVEL)
495NTSTATUS
496NTAPI
497WDFEXPORT(WdfRegistryQueryMemory)(
498 __in
499 PWDF_DRIVER_GLOBALS DriverGlobals,
500 __in
501 WDFKEY Key,
502 __in
503 PCUNICODE_STRING ValueName,
504 __in
505 __drv_strictTypeMatch( 1)
506 POOL_TYPE PoolType,
507 __in_opt
508 PWDF_OBJECT_ATTRIBUTES MemoryAttributes,
509 __out
510 WDFMEMORY* Memory,
511 __out_opt
512 PULONG ValueType
513 )
514{
515 DDI_ENTRY();
516
517 FxRegKey* pKey;
518 PFX_DRIVER_GLOBALS pFxDriverGlobals;
519 NTSTATUS status;
520 ULONG dataLength;
521 PVOID dataBuffer;
522
523 FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals),
524 Key,
525 FX_TYPE_REG_KEY,
526 (PVOID*) &pKey,
527 &pFxDriverGlobals);
528
529 FxPointerNotNull(pFxDriverGlobals, ValueName);
530 FxPointerNotNull(pFxDriverGlobals, Memory);
531
532 *Memory = NULL;
533
534 status = FxVerifierCheckIrqlLevel(pFxDriverGlobals, PASSIVE_LEVEL);
535 if (!NT_SUCCESS(status)) {
536 return status;
537 }
538
539 FxVerifierCheckNxPoolType(pFxDriverGlobals, PoolType, pFxDriverGlobals->Tag);
540
541 status = FxValidateObjectAttributes(pFxDriverGlobals, MemoryAttributes);
542 if (!NT_SUCCESS(status)) {
543 return status;
544 }
545
546 status = FxValidateUnicodeString(pFxDriverGlobals, ValueName);
547 if (!NT_SUCCESS(status)) {
548 return status;
549 }
550
551 //
552 // Query the buffer length required.
553 //
554 status = pKey->QueryValue(ValueName, 0, NULL, &dataLength, NULL);
555 if (!NT_SUCCESS(status) && status != STATUS_BUFFER_OVERFLOW) {
556 return status;
557 }
558
559 dataBuffer = FxPoolAllocate(pFxDriverGlobals, PagedPool, dataLength);
560 if (dataBuffer == NULL) {
561 status = STATUS_INSUFFICIENT_RESOURCES;
562
563 DoTraceLevelMessage(
564 pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGERROR,
565 "WDFKEY %p KEY_VALUE_PARTIAL_INFORMATION allocation failed, %!STATUS!",
566 Key, status);
567
568 return status;
569 }
570
571 status = pKey->QueryValue(ValueName, dataLength, dataBuffer, &dataLength, ValueType);
572 if (NT_SUCCESS(status)) {
573 FxMemoryObject* pObject;
574
575 status = FxMemoryObject::_Create(pFxDriverGlobals,
576 MemoryAttributes,
577 PoolType,
578 pFxDriverGlobals->Tag,
579 dataLength,
580 &pObject);
581
582 if (NT_SUCCESS(status)) {
583 status = pObject->Commit(MemoryAttributes, (WDFOBJECT*) Memory);
584
585 if (NT_SUCCESS(status)) {
586 RtlCopyMemory(pObject->GetBuffer(),
587 dataBuffer,
588 dataLength);
589 }
590 else {
591 pObject->DeleteFromFailedCreate();
592 }
593 }
594 else {
595 DoTraceLevelMessage(
596 pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGERROR,
597 "WDFKEY %p WDFMEMORY object create failed, %!STATUS!",
598 Key, status);
599 }
600 }
601 else {
602 DoTraceLevelMessage( pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGERROR,
603 "WDFKEY %p QueryPartial failed, %!STATUS!",
604 Key, status);
605 }
606
607 FxPoolFree(dataBuffer);
608
609 return status;
610}
611
612_Must_inspect_result_
613__drv_maxIRQL(PASSIVE_LEVEL)
614NTSTATUS
615NTAPI
616WDFEXPORT(WdfRegistryQueryMultiString)(
617 __in
618 PWDF_DRIVER_GLOBALS DriverGlobals,
619 __in
620 WDFKEY Key,
621 __in
622 PCUNICODE_STRING ValueName,
623 __in_opt
624 PWDF_OBJECT_ATTRIBUTES StringsAttributes,
625 __in
626 WDFCOLLECTION Collection
627 )
628{
629 DDI_ENTRY();
630
631 PFX_DRIVER_GLOBALS pFxDriverGlobals;
632 FxDeviceBase* pDeviceBase;
633 FxCollection* pCollection;
634 FxRegKey* pKey;
635 NTSTATUS status;
636 ULONG dataLength, type;
637 PVOID dataBuffer;
638
639 FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals),
640 Key,
641 FX_TYPE_REG_KEY,
642 (PVOID*) &pKey,
643 &pFxDriverGlobals);
644
645 pDeviceBase = NULL;
646
647 FxPointerNotNull(pFxDriverGlobals, ValueName);
648 FxPointerNotNull(pFxDriverGlobals, Collection);
649
650 status = FxValidateObjectAttributes(pFxDriverGlobals, StringsAttributes);
651 if (!NT_SUCCESS(status)) {
652 return status;
653 }
654
655 status = FxVerifierCheckIrqlLevel(pFxDriverGlobals, PASSIVE_LEVEL);
656 if (!NT_SUCCESS(status)) {
657 return status;
658 }
659
660 status = FxValidateUnicodeString(pFxDriverGlobals, ValueName);
661 if (!NT_SUCCESS(status)) {
662 return status;
663 }
664
665 FxObjectHandleGetPtr(pFxDriverGlobals,
666 Collection,
667 FX_TYPE_COLLECTION,
668 (PVOID*) &pCollection);
669
670 pDeviceBase = FxDeviceBase::_SearchForDevice(pFxDriverGlobals,
671 StringsAttributes);
672
673 status = pKey->QueryValue(ValueName, 0, NULL, &dataLength, &type);
674 if (!NT_SUCCESS(status) && status != STATUS_BUFFER_OVERFLOW) {
675 DoTraceLevelMessage(
676 pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGERROR,
677 "WDFKEY %p QueryPartial failed: %!STATUS!", Key, status);
678
679 return status;
680 }
681
682 if (type != REG_MULTI_SZ) {
683 return STATUS_OBJECT_TYPE_MISMATCH;
684 }
685
686 dataBuffer = FxPoolAllocate(pFxDriverGlobals, PagedPool, dataLength);
687 if (dataBuffer == NULL) {
688 status = STATUS_INSUFFICIENT_RESOURCES;
689
690 DoTraceLevelMessage(
691 pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGERROR,
692 "WDFKEY %p KEY_VALUE_PARTIAL_INFORMATION allocation failed, %!STATUS!",
693 Key, status);
694
695 return status;
696 }
697
698 status = pKey->QueryValue(ValueName, dataLength, dataBuffer, &dataLength, &type);
699 if (NT_SUCCESS(status)) {
700 //
701 // Verify that the data from the registry is a valid multi-sz string.
702 //
703 status = FxRegKey::_VerifyMultiSzString(pFxDriverGlobals,
704 ValueName,
705 (PWCHAR) dataBuffer,
706 dataLength);
707 }
708
709 if (NT_SUCCESS(status)) {
710 ULONG initialCount;
711 PWCHAR pCur;
712
713 initialCount = pCollection->Count();
714 pCur = (PWCHAR) dataBuffer;
715
716 while (*pCur != UNICODE_NULL) {
717 FxString* pString;
718
719 pString = new (pFxDriverGlobals, StringsAttributes)
720 FxString(pFxDriverGlobals);
721
722 if (pString != NULL) {
723 if (pDeviceBase != NULL) {
724 pString->SetDeviceBase(pDeviceBase);
725 }
726
727 status = pString->Assign(pCur);
728
729 if (NT_SUCCESS(status)) {
730 WDFOBJECT dummy;
731
732 status = pString->Commit(StringsAttributes, &dummy);
733 }
734
735 if (NT_SUCCESS(status)) {
736 if (pCollection->Add(pString) == FALSE) {
737 status = STATUS_INSUFFICIENT_RESOURCES;
738
739 DoTraceLevelMessage(
740 pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGERROR,
741 "WDFKEY %p, WDFCOLLECTION %p, collection add failed "
742 "%!STATUS!", Key, Collection, status);
743 }
744 }
745
746 if (!NT_SUCCESS(status)) {
747 //
748 // Delete the string we just created
749 //
750 pString->DeleteFromFailedCreate();
751 }
752 else {
753 //
754 // NT_SUCCES(status)
755 //
756 // Either the caller is responsible for freeing the
757 // WDFSTRING or it has been parented to another object.
758 //
759 DO_NOTHING();
760 }
761 }
762 else {
763 status = STATUS_INSUFFICIENT_RESOURCES;
764 }
765
766 if (!NT_SUCCESS(status)) {
767 DoTraceLevelMessage(
768 pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGERROR,
769 "WDFKEY %p: WDFSTRING creation failed: %!STATUS!",
770 Key, status);
771 break;
772 }
773
774 //
775 // Increment to the next string in the multi sz (length of string +
776 // 1 for the NULL)
777 //
778 pCur += wcslen(pCur) + 1;
779 }
780
781 if (!NT_SUCCESS(status)) {
782 //
783 // Clear out all the items we added to the collection
784 //
785 while (pCollection->Count() > initialCount) {
786 pCollection->Remove(initialCount);
787 }
788 }
789 }
790
791 FxPoolFree(dataBuffer);
792
793 return status;
794}
795
796_Must_inspect_result_
797__drv_maxIRQL(PASSIVE_LEVEL)
798NTSTATUS
799NTAPI
800WDFEXPORT(WdfRegistryQueryUnicodeString)(
801 __in
802 PWDF_DRIVER_GLOBALS DriverGlobals,
803 __in
804 WDFKEY Key,
805 __in
806 PCUNICODE_STRING ValueName,
807 __out_opt
808 PUSHORT ValueByteLength,
809 __inout_opt
810 PUNICODE_STRING Value
811 )
812{
813 DDI_ENTRY();
814
815 PFX_DRIVER_GLOBALS pFxDriverGlobals;
816 FxRegKey* pKey;
817 NTSTATUS status;
818 ULONG dataLength, type;
819 PVOID dataBuffer;
820
821 FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals),
822 Key,
823 FX_TYPE_REG_KEY,
824 (PVOID*) &pKey,
825 &pFxDriverGlobals);
826
827 FxPointerNotNull(pFxDriverGlobals, ValueName);
828
829 status = FxVerifierCheckIrqlLevel(pFxDriverGlobals, PASSIVE_LEVEL);
830 if (!NT_SUCCESS(status)) {
831 return status;
832 }
833
834 status = FxValidateUnicodeString(pFxDriverGlobals, ValueName);
835 if (!NT_SUCCESS(status)) {
836 return status;
837 }
838
839 if (Value != NULL) {
840 status = FxValidateUnicodeString(pFxDriverGlobals, Value);
841 if (!NT_SUCCESS(status)) {
842 return status;
843 }
844 }
845
846 if (Value == NULL) {
847 //
848 // Caller wants to know just the length
849 //
850 dataLength = 0;
851 dataBuffer = NULL;
852 }
853 else {
854 dataLength = Value->MaximumLength;
855 dataBuffer = FxPoolAllocate(pFxDriverGlobals, PagedPool, dataLength);
856
857 if (dataBuffer == NULL) {
858 status = STATUS_INSUFFICIENT_RESOURCES;
859
860 DoTraceLevelMessage(
861 pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGERROR,
862 "WDFKEY %p KEY_VALUE_PARTIAL_INFORMATION allocation failed, "
863 "%!STATUS!", Key, status);
864
865 return status;
866 }
867 }
868
869 status = pKey->QueryValue(ValueName, dataLength, dataBuffer, &dataLength, &type);
870 if (NT_SUCCESS(status) &&
871 FxRegKey::_IsValidSzType(type) == FALSE) {
872 status = STATUS_OBJECT_TYPE_MISMATCH;
873 }
874
875 //
876 // Set ValueByteLength before doing the copy
877 //
878 if (NT_SUCCESS(status) || status == STATUS_BUFFER_OVERFLOW) {
879 //
880 // pPartial->DataLength is in bytes, convert to number of
881 // WCHARs
882 //
883 if (ValueByteLength != NULL) {
884 *ValueByteLength = (USHORT)dataLength ;
885 }
886 }
887
888 if (NT_SUCCESS(status) && Value != NULL) {
889
890
891
892
893 ASSERT(ValueByteLength == NULL ||
894 *ValueByteLength >= dataLength);
895
896 //
897 // pPartial->DataLength cannot be greater than Value->MaximumLength
898 // based on the call to _ComputePartialSize above. So it is safe to
899 // copy the pPartial data buffer to the Value buffer.
900 //
901 __analysis_assume(dataLength <= Value->MaximumLength);
902 RtlCopyMemory(Value->Buffer, dataBuffer, dataLength);
903
904 //terminating null shouldn't be included in the Length
905 Value->Length = (USHORT)dataLength;
906
907 if (Value->Buffer[Value->Length/sizeof(WCHAR)-1] == UNICODE_NULL) {
908 Value->Length -= sizeof(WCHAR);
909 }
910 }
911
912 if (dataBuffer != NULL) {
913 FxPoolFree(dataBuffer);
914 }
915
916 return status;
917}
918
919_Must_inspect_result_
920__drv_maxIRQL(PASSIVE_LEVEL)
921NTSTATUS
922NTAPI
923WDFEXPORT(WdfRegistryQueryString)(
924 __in
925 PWDF_DRIVER_GLOBALS DriverGlobals,
926 __in
927 WDFKEY Key,
928 __in
929 PCUNICODE_STRING ValueName,
930 __in
931 WDFSTRING String
932 )
933{
934 DDI_ENTRY();
935
936 PFX_DRIVER_GLOBALS pFxDriverGlobals;
937 FxString* pString;
938 FxRegKey* pKey;
939 NTSTATUS status;
940 ULONG dataLength, type;
941 PVOID dataBuffer;
942
943 FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals),
944 Key,
945 FX_TYPE_REG_KEY,
946 (PVOID*) &pKey,
947 &pFxDriverGlobals);
948
949 FxPointerNotNull(pFxDriverGlobals, ValueName);
950 FxPointerNotNull(pFxDriverGlobals, String);
951
952 status = FxVerifierCheckIrqlLevel(pFxDriverGlobals, PASSIVE_LEVEL);
953 if (!NT_SUCCESS(status)) {
954 return status;
955 }
956
957 status = FxValidateUnicodeString(pFxDriverGlobals, ValueName);
958 if (!NT_SUCCESS(status)) {
959 return status;
960 }
961
962 FxObjectHandleGetPtr(pFxDriverGlobals,
963 String,
964 FX_TYPE_STRING,
965 (PVOID*) &pString);
966
967 status = pKey->QueryValue(ValueName, 0, NULL, &dataLength, &type);
968 if (NT_SUCCESS(status) &&
969 FxRegKey::_IsValidSzType(type) == FALSE) {
970 status = STATUS_OBJECT_TYPE_MISMATCH;
971 }
972
973 if (!NT_SUCCESS(status) && status != STATUS_BUFFER_OVERFLOW) {
974 DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGERROR,
975 "WDFKEY %p, QueryPartial failed, %!STATUS!",
976 Key, status);
977 return status;
978 }
979
980 dataBuffer = FxPoolAllocate(pFxDriverGlobals, PagedPool, dataLength);
981 if (dataBuffer == NULL) {
982 status = STATUS_INSUFFICIENT_RESOURCES;
983
984 DoTraceLevelMessage(
985 pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGERROR,
986 "WDFKEY %p KEY_VALUE_PARTIAL_INFORMATION allocation failed, "
987 "%!STATUS!", Key, status);
988
989 return status;
990 }
991
992 status = pKey->QueryValue(ValueName, dataLength, dataBuffer, &dataLength, &type);
993 if (NT_SUCCESS(status) &&
994 FxRegKey::_IsValidSzType(type) == FALSE) {
995 status = STATUS_OBJECT_TYPE_MISMATCH;
996 }
997
998 if (NT_SUCCESS(status)) {
999 if (dataLength <= USHORT_MAX) {
1000 UNICODE_STRING tmp;
1001
1002 if (dataLength == 0x0) {
1003 //
1004 // Empty string
1005 //
1006 tmp.Buffer = L"";
1007 tmp.Length = 0;
1008 tmp.MaximumLength = 0;
1009 }
1010 else {
1011
1012 //
1013 // The string we read may not be NULL terminated, so put it into a
1014 // UNICODE_STRING. If the final character is NULL, shorten the
1015 // length of the string so that it does not include for the NULL.
1016 //
1017 // If there are embedded NULLs in the string previous to the final
1018 // character, we leave them in place.
1019 //
1020 tmp.Buffer = (PWCHAR) dataBuffer;
1021 tmp.Length = (USHORT) dataLength;
1022 tmp.MaximumLength = tmp.Length;
1023
1024 if (tmp.Buffer[(tmp.Length/sizeof(WCHAR))-1] == UNICODE_NULL) {
1025 //
1026 // Do not include the UNICODE_NULL in the length
1027 //
1028 tmp.Length -= sizeof(WCHAR);
1029 }
1030 }
1031
1032 status = pString->Assign(&tmp);
1033 }
1034 else {
1035 status = STATUS_INVALID_BUFFER_SIZE;
1036
1037 DoTraceLevelMessage(
1038 pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGERROR,
1039 "WDFKEY %p QueryPartial failed, Length %d > max %d, %!STATUS!",
1040 Key, dataLength, USHORT_MAX, status);
1041 }
1042 }
1043 else {
1044 DoTraceLevelMessage(
1045 pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGERROR,
1046 "WDFKEY %p QueryPartial failed, Length %d, %!STATUS!",
1047 Key, dataLength, status);
1048 }
1049
1050 FxPoolFree(dataBuffer);
1051
1052 return status;
1053}
1054
1055_Must_inspect_result_
1056__drv_maxIRQL(PASSIVE_LEVEL)
1057NTSTATUS
1058NTAPI
1059WDFEXPORT(WdfRegistryQueryULong)(
1060 __in
1061 PWDF_DRIVER_GLOBALS DriverGlobals,
1062 __in
1063 WDFKEY Key,
1064 __in
1065 PCUNICODE_STRING ValueName,
1066 __out
1067 PULONG Value
1068 )
1069{
1070 DDI_ENTRY();
1071
1072 PFX_DRIVER_GLOBALS pFxDriverGlobals;
1073 FxRegKey* pKey;
1074 NTSTATUS status;
1075
1076 FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals),
1077 Key,
1078 FX_TYPE_REG_KEY,
1079 (PVOID*) &pKey,
1080 &pFxDriverGlobals);
1081
1082 FxPointerNotNull(pFxDriverGlobals, ValueName);
1083 FxPointerNotNull(pFxDriverGlobals, Value);
1084
1085 status = FxVerifierCheckIrqlLevel(pFxDriverGlobals, PASSIVE_LEVEL);
1086 if (!NT_SUCCESS(status)) {
1087 return status;
1088 }
1089
1090 status = FxValidateUnicodeString(pFxDriverGlobals, ValueName);
1091 if (!NT_SUCCESS(status)) {
1092 return status;
1093 }
1094
1095 status = FxRegKey::_QueryULong(pKey->GetHandle(), ValueName, Value);
1096
1097 if (!NT_SUCCESS(status)) {
1098 DoTraceLevelMessage(
1099 pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGERROR,
1100 "WDFKEY %p, QueryULong, %!STATUS!", Key, status);
1101 }
1102
1103 return status;
1104}
1105
1106
1107_Must_inspect_result_
1108__drv_maxIRQL(PASSIVE_LEVEL)
1109NTSTATUS
1110NTAPI
1111WDFEXPORT(WdfRegistryAssignValue)(
1112 __in
1113 PWDF_DRIVER_GLOBALS DriverGlobals,
1114 __in
1115 WDFKEY Key,
1116 __in
1117 PCUNICODE_STRING ValueName,
1118 __in
1119 ULONG ValueType,
1120 __in
1121 ULONG ValueLength,
1122 __in_ecount( ValueLength)
1123 PVOID Value
1124 )
1125{
1126 DDI_ENTRY();
1127
1128 PFX_DRIVER_GLOBALS pFxDriverGlobals;
1129 FxRegKey* pKey;
1130 NTSTATUS status;
1131
1132 FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals),
1133 Key,
1134 FX_TYPE_REG_KEY,
1135 (PVOID*) &pKey,
1136 &pFxDriverGlobals);
1137
1138 FxPointerNotNull(pFxDriverGlobals, ValueName);
1139
1140 status = FxVerifierCheckIrqlLevel(pFxDriverGlobals, PASSIVE_LEVEL);
1141 if (!NT_SUCCESS(status)) {
1142 return status;
1143 }
1144
1145 status = FxValidateUnicodeString(pFxDriverGlobals, ValueName);
1146 if (!NT_SUCCESS(status)) {
1147 return status;
1148 }
1149
1150 status = pKey->SetValue(ValueName, ValueType, Value, ValueLength);
1151
1152 if (!NT_SUCCESS(status)) {
1153 DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGERROR,
1154 "WDFKEY %p SetValue, %!STATUS!", Key, status);
1155 }
1156
1157 return status;
1158}
1159
1160
1161_Must_inspect_result_
1162__drv_maxIRQL(PASSIVE_LEVEL)
1163NTSTATUS
1164NTAPI
1165WDFEXPORT(WdfRegistryAssignMemory)(
1166 __in
1167 PWDF_DRIVER_GLOBALS DriverGlobals,
1168 __in
1169 WDFKEY Key,
1170 __in
1171 PCUNICODE_STRING ValueName,
1172 __in
1173 ULONG ValueType,
1174 __in
1175 WDFMEMORY Memory,
1176 __in_opt
1177 PWDFMEMORY_OFFSET MemoryOffsets
1178 )
1179{
1180 DDI_ENTRY();
1181
1182 PFX_DRIVER_GLOBALS pFxDriverGlobals;
1183 IFxMemory* pMemory;
1184 FxRegKey* pKey;
1185 PVOID pBuffer;
1186 ULONG length;
1187 NTSTATUS status;
1188
1189 FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals),
1190 Key,
1191 FX_TYPE_REG_KEY,
1192 (PVOID*) &pKey,
1193 &pFxDriverGlobals);
1194
1195 FxPointerNotNull(pFxDriverGlobals, ValueName);
1196 FxPointerNotNull(pFxDriverGlobals, Memory);
1197
1198 status = FxVerifierCheckIrqlLevel(pFxDriverGlobals, PASSIVE_LEVEL);
1199 if (!NT_SUCCESS(status)) {
1200 return status;
1201 }
1202
1203 status = FxValidateUnicodeString(pFxDriverGlobals, ValueName);
1204 if (!NT_SUCCESS(status)) {
1205 return status;
1206 }
1207
1208 FxObjectHandleGetPtr(pFxDriverGlobals,
1209 Memory,
1210 IFX_TYPE_MEMORY,
1211 (PVOID*) &pMemory);
1212
1213 pBuffer = pMemory->GetBuffer();
1214 length = (ULONG) pMemory->GetBufferSize();
1215
1216 if (MemoryOffsets != NULL) {
1217 status = pMemory->ValidateMemoryOffsets(MemoryOffsets);
1218
1219 if (!NT_SUCCESS(status)) {
1220 DoTraceLevelMessage(
1221 pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGERROR,
1222 "WDFKEY %p, WDFMEMORY %p Offsets overflowed, %!STATUS!",
1223 Key, Memory, status);
1224
1225 return status;
1226 }
1227
1228 if (MemoryOffsets->BufferLength > 0) {
1229 status = RtlSizeTToULong(MemoryOffsets->BufferLength, &length);
1230
1231 if (!NT_SUCCESS(status)) {
1232 DoTraceLevelMessage(
1233 pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGERROR,
1234 "WDFKEY %p, WDFMEMORY %p BufferLength in Offsets truncated, "
1235 "%!STATUS!", Key, Memory, status);
1236
1237 return status;
1238 }
1239 }
1240
1241 pBuffer = WDF_PTR_ADD_OFFSET(pBuffer, MemoryOffsets->BufferOffset);
1242 }
1243
1244 status = pKey->SetValue(ValueName, ValueType, pBuffer, length);
1245
1246 if (!NT_SUCCESS(status)) {
1247 DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGERROR,
1248 "WDFKEY handle %p SetValue, %!STATUS!", Key, status);
1249 }
1250
1251 return status;
1252}
1253
1254_Must_inspect_result_
1255__drv_maxIRQL(PASSIVE_LEVEL)
1256NTSTATUS
1257NTAPI
1258WDFEXPORT(WdfRegistryAssignULong)(
1259 __in
1260 PWDF_DRIVER_GLOBALS DriverGlobals,
1261 __in
1262 WDFKEY Key,
1263 __in
1264 PCUNICODE_STRING ValueName,
1265 __in
1266 ULONG Value
1267 )
1268{
1269 DDI_ENTRY();
1270
1271 PFX_DRIVER_GLOBALS pFxDriverGlobals;
1272 FxRegKey* pKey;
1273 NTSTATUS status;
1274
1275 FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals),
1276 Key,
1277 FX_TYPE_REG_KEY,
1278 (PVOID*) &pKey,
1279 &pFxDriverGlobals);
1280
1281 FxPointerNotNull(pFxDriverGlobals, ValueName);
1282
1283 status = FxVerifierCheckIrqlLevel(pFxDriverGlobals, PASSIVE_LEVEL);
1284 if (!NT_SUCCESS(status)) {
1285 return status;
1286 }
1287
1288 status = FxValidateUnicodeString(pFxDriverGlobals, ValueName);
1289 if (!NT_SUCCESS(status)) {
1290 return status;
1291 }
1292
1293 status = pKey->SetValue(ValueName, REG_DWORD, &Value, sizeof(Value));
1294
1295 if (!NT_SUCCESS(status)) {
1296 DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGERROR,
1297 "WDFKEY %p SetValue, %!STATUS!",
1298 Key, status);
1299 }
1300
1301 return status;
1302}
1303
1304_Must_inspect_result_
1305__drv_maxIRQL(PASSIVE_LEVEL)
1306NTSTATUS
1307NTAPI
1308WDFEXPORT(WdfRegistryAssignUnicodeString)(
1309 __in
1310 PWDF_DRIVER_GLOBALS DriverGlobals,
1311 __in
1312 WDFKEY Key,
1313 __in
1314 PCUNICODE_STRING ValueName,
1315 __in
1316 PCUNICODE_STRING Value
1317 )
1318{
1319 DDI_ENTRY();
1320
1321 PFX_DRIVER_GLOBALS pFxDriverGlobals;
1322 FxRegKey* pKey;
1323 NTSTATUS status;
1324 PWCHAR tempValueBuf;
1325 ULONG length;
1326
1327 FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals),
1328 Key,
1329 FX_TYPE_REG_KEY,
1330 (PVOID*) &pKey,
1331 &pFxDriverGlobals);
1332
1333 FxPointerNotNull(pFxDriverGlobals, ValueName);
1334 FxPointerNotNull(pFxDriverGlobals, Value);
1335
1336 tempValueBuf = NULL;
1337
1338 status = FxVerifierCheckIrqlLevel(pFxDriverGlobals, PASSIVE_LEVEL);
1339 if (!NT_SUCCESS(status)) {
1340 return status;
1341 }
1342
1343 status = FxValidateUnicodeString(pFxDriverGlobals, ValueName);
1344 if (!NT_SUCCESS(status)) {
1345 return status;
1346 }
1347
1348 status = FxValidateUnicodeString(pFxDriverGlobals, Value);
1349 if (!NT_SUCCESS(status)) {
1350 return status;
1351 }
1352
1353 length = Value->Length + sizeof(UNICODE_NULL);
1354
1355 //
1356 // Buffer must be NULL terminated and Length of the buffer must also include the NULL
1357 // Allocate a temporary buffer and NULL terminate it.
1358 //
1359 tempValueBuf = (PWCHAR) FxPoolAllocate(pFxDriverGlobals, PagedPool, length);
1360
1361 if (tempValueBuf == NULL) {
1362 status = STATUS_INSUFFICIENT_RESOURCES;
1363
1364 DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGERROR,
1365 "WDFKEY %p allocate temporary buffer failed, "
1366 "%!STATUS!", Key, status);
1367
1368 return status;
1369 }
1370
1371 //
1372 // Copy over the string from the callers buffer and make sure it is
1373 // NULL terminated.
1374 //
1375 RtlCopyMemory(tempValueBuf, Value->Buffer, Value->Length);
1376 tempValueBuf[Value->Length/sizeof(WCHAR)] = UNICODE_NULL;
1377
1378 status = pKey->SetValue(ValueName, REG_SZ, tempValueBuf, length);
1379
1380 FxPoolFree(tempValueBuf);
1381
1382 if (!NT_SUCCESS(status)) {
1383 DoTraceLevelMessage( pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGERROR,
1384 "WDFKEY %p set value failed, %!STATUS!",
1385 Key, status);
1386 }
1387
1388 return status;
1389}
1390
1391_Must_inspect_result_
1392__drv_maxIRQL(PASSIVE_LEVEL)
1393NTSTATUS
1394NTAPI
1395WDFEXPORT(WdfRegistryAssignString)(
1396 __in
1397 PWDF_DRIVER_GLOBALS DriverGlobals,
1398 __in
1399 WDFKEY Key,
1400 __in
1401 PCUNICODE_STRING ValueName,
1402 __in
1403 WDFSTRING String
1404 )
1405{
1406 DDI_ENTRY();
1407
1408 PFX_DRIVER_GLOBALS pFxDriverGlobals;
1409 FxString* pString;
1410 FxRegKey* pKey;
1411 NTSTATUS status;
1412
1413 FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals),
1414 Key,
1415 FX_TYPE_REG_KEY,
1416 (PVOID*) &pKey,
1417 &pFxDriverGlobals);
1418
1419 FxPointerNotNull(pFxDriverGlobals, ValueName);
1420 FxPointerNotNull(pFxDriverGlobals, String);
1421
1422 status = FxVerifierCheckIrqlLevel(pFxDriverGlobals, PASSIVE_LEVEL);
1423 if (!NT_SUCCESS(status)) {
1424 return status;
1425 }
1426
1427 status = FxValidateUnicodeString(pFxDriverGlobals, ValueName);
1428 if (!NT_SUCCESS(status)) {
1429 return status;
1430 }
1431
1432 FxObjectHandleGetPtr(pFxDriverGlobals,
1433 String,
1434 FX_TYPE_STRING,
1435 (PVOID*) &pString);
1436
1437 status = pKey->SetValue(ValueName,
1438 REG_SZ,
1439 pString->Buffer(),
1440 pString->ByteLength(TRUE));
1441
1442 if (!NT_SUCCESS(status)) {
1443 DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGERROR,
1444 "WDFKEY handle %p SetValue, %!STATUS!",
1445 Key, status);
1446 }
1447
1448 return status;
1449}
1450
1451_Must_inspect_result_
1452__drv_maxIRQL(PASSIVE_LEVEL)
1453NTSTATUS
1454NTAPI
1455WDFEXPORT(WdfRegistryAssignMultiString)(
1456 __in
1457 PWDF_DRIVER_GLOBALS DriverGlobals,
1458 __in
1459 WDFKEY Key,
1460 __in
1461 PCUNICODE_STRING ValueName,
1462 __in
1463 WDFCOLLECTION StringsCollection
1464 )
1465{
1466 DDI_ENTRY();
1467
1468 PFX_DRIVER_GLOBALS pFxDriverGlobals;
1469 FxCollection* pCollection;
1470 FxRegKey* pKey;
1471 PWCHAR pValue;
1472 NTSTATUS status;
1473 ULONG length;
1474 BOOLEAN valid;
1475
1476 FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals),
1477 Key,
1478 FX_TYPE_REG_KEY,
1479 (PVOID*) &pKey,
1480 &pFxDriverGlobals);
1481
1482 FxPointerNotNull(pFxDriverGlobals, ValueName);
1483 FxPointerNotNull(pFxDriverGlobals, StringsCollection);
1484
1485 status = FxVerifierCheckIrqlLevel(pFxDriverGlobals, PASSIVE_LEVEL);
1486 if (!NT_SUCCESS(status)) {
1487 return status;
1488 }
1489
1490 status = FxValidateUnicodeString(pFxDriverGlobals, ValueName);
1491 if (!NT_SUCCESS(status)) {
1492 return status;
1493 }
1494
1495 FxObjectHandleGetPtr(pFxDriverGlobals,
1496 StringsCollection,
1497 FX_TYPE_COLLECTION,
1498 (PVOID *) &pCollection);
1499
1500 valid = FALSE;
1501
1502 status = RtlSizeTToULong(
1503 FxCalculateTotalStringSize(pCollection, TRUE, &valid),
1504 &length);
1505
1506 if (!NT_SUCCESS(status)) {
1507 DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGERROR,
1508 "WDFCOLLECTION %p, collection too large to fit into "
1509 "a ULONG, %!STATUS!", StringsCollection, status);
1510 return status;
1511 }
1512
1513 if (valid == FALSE) {
1514 status = STATUS_INVALID_PARAMETER;
1515 DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGERROR,
1516 "WDFKEY %p, WDFCOLLECTION %p contains "
1517 "non string objects, %!STATUS!",
1518 Key, StringsCollection, status);
1519 return status;
1520 }
1521
1522 pValue = (PWCHAR) FxPoolAllocate(pFxDriverGlobals, PagedPool, length);
1523
1524 if (pValue == NULL) {
1525 status = STATUS_INSUFFICIENT_RESOURCES;
1526
1527 DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGERROR,
1528 "WDFKEY %p allocate for query buffer failed, "
1529 "%!STATUS!", Key, status);
1530
1531 return status;
1532 }
1533
1534 FxCopyMultiSz(pValue, pCollection);
1535
1536 status = pKey->SetValue(ValueName, REG_MULTI_SZ, pValue, length);
1537
1538 if (!NT_SUCCESS(status)) {
1539 DoTraceLevelMessage( pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGERROR,
1540 "WDFKEY %p SetValue, %!STATUS!",
1541 Key, status);
1542 }
1543
1544 FxPoolFree(pValue);
1545
1546 return status;
1547}
1548
1549} // extern "C"