ReactOS 0.4.15-dev-7924-g5949c20
registry.c
Go to the documentation of this file.
1/*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS system libraries
4 * PURPOSE: Rtl registry functions
5 * FILE: lib/rtl/registry.c
6 * PROGRAMER: Alex Ionescu (alex.ionescu@reactos.org)
7 * Eric Kohl
8 */
9
10/* INCLUDES *****************************************************************/
11
12#include <rtl.h>
13
14#include <ndk/cmfuncs.h>
15
16#define NDEBUG
17#include <debug.h>
18
19#define TAG_RTLREGISTRY 'vrqR'
20
22
23/* DATA **********************************************************************/
24
26{
27 NULL,
28 L"\\Registry\\Machine\\System\\CurrentControlSet\\Services",
29 L"\\Registry\\Machine\\System\\CurrentControlSet\\Control",
30 L"\\Registry\\Machine\\Software\\Microsoft\\Windows NT\\CurrentVersion",
31 L"\\Registry\\Machine\\Hardware\\DeviceMap",
32 L"\\Registry\\User\\.Default",
33};
34
35/* PRIVATE FUNCTIONS *********************************************************/
36
43{
44 USHORT ActualLength;
45 PUNICODE_STRING ReturnString = Buffer;
47 ULONG RealLength;
48
49 /* Check if this is a string */
50 if ((ValueType == REG_SZ) ||
53 {
54 /* Normalize the length */
56 ActualLength = MAXUSHORT;
57 else
58 ActualLength = (USHORT)ValueLength;
59
60 /* Check if the return string has been allocated */
61 if (!ReturnString->Buffer)
62 {
63 /* Allocate it */
64 ReturnString->Buffer = RtlpAllocateStringMemory(ActualLength, TAG_RTLREGISTRY);
65 if (!ReturnString->Buffer) return STATUS_NO_MEMORY;
66 ReturnString->MaximumLength = ActualLength;
67 }
68 else if (ActualLength > ReturnString->MaximumLength)
69 {
70 /* The string the caller allocated is too small */
72 }
73
74 /* Copy the data */
75 RtlCopyMemory(ReturnString->Buffer, ValueData, ActualLength);
76 ReturnString->Length = ActualLength - sizeof(UNICODE_NULL);
77 }
78 else if (ValueLength <= sizeof(ULONG))
79 {
80 /* Check if we can just copy the data */
81 if ((Buffer != ValueData) && (ValueLength))
82 {
83 /* Copy it */
85 }
86 }
87 else
88 {
89 /* Check if the length is negative */
90 if ((LONG)*Length < 0)
91 {
92 /* Get the real length and copy the buffer */
93 RealLength = -(LONG)*Length;
94 if (RealLength < ValueLength) return STATUS_BUFFER_TOO_SMALL;
96 }
97 else
98 {
99 if (ValueType != REG_BINARY)
100 {
101 /* Check if there's space for the length and type, plus data */
102 if (*Length < (2 * sizeof(ULONG) + ValueLength))
103 {
104 /* Nope, fail */
106 }
107
108 /* Return the data */
109 *Length++ = ValueLength;
110 *Length++ = ValueType;
112 }
113 else
114 {
115 /* Return the REG_BINARY data */
117 }
118 }
119 }
120
121 /* All done */
122 return STATUS_SUCCESS;
123}
124
126NTAPI
128 IN PKEY_VALUE_FULL_INFORMATION KeyValueInfo,
129 IN OUT PULONG InfoSize,
132{
133 ULONG InfoLength;
134 SIZE_T Length, SpareLength, c;
136 PCHAR SpareData, DataEnd;
137 ULONG Type;
138 PWCHAR Name, p, ValueEnd;
139 PVOID Data;
141 BOOLEAN FoundExpander = FALSE;
143
144 /* Setup defaults */
145 InfoLength = *InfoSize;
146 *InfoSize = 0;
147
148 /* Check if there's no data */
149 if (KeyValueInfo->DataOffset == MAXULONG)
150 {
151 /* Return proper status code */
154 }
155
156 /* Setup spare data pointers */
157 SpareData = (PCHAR)KeyValueInfo;
158 SpareLength = InfoLength;
159 DataEnd = SpareData + SpareLength;
160
161 /* Check if there's no value or data */
162 if ((KeyValueInfo->Type == REG_NONE) ||
163 (!(KeyValueInfo->DataLength) &&
164 (KeyValueInfo->Type == QueryTable->DefaultType)))
165 {
166 /* Check if there's no value */
168 {
169 /* Return proper status code */
172 }
173
174 /* We can setup a default value... capture the defaults */
179 if (!Length)
180 {
181 /* No default length given, try to calculate it */
182 p = Data;
183 if ((Type == REG_SZ) || (Type == REG_EXPAND_SZ))
184 {
185 /* This is a string, count the characters */
186 while (*p++);
188 }
189 else if (Type == REG_MULTI_SZ)
190 {
191 /* This is a multi-string, calculate all characters */
192 while (*p) while (*p++);
194 }
195 }
196 }
197 else
198 {
199 /* Check if we have length */
200 if (KeyValueInfo->DataLength)
201 {
202 /* Increase the spare data */
203 SpareData += KeyValueInfo->DataOffset +
204 KeyValueInfo->DataLength;
205 }
206 else
207 {
208 /* Otherwise, the spare data only has the name data */
210 KeyValueInfo->NameLength;
211 }
212
213 /* Align the pointer and get new size of spare data */
214 SpareData = (PVOID)(((ULONG_PTR)SpareData + 7) & ~7);
215 SpareLength = DataEnd - SpareData;
216
217 /* Check if we have space to copy the data */
218 RequiredLength = KeyValueInfo->NameLength + sizeof(UNICODE_NULL);
219 if ((SpareData > DataEnd) || (SpareLength < RequiredLength))
220 {
221 /* Fail and return the missing length */
222 *InfoSize = (ULONG)(SpareData - (PCHAR)KeyValueInfo) + RequiredLength;
224 }
225
226 /* Check if this isn't a direct return */
228 {
229 /* Copy the data and null-terminate it */
230 Name = (PWCHAR)SpareData;
231 RtlCopyMemory(Name, KeyValueInfo->Name, KeyValueInfo->NameLength);
232 Name[KeyValueInfo->NameLength / sizeof(WCHAR)] = UNICODE_NULL;
233
234 /* Update the spare data information */
235 SpareData += RequiredLength;
236 SpareData = (PVOID)(((ULONG_PTR)SpareData + 7) & ~7);
237 SpareLength = DataEnd - SpareData;
238 }
239 else
240 {
241 /* Just return the name */
243 }
244
245 /* Capture key data */
246 Type = KeyValueInfo->Type;
247 Data = (PVOID)((ULONG_PTR)KeyValueInfo + KeyValueInfo->DataOffset);
248 Length = KeyValueInfo->DataLength;
249 }
250
251 /* Check if we're expanding */
253 {
254 /* Check if it's a multi-string */
255 if (Type == REG_MULTI_SZ)
256 {
257 /* Prepare defaults */
259 /* Skip the last two UNICODE_NULL chars (the terminating null string) */
260 ValueEnd = (PWSTR)((ULONG_PTR)Data + Length - 2 * sizeof(UNICODE_NULL));
261 p = Data;
262
263 /* Loop all strings */
264 while (p < ValueEnd)
265 {
266 /* Go to the next string */
267 while (*p++);
268
269 /* Get the length and check if this is direct */
272 {
273 /* Do the query */
275 Data,
276 (ULONG)Length,
280 sizeof(UNICODE_STRING));
281 }
282 else
283 {
284 /* Call the custom routine */
286 REG_SZ,
287 Data,
288 (ULONG)Length,
289 Context,
291 }
292
293 /* Normalize status */
295 if (!NT_SUCCESS(Status)) break;
296
297 /* Update data pointer */
298 Data = p;
299 }
300
301 /* Return */
302 return Status;
303 }
304
305 /* Check if this is an expand string */
306 if ((Type == REG_EXPAND_SZ) && (Length >= sizeof(WCHAR)))
307 {
308 /* Try to find the expander */
309 c = Length - sizeof(UNICODE_NULL);
310 p = (PWCHAR)Data;
311 while (c)
312 {
313 /* Check if this is one */
314 if (*p == L'%')
315 {
316 /* Yup! */
317 FoundExpander = TRUE;
318 break;
319 }
320
321 /* Continue in the buffer */
322 p++;
323 c -= sizeof(WCHAR);
324 }
325
326 /* So check if we have one */
327 if (FoundExpander)
328 {
329 /* Setup the source string */
330 RtlInitEmptyUnicodeString(&Source, Data, (USHORT)Length);
331 Source.Length = Source.MaximumLength - sizeof(UNICODE_NULL);
332
333 /* Setup the destination string */
334 RtlInitEmptyUnicodeString(&Destination, (PWCHAR)SpareData, 0);
335
336 /* Check if we're out of space */
337 if (SpareLength <= 0)
338 {
339 /* Then we don't have any space in our string */
341 }
342 else if (SpareLength <= MAXUSHORT)
343 {
344 /* This is the good case, where we fit into a string */
345 Destination.MaximumLength = (USHORT)SpareLength;
346 Destination.Buffer[SpareLength / sizeof(WCHAR) - 1] = UNICODE_NULL;
347 }
348 else
349 {
350 /* We can't fit into a string, so truncate */
353 }
354
355 /* Expand the strings and set our type as one string */
357 &Source,
360 Type = REG_SZ;
361
362 /* Check for success */
363 if (NT_SUCCESS(Status))
364 {
365 /* Set the value name and length to our string */
368 }
369 else
370 {
371 /* Check if our buffer is too small */
373 {
374 /* Set the required missing length */
375 *InfoSize = (ULONG)(SpareData - (PCHAR)KeyValueInfo) +
377
378 /* Notify debugger */
379 DPRINT1("RTL: Expand variables for %wZ failed - "
380 "Status == %lx Size %x > %x <%x>\n",
381 &Source,
382 Status,
383 *InfoSize,
384 InfoLength,
386 }
387 else
388 {
389 /* Notify debugger */
390 DPRINT1("RTL: Expand variables for %wZ failed - "
391 "Status == %lx\n",
392 &Source,
393 Status);
394 }
395
396 /* Return the status */
397 return Status;
398 }
399 }
400 }
401 }
402
403 /* Check if this is a direct query */
405 {
406 /* Return the data */
408 Data,
409 (ULONG)Length,
411 }
412 else
413 {
414 /* Call the query routine */
416 Type,
417 Data,
418 (ULONG)Length,
419 Context,
421 }
422
423 /* Normalize and return status */
425}
426
429PVOID
430NTAPI
431RtlpAllocDeallocQueryBuffer(
433 _In_opt_ __drv_freesMem(Mem) PVOID OldBuffer,
434 _In_ SIZE_T OldBufferSize,
436{
437 PVOID Buffer = NULL;
438
439 /* Assume success */
441
442 /* Free the old buffer */
443 if (OldBuffer) RtlpFreeMemory(OldBuffer, TAG_RTLREGISTRY);
444
445 /* Check if we need to allocate a new one */
446 if (BufferSize)
447 {
448 /* Allocate */
450 if (!(Buffer) && (Status)) *Status = STATUS_NO_MEMORY;
451 }
452
453 /* Return the pointer */
454 return Buffer;
455}
456
458NTAPI
460 IN PCWSTR Path,
463{
464 UNICODE_STRING KeyPath, KeyName;
465 WCHAR KeyBuffer[MAX_PATH];
468
469 /* Check if we just want the handle */
470 if (RelativeTo & RTL_REGISTRY_HANDLE)
471 {
473 return STATUS_SUCCESS;
474 }
475
476 /* Check for optional flag */
477 if (RelativeTo & RTL_REGISTRY_OPTIONAL)
478 {
479 /* Mask it out */
480 RelativeTo &= ~RTL_REGISTRY_OPTIONAL;
481 }
482
483 /* Fail on invalid parameter */
484 if (RelativeTo >= RTL_REGISTRY_MAXIMUM) return STATUS_INVALID_PARAMETER;
485
486 /* Initialize the key name */
487 RtlInitEmptyUnicodeString(&KeyName, KeyBuffer, sizeof(KeyBuffer));
488
489 /* Check if we have to lookup a path to prefix */
490 if (RelativeTo != RTL_REGISTRY_ABSOLUTE)
491 {
492 /* Check if we need the current user key */
493 if (RelativeTo == RTL_REGISTRY_USER)
494 {
495 /* Get the user key path */
497
498 /* Check if it worked */
499 if (NT_SUCCESS(Status))
500 {
501 /* Append the user key path */
503
504 /* Free the user key path */
505 RtlFreeUnicodeString (&KeyPath);
506 }
507 else
508 {
509 /* It didn't work so fall back to the default user key */
511 }
512 }
513 else
514 {
515 /* Get one of the prefixes */
517 RtlpRegPaths[RelativeTo]);
518 }
519
520 /* Check for failure, otherwise, append the path separator */
521 if (!NT_SUCCESS(Status)) return Status;
523 if (!NT_SUCCESS(Status)) return Status;
524 }
525
526 /* And now append the path */
527 if (Path[0] == L'\\' && RelativeTo != RTL_REGISTRY_ABSOLUTE) Path++; // HACK!
529 if (!NT_SUCCESS(Status)) return Status;
530
531 /* Initialize the object attributes */
533 &KeyName,
535 NULL,
536 NULL);
537
538 /* Check if we want to create it */
539 if (Create)
540 {
541 /* Create the key with write privileges */
542 Status = ZwCreateKey(KeyHandle,
545 0,
546 NULL,
547 0,
548 NULL);
549 }
550 else
551 {
552 /* Otherwise, just open it with read access */
553 Status = ZwOpenKey(KeyHandle,
556 }
557
558 /* Return status */
559 return Status;
560}
561
563VOID
565 _In_ ULONG RelativeTo,
567{
568 /* Did the caller pass a key handle? */
569 if (!(RelativeTo & RTL_REGISTRY_HANDLE))
570 {
571 /* We opened the key in RtlpGetRegistryHandle, so close it now */
573 }
574}
575
576/* PUBLIC FUNCTIONS **********************************************************/
577
578/*
579 * @implemented
580 */
582NTAPI
584 IN PWSTR Path)
585{
589
590 /* Call the helper */
591 Status = RtlpGetRegistryHandle(RelativeTo,
592 Path,
593 FALSE,
594 &KeyHandle);
595 if (!NT_SUCCESS(Status)) return Status;
596
597 /* Close the handle even for RTL_REGISTRY_HANDLE */
599 return STATUS_SUCCESS;
600}
601
602/*
603 * @implemented
604 */
606NTAPI
608 IN PWSTR Path)
609{
613
614 /* Call the helper */
615 Status = RtlpGetRegistryHandle(RelativeTo,
616 Path,
617 TRUE,
618 &KeyHandle);
619 if (!NT_SUCCESS(Status)) return Status;
620
621 /* All went well, close the handle and return status */
623 return STATUS_SUCCESS;
624}
625
626/*
627 * @implemented
628 */
630NTAPI
632 IN PCWSTR Path,
634{
639
640 /* Call the helper */
641 Status = RtlpGetRegistryHandle(RelativeTo,
642 Path,
643 TRUE,
644 &KeyHandle);
645 if (!NT_SUCCESS(Status)) return Status;
646
647 /* Initialize the key name and delete it */
650
651 /* Close the handle and return status */
653 return Status;
654}
655
656/*
657 * @implemented
658 */
660NTAPI
662 IN PCWSTR Path,
667{
672
673 /* Call the helper */
674 Status = RtlpGetRegistryHandle(RelativeTo,
675 Path,
676 TRUE,
677 &KeyHandle);
678 if (!NT_SUCCESS(Status)) return Status;
679
680 /* Initialize the key name and set it */
682 Status = ZwSetValueKey(KeyHandle,
683 &Name,
684 0,
685 ValueType,
686 ValueData,
688
689 /* Close the handle and return status */
691 return Status;
692}
693
694/*
695 * @implemented
696 */
698NTAPI
701{
703 UNICODE_STRING KeyPath;
706
707 /* Get the user key */
709 if (NT_SUCCESS(Status))
710 {
711 /* Initialize the attributes and open it */
713 &KeyPath,
715 NULL,
716 NULL);
718
719 /* Free the path and return success if it worked */
720 RtlFreeUnicodeString(&KeyPath);
721 if (NT_SUCCESS(Status)) return STATUS_SUCCESS;
722 }
723
724 /* It didn't work, so use the default key */
727 &KeyPath,
729 NULL,
730 NULL);
732
733 /* Return status */
734 return Status;
735}
736
737/*
738 * @implemented
739 */
741NTAPI
743{
745 UCHAR Buffer[256];
746 PSID_AND_ATTRIBUTES SidBuffer;
748 UNICODE_STRING SidString;
751
752 /* Open the thread token */
755 TRUE,
757 &TokenHandle);
758 if (!NT_SUCCESS(Status))
759 {
760 /* We failed, is it because we don't have a thread token? */
761 if (Status != STATUS_NO_TOKEN) return Status;
762
763 /* It is, so use the process token */
767 &TokenHandle);
768 if (!NT_SUCCESS(Status)) return Status;
769 }
770
771 /* Now query the token information */
772 SidBuffer = (PSID_AND_ATTRIBUTES)Buffer;
773 Status = ZwQueryInformationToken(TokenHandle,
774 TokenUser,
775 (PVOID)SidBuffer,
776 sizeof(Buffer),
777 &Length);
778
779 /* Close the handle and handle failure */
781 if (!NT_SUCCESS(Status)) return Status;
782
783 /* Convert the SID */
784 Status = RtlConvertSidToUnicodeString(&SidString, SidBuffer[0].Sid, TRUE);
785 if (!NT_SUCCESS(Status)) return Status;
786
787 /* Add the length of the prefix */
788 Length = SidString.Length + sizeof(L"\\REGISTRY\\USER\\");
789
790 /* Initialize a string */
791 RtlInitEmptyUnicodeString(KeyPath,
793 (USHORT)Length);
794 if (!KeyPath->Buffer)
795 {
796 /* Free the string and fail */
797 RtlFreeUnicodeString(&SidString);
798 return STATUS_NO_MEMORY;
799 }
800
801 /* Append the prefix and SID */
802 RtlAppendUnicodeToString(KeyPath, L"\\REGISTRY\\USER\\");
803 RtlAppendUnicodeStringToString(KeyPath, &SidString);
804
805 /* Free the temporary string and return success */
806 RtlFreeUnicodeString(&SidString);
807 return STATUS_SUCCESS;
808}
809
810/*
811 * @implemented
812 */
814NTAPI
821{
822 /* Check if we have object attributes */
824 {
825 /* Mask out the unsupported flags */
826 ObjectAttributes->Attributes &= ~(OBJ_PERMANENT | OBJ_EXCLUSIVE);
827 }
828
829 /* Create the key */
830 return ZwCreateKey(KeyHandle,
833 0,
834 NULL,
835 0,
837}
838
839/*
840 * @implemented
841 */
843NTAPI
846 IN ULONG Index,
848{
853
854 /* Check if we have a name */
855 if (SubKeyName->MaximumLength)
856 {
857 /* Allocate a buffer for it */
858 BufferLength = SubKeyName->MaximumLength +
859 sizeof(KEY_BASIC_INFORMATION);
860 KeyInfo = RtlAllocateHeap(RtlGetProcessHeap(), 0, BufferLength);
861 if (!KeyInfo) return STATUS_NO_MEMORY;
862 }
863
864 /* Enumerate the key */
865 Status = ZwEnumerateKey(KeyHandle,
866 Index,
868 KeyInfo,
871 if (NT_SUCCESS(Status) && (KeyInfo != NULL))
872 {
873 /* Check if the name fits */
874 if (KeyInfo->NameLength <= SubKeyName->MaximumLength)
875 {
876 /* Set the length */
877 SubKeyName->Length = (USHORT)KeyInfo->NameLength;
878
879 /* Copy it */
881 KeyInfo->Name,
882 SubKeyName->Length);
883 }
884 else
885 {
886 /* Otherwise, we ran out of buffer space */
888 }
889 }
890
891 /* Free the buffer and return status */
892 if (KeyInfo) RtlFreeHeap(RtlGetProcessHeap(), 0, KeyInfo);
893 return Status;
894}
895
896/*
897 * @implemented
898 */
900NTAPI
902{
903 /* This just deletes the key */
904 return ZwDeleteKey(KeyHandle);
905}
906
907/*
908 * @implemented
909 */
911NTAPI
916{
917 /* Check if we have object attributes */
919 {
920 /* Mask out the unsupported flags */
921 ObjectAttributes->Attributes &= ~(OBJ_PERMANENT | OBJ_EXCLUSIVE);
922 }
923
924 /* Open the key */
925 return ZwOpenKey(KeyHandle, DesiredAccess, ObjectAttributes);
926}
927
928/*
929 * @implemented
930 */
932NTAPI
938{
943
944 /* Clear the value name */
945 RtlInitEmptyUnicodeString(&ValueName, NULL, 0);
946
947 /* Check if we were already given a length */
949
950 /* Add the size of the structure */
952
953 /* Allocate memory for the value */
954 ValueInfo = RtlAllocateHeap(RtlGetProcessHeap(), 0, BufferLength);
955 if (!ValueInfo) return STATUS_NO_MEMORY;
956
957 /* Query the value */
958 Status = ZwQueryValueKey(KeyHandle,
959 &ValueName,
961 ValueInfo,
963 &BufferLength);
965 {
966 /* Return the length and type */
967 if (DataLength) *DataLength = ValueInfo->DataLength;
968 if (Type) *Type = ValueInfo->Type;
969 }
970
971 /* Check if the caller wanted data back, and we got it */
972 if ((NT_SUCCESS(Status)) && (Data))
973 {
974 /* Copy it */
975 RtlMoveMemory(Data, ValueInfo->Data, ValueInfo->DataLength);
976 }
977
978 /* Free the memory and return status */
979 RtlFreeHeap(RtlGetProcessHeap(), 0, ValueInfo);
980 return Status;
981}
982
983/*
984 * @implemented
985 */
987NTAPI
989 IN ULONG Type,
990 IN PVOID Data,
992{
994
995 /* Set the value */
996 RtlInitEmptyUnicodeString(&ValueName, NULL, 0);
997 return ZwSetValueKey(KeyHandle,
998 &ValueName,
999 0,
1000 Type,
1001 Data,
1002 DataLength);
1003}
1004
1005/*
1006 * @implemented
1007 */
1009NTAPI
1011 IN PCWSTR Path,
1015{
1017 PKEY_VALUE_FULL_INFORMATION KeyValueInfo = NULL;
1018 HANDLE KeyHandle, CurrentKey;
1019 SIZE_T BufferSize, InfoSize;
1020 UNICODE_STRING KeyPath, KeyValueName;
1022 ULONG i, Value;
1024
1025 /* Get the registry handle */
1027 if (!NT_SUCCESS(Status)) return Status;
1028
1029 /* Initialize the path */
1030 RtlInitUnicodeString(&KeyPath,
1031 (RelativeTo & RTL_REGISTRY_HANDLE) ? NULL : Path);
1032
1033 /* Allocate a query buffer */
1035 KeyValueInfo = RtlpAllocDeallocQueryBuffer(&BufferSize, NULL, 0, &Status);
1036 if (!KeyValueInfo)
1037 {
1038 /* Close the handle if we have one and fail */
1040 return Status;
1041 }
1042
1043 /* Set defaults */
1044 KeyValueInfo->DataOffset = 0;
1045 InfoSize = BufferSize - sizeof(UNICODE_NULL);
1046 CurrentKey = KeyHandle;
1047
1048 /* Loop the query table */
1049 while ((QueryTable->QueryRoutine) ||
1052 {
1053 /* Check if the request is invalid */
1055 (!(QueryTable->Name) ||
1058 {
1059 /* Fail */
1061 break;
1062 }
1063
1064 /* Check if we want a specific key */
1067 {
1068 /* Check if we're working with another handle */
1069 if (CurrentKey != KeyHandle)
1070 {
1071 /* Close our current key and use the top */
1072 NtClose(CurrentKey);
1073 CurrentKey = KeyHandle;
1074 }
1075 }
1076
1077 /* Check if we're querying the subkey */
1079 {
1080 /* Make sure we have a name */
1081 if (!QueryTable->Name)
1082 {
1083 /* Fail */
1085 }
1086 else
1087 {
1088 /* Initialize the name */
1090
1091 /* Get the key handle */
1093 &KeyPath,
1096 KeyHandle,
1097 NULL);
1098 Status = ZwOpenKey(&CurrentKey,
1101 if (NT_SUCCESS(Status))
1102 {
1103 /* If we have a query routine, go enumerate values */
1104 if (QueryTable->QueryRoutine) goto ProcessValues;
1105 }
1106 }
1107 }
1108 else if (QueryTable->Name)
1109 {
1110 /* Initialize the path */
1111 RtlInitUnicodeString(&KeyValueName, QueryTable->Name);
1112
1113 /* Start query loop */
1114 i = 0;
1115 while (TRUE)
1116 {
1117 /* Make sure we didn't retry too many times */
1118 if (i++ > 4)
1119 {
1120 /* Fail */
1121 DPRINT1("RtlQueryRegistryValues: Miscomputed buffer size "
1122 "at line %d\n", __LINE__);
1123 break;
1124 }
1125
1126 /* Query key information */
1127 Status = ZwQueryValueKey(CurrentKey,
1128 &KeyValueName,
1130 KeyValueInfo,
1131 (ULONG)InfoSize,
1132 &ResultLength);
1134 {
1135 /* Normalize status code */
1137 }
1138
1139 /* Check for failure */
1140 if (!NT_SUCCESS(Status))
1141 {
1142 /* Check if we didn't find it */
1144 {
1145 /* Setup a default */
1146 KeyValueInfo->Type = REG_NONE;
1147 KeyValueInfo->DataLength = 0;
1148 ResultLength = (ULONG)InfoSize;
1149
1150 /* Call the query routine */
1152 KeyValueInfo,
1153 &ResultLength,
1154 Context,
1155 Environment);
1156 }
1157
1158 /* Check for buffer being too small */
1160 {
1161 /* Increase allocation size */
1163 sizeof(ULONG_PTR) +
1164 sizeof(UNICODE_NULL);
1165 KeyValueInfo = RtlpAllocDeallocQueryBuffer(&BufferSize,
1166 KeyValueInfo,
1167 BufferSize,
1168 &Status);
1169 if (!KeyValueInfo) break;
1170
1171 /* Update the data */
1172 KeyValueInfo->DataOffset = 0;
1173 InfoSize = BufferSize - sizeof(UNICODE_NULL);
1174 continue;
1175 }
1176 }
1177 else
1178 {
1179 /* Check if this is a multi-string */
1180 if (KeyValueInfo->Type == REG_MULTI_SZ)
1181 {
1182 /* Add a null-char */
1183 ((PWCHAR)KeyValueInfo)[ResultLength / sizeof(WCHAR)] = UNICODE_NULL;
1184 KeyValueInfo->DataLength += sizeof(UNICODE_NULL);
1185 }
1186
1187 /* Call the query routine */
1188 ResultLength = (ULONG)InfoSize;
1190 KeyValueInfo,
1191 &ResultLength,
1192 Context,
1193 Environment);
1194
1195 /* Check for buffer being too small */
1197 {
1198 /* Increase allocation size */
1200 sizeof(ULONG_PTR) +
1201 sizeof(UNICODE_NULL);
1202 KeyValueInfo = RtlpAllocDeallocQueryBuffer(&BufferSize,
1203 KeyValueInfo,
1204 BufferSize,
1205 &Status);
1206 if (!KeyValueInfo) break;
1207
1208 /* Update the data */
1209 KeyValueInfo->DataOffset = 0;
1210 InfoSize = BufferSize - sizeof(UNICODE_NULL);
1211 continue;
1212 }
1213
1214 /* Check if we need to delete the key */
1215 if ((NT_SUCCESS(Status)) &&
1217 {
1218 /* Delete it */
1219 ZwDeleteValueKey(CurrentKey, &KeyValueName);
1220 }
1221 }
1222
1223 /* We're done, break out */
1224 break;
1225 }
1226 }
1228 {
1229 /* Just call the query routine */
1231 REG_NONE,
1232 NULL,
1233 0,
1234 Context,
1236 }
1237 else
1238 {
1239ProcessValues:
1240 /* Loop every value */
1241 i = Value = 0;
1242 while (TRUE)
1243 {
1244 /* Enumerate the keys */
1245 Status = ZwEnumerateValueKey(CurrentKey,
1246 Value,
1248 KeyValueInfo,
1249 (ULONG)InfoSize,
1250 &ResultLength);
1252 {
1253 /* Normalize the status */
1255 }
1256
1257 /* Check if we found all the entries */
1259 {
1260 /* Check if this was the first entry and caller needs it */
1261 if (!(Value) &&
1263 {
1264 /* Fail */
1266 }
1267 else
1268 {
1269 /* Otherwise, it's ok */
1271 }
1272 break;
1273 }
1274
1275 /* Check if enumeration worked */
1276 if (NT_SUCCESS(Status))
1277 {
1278 /* Call the query routine */
1279 ResultLength = (ULONG)InfoSize;
1281 KeyValueInfo,
1282 &ResultLength,
1283 Context,
1284 Environment);
1285 }
1286
1287 /* Check if the query failed */
1289 {
1290 /* Increase allocation size */
1292 sizeof(ULONG_PTR) +
1293 sizeof(UNICODE_NULL);
1294 KeyValueInfo = RtlpAllocDeallocQueryBuffer(&BufferSize,
1295 KeyValueInfo,
1296 BufferSize,
1297 &Status);
1298 if (!KeyValueInfo) break;
1299
1300 /* Update the data */
1301 KeyValueInfo->DataOffset = 0;
1302 InfoSize = BufferSize - sizeof(UNICODE_NULL);
1303
1304 /* Try the value again unless it's been too many times */
1305 if (i++ <= 4) continue;
1306 break;
1307 }
1308
1309 /* Break out if we failed */
1310 if (!NT_SUCCESS(Status)) break;
1311
1312 /* Reset the number of retries and check if we need to delete */
1313 i = 0;
1315 {
1316 /* Build the name */
1317 RtlInitEmptyUnicodeString(&KeyValueName,
1318 KeyValueInfo->Name,
1319 (USHORT)KeyValueInfo->NameLength);
1320 KeyValueName.Length = KeyValueName.MaximumLength;
1321
1322 /* Delete the key */
1323 Status = ZwDeleteValueKey(CurrentKey, &KeyValueName);
1324 if (NT_SUCCESS(Status)) Value--;
1325 }
1326
1327 /* Go to the next value */
1328 Value++;
1329 }
1330 }
1331
1332 /* Check if we failed anywhere along the road */
1333 if (!NT_SUCCESS(Status)) break;
1334
1335 /* Continue */
1336 QueryTable++;
1337 }
1338
1339 /* Check if we need to close our handle */
1341 if ((CurrentKey) && (CurrentKey != KeyHandle)) ZwClose(CurrentKey);
1342
1343 /* Free our buffer and return status */
1344 RtlpAllocDeallocQueryBuffer(NULL, KeyValueInfo, BufferSize, NULL);
1345 return Status;
1346}
1347
1348/* EOF */
unsigned char BOOLEAN
PRTL_UNICODE_STRING_BUFFER Path
Type
Definition: Type.h:7
struct NameRec_ * Name
Definition: cdprocs.h:460
LONG NTSTATUS
Definition: precomp.h:26
#define DPRINT1
Definition: precomp.h:8
@ Create
Definition: registry.c:563
_In_ ULONG _In_ BATTERY_QUERY_INFORMATION_LEVEL _In_ LONG _In_ ULONG _Out_ PULONG ReturnedLength
Definition: batclass.h:188
PVOID NTAPI RtlAllocateHeap(IN PVOID HeapHandle, IN ULONG Flags, IN SIZE_T Size)
Definition: heap.c:590
BOOLEAN NTAPI RtlFreeHeap(IN PVOID HeapHandle, IN ULONG Flags, IN PVOID HeapBase)
Definition: heap.c:608
_In_ ULONG _In_opt_ WDFREQUEST _In_opt_ PVOID _In_ size_t _In_ PVOID _In_ size_t _Out_ size_t * DataLength
Definition: cdrom.h:1444
Definition: bufpool.h:45
IN PUNICODE_STRING IN POBJECT_ATTRIBUTES ObjectAttributes
Definition: conport.c:36
#define BufferSize
Definition: mmc.h:75
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define GENERIC_READ
Definition: compat.h:135
#define MAX_PATH
Definition: compat.h:34
#define ULONG_PTR
Definition: config.h:101
#define __drv_freesMem(kind)
Definition: driverspecs.h:272
#define __drv_allocatesMem(kind)
Definition: driverspecs.h:257
NTSTATUS RtlAppendUnicodeToString(IN PUNICODE_STRING Str1, IN PWSTR Str2)
Definition: string_lib.cpp:62
struct _UNICODE_STRING UNICODE_STRING
NTSYSAPI NTSTATUS NTAPI ZwDeleteValueKey(__in IN HANDLE Key, __in IN PUNICODE_STRING ValueName)
Status
Definition: gdiplustypes.h:25
const GLubyte * c
Definition: glext.h:8905
GLfloat GLfloat p
Definition: glext.h:8902
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
_In_ GUID _In_ PVOID ValueData
Definition: hubbusif.h:312
#define OBJ_KERNEL_HANDLE
Definition: winternl.h:231
#define OBJ_CASE_INSENSITIVE
Definition: winternl.h:228
#define OBJ_EXCLUSIVE
Definition: winternl.h:227
#define OBJ_PERMANENT
Definition: winternl.h:226
NTSYSAPI NTSTATUS WINAPI RtlExpandEnvironmentStrings_U(PCWSTR, const UNICODE_STRING *, UNICODE_STRING *, ULONG *)
NTSYSAPI NTSTATUS WINAPI RtlQueryRegistryValues(ULONG, PCWSTR, PRTL_QUERY_REGISTRY_TABLE, PVOID, PVOID)
#define c
Definition: ke_i.h:80
#define REG_SZ
Definition: layer.c:22
#define Unused(x)
Definition: atlwin.h:28
if(dx< 0)
Definition: linetemp.h:194
#define PCHAR
Definition: match.c:90
PVOID PVOID PWCHAR PVOID Environment
Definition: env.c:47
* PNTSTATUS
Definition: strlen.c:14
#define InitializeObjectAttributes(p, n, a, r, s)
Definition: reg.c:106
static ACCESS_MASK const OBJECT_ATTRIBUTES ULONG TitleIndex
Definition: reg.c:131
#define _Out_opt_
Definition: ms_sal.h:346
#define _Success_(expr)
Definition: ms_sal.h:259
#define _On_failure_(annos)
Definition: ms_sal.h:266
#define _When_(expr, annos)
Definition: ms_sal.h:254
#define _In_
Definition: ms_sal.h:308
#define _In_opt_
Definition: ms_sal.h:309
#define _Post_satisfies_(cond)
Definition: ms_sal.h:588
_Must_inspect_result_ _Out_ PNDIS_STATUS _In_ NDIS_HANDLE _In_ PNDIS_STRING SubKeyName
Definition: ndis.h:4725
_In_ UINT _In_ UINT _In_ PNDIS_PACKET Source
Definition: ndis.h:3169
_Must_inspect_result_ _Out_ PNDIS_STATUS _In_ NDIS_HANDLE _In_ ULONG _Out_ PNDIS_STRING _Out_ PNDIS_HANDLE KeyHandle
Definition: ndis.h:4715
_In_ ACCESS_MASK _In_ POBJECT_ATTRIBUTES _Reserved_ ULONG _In_opt_ PUNICODE_STRING _In_ ULONG _Out_opt_ PULONG Disposition
Definition: cmfuncs.h:56
NTSYSAPI NTSTATUS NTAPI ZwClose(_In_ HANDLE Handle)
_In_ ACCESS_MASK _In_ ULONG _Out_ PHANDLE TokenHandle
Definition: psfuncs.h:726
NTSYSAPI NTSTATUS NTAPI ZwOpenThreadTokenEx(_In_ HANDLE ThreadHandle, _In_ ACCESS_MASK DesiredAccess, _In_ BOOLEAN OpenAsSelf, _In_ ULONG HandleAttributes, _Out_ PHANDLE TokenHandle)
_In_ PCWSTR _Inout_ _At_ QueryTable _Pre_unknown_ PRTL_QUERY_REGISTRY_TABLE QueryTable
Definition: rtlfuncs.h:4208
_In_ PUNICODE_STRING _Inout_ PUNICODE_STRING Destination
Definition: rtlfuncs.h:3004
_In_ ULONG _In_ ACCESS_MASK _In_ PSID Sid
Definition: rtlfuncs.h:1133
NTSYSAPI NTSTATUS NTAPI ZwOpenProcessTokenEx(_In_ HANDLE ProcessHandle, _In_ ACCESS_MASK DesiredAccess, _In_ ULONG HandleAttributes, _Out_ PHANDLE TokenHandle)
@ KeyBasicInformation
Definition: nt_native.h:1131
#define RTL_QUERY_REGISTRY_SUBKEY
Definition: nt_native.h:125
#define REG_BINARY
Definition: nt_native.h:1496
@ KeyValuePartialInformation
Definition: nt_native.h:1182
@ KeyValueFullInformation
Definition: nt_native.h:1181
NTSYSAPI NTSTATUS NTAPI RtlAppendUnicodeStringToString(PUNICODE_STRING Destination, PUNICODE_STRING Source)
ULONG ACCESS_MASK
Definition: nt_native.h:40
struct _KEY_BASIC_INFORMATION KEY_BASIC_INFORMATION
NTSYSAPI VOID NTAPI RtlInitUnicodeString(PUNICODE_STRING DestinationString, PCWSTR SourceString)
#define RTL_QUERY_REGISTRY_NOEXPAND
Definition: nt_native.h:139
#define RTL_REGISTRY_ABSOLUTE
Definition: nt_native.h:161
#define NtCurrentProcess()
Definition: nt_native.h:1657
#define RTL_QUERY_REGISTRY_REQUIRED
Definition: nt_native.h:132
#define RTL_QUERY_REGISTRY_TOPKEY
Definition: nt_native.h:129
#define RTL_QUERY_REGISTRY_DIRECT
Definition: nt_native.h:144
#define RTL_REGISTRY_USER
Definition: nt_native.h:166
#define REG_MULTI_SZ
Definition: nt_native.h:1501
NTSTATUS NTAPI NtClose(IN HANDLE Handle)
Definition: obhandle.c:3402
NTSYSAPI VOID NTAPI RtlFreeUnicodeString(PUNICODE_STRING UnicodeString)
#define RTL_QUERY_REGISTRY_DELETE
Definition: nt_native.h:153
#define RTL_REGISTRY_MAXIMUM
Definition: nt_native.h:167
#define REG_NONE
Definition: nt_native.h:1492
#define RTL_QUERY_REGISTRY_NOVALUE
Definition: nt_native.h:135
#define RTL_REGISTRY_OPTIONAL
Definition: nt_native.h:169
#define GENERIC_WRITE
Definition: nt_native.h:90
#define REG_EXPAND_SZ
Definition: nt_native.h:1494
#define RTL_REGISTRY_HANDLE
Definition: nt_native.h:168
#define MAXIMUM_ALLOWED
Definition: nt_native.h:83
#define UNICODE_NULL
_In_ ULONG _In_ ULONG _In_ ULONG Length
Definition: ntddpcm.h:102
NTSYSAPI NTSTATUS NTAPI RtlConvertSidToUnicodeString(OUT PUNICODE_STRING DestinationString, IN PVOID Sid, IN BOOLEAN AllocateDestinationString)
PVOID *typedef PHANDLE
Definition: ntsecpkg.h:455
#define STATUS_NO_TOKEN
Definition: ntstatus.h:360
#define STATUS_NO_MORE_ENTRIES
Definition: ntstatus.h:205
#define STATUS_NO_MEMORY
Definition: ntstatus.h:260
#define L(x)
Definition: ntvdm.h:50
long LONG
Definition: pedump.c:60
unsigned short USHORT
Definition: pedump.c:61
PVOID NTAPI RtlpAllocateMemory(_In_ ULONG Bytes, _In_ ULONG Tag)
Definition: rtlcompat.c:34
VOID NTAPI RtlpFreeMemory(_In_ PVOID Mem, _In_ ULONG Tag)
Definition: rtlcompat.c:45
#define RtlpAllocateStringMemory
Definition: rtlp.h:155
#define PAGED_CODE_RTL()
Definition: rtlp.h:16
NTSTATUS NTAPI RtlpCallQueryRegistryRoutine(IN PRTL_QUERY_REGISTRY_TABLE QueryTable, IN PKEY_VALUE_FULL_INFORMATION KeyValueInfo, IN OUT PULONG InfoSize, IN PVOID Context, IN PVOID Environment)
Definition: registry.c:127
NTSTATUS NTAPI RtlFormatCurrentUserKeyPath(OUT PUNICODE_STRING KeyPath)
Definition: registry.c:742
NTSTATUS NTAPI RtlpNtSetValueKey(IN HANDLE KeyHandle, IN ULONG Type, IN PVOID Data, IN ULONG DataLength)
Definition: registry.c:988
FORCEINLINE VOID RtlpCloseRegistryHandle(_In_ ULONG RelativeTo, _In_ HANDLE KeyHandle)
Definition: registry.c:564
NTSTATUS NTAPI RtlpNtQueryValueKey(IN HANDLE KeyHandle, OUT PULONG Type OPTIONAL, OUT PVOID Data OPTIONAL, IN OUT PULONG DataLength OPTIONAL, IN ULONG Unused)
Definition: registry.c:933
NTSTATUS NTAPI RtlpNtOpenKey(OUT HANDLE KeyHandle, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes, IN ULONG Unused)
Definition: registry.c:912
#define TAG_RTLREGISTRY
Definition: registry.c:19
NTSTATUS NTAPI RtlpNtCreateKey(OUT HANDLE KeyHandle, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes, IN ULONG TitleIndex, IN PUNICODE_STRING Class, OUT PULONG Disposition)
Definition: registry.c:815
NTSTATUS NTAPI RtlpNtMakeTemporaryKey(IN HANDLE KeyHandle)
Definition: registry.c:901
NTSTATUS NTAPI RtlpQueryRegistryDirect(IN ULONG ValueType, IN PVOID ValueData, IN ULONG ValueLength, IN PVOID Buffer)
Definition: registry.c:39
PCWSTR RtlpRegPaths[RTL_REGISTRY_MAXIMUM]
Definition: registry.c:25
NTSTATUS NTAPI RtlCheckRegistryKey(IN ULONG RelativeTo, IN PWSTR Path)
Definition: registry.c:583
NTSTATUS NTAPI RtlpGetRegistryHandle(IN ULONG RelativeTo, IN PCWSTR Path, IN BOOLEAN Create, IN PHANDLE KeyHandle)
Definition: registry.c:459
NTSTATUS NTAPI RtlOpenCurrentUser(IN ACCESS_MASK DesiredAccess, OUT PHANDLE KeyHandle)
Definition: registry.c:699
NTSTATUS NTAPI RtlpNtEnumerateSubKey(IN HANDLE KeyHandle, OUT PUNICODE_STRING SubKeyName, IN ULONG Index, IN ULONG Unused)
Definition: registry.c:844
NTSTATUS NTAPI RtlDeleteRegistryValue(IN ULONG RelativeTo, IN PCWSTR Path, IN PCWSTR ValueName)
Definition: registry.c:631
SIZE_T RtlpAllocDeallocQueryBufferSize
Definition: libsupp.c:17
NTSTATUS NTAPI RtlCreateRegistryKey(IN ULONG RelativeTo, IN PWSTR Path)
Definition: registry.c:607
NTSTATUS NTAPI RtlWriteRegistryValue(IN ULONG RelativeTo, IN PCWSTR Path, IN PCWSTR ValueName, IN ULONG ValueType, IN PVOID ValueData, IN ULONG ValueLength)
Definition: registry.c:661
#define STATUS_SUCCESS
Definition: shellext.h:65
#define STATUS_BUFFER_TOO_SMALL
Definition: shellext.h:69
#define STATUS_BUFFER_OVERFLOW
Definition: shellext.h:66
PULONG MinorVersion OPTIONAL
Definition: CrossNt.h:68
PRTL_QUERY_REGISTRY_ROUTINE QueryRoutine
Definition: nt_native.h:109
USHORT MaximumLength
Definition: env_spec_w32.h:370
#define TAG_USTR
Definition: tag.h:145
ULONG_PTR * PSIZE_T
Definition: typedefs.h:80
uint16_t * PWSTR
Definition: typedefs.h:56
#define MAXULONG
Definition: typedefs.h:251
uint32_t * PULONG
Definition: typedefs.h:59
const uint16_t * PCWSTR
Definition: typedefs.h:57
#define FIELD_OFFSET(t, f)
Definition: typedefs.h:255
#define NTAPI
Definition: typedefs.h:36
void * PVOID
Definition: typedefs.h:50
PVOID HANDLE
Definition: typedefs.h:73
ULONG_PTR SIZE_T
Definition: typedefs.h:80
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
#define MAXUSHORT
Definition: typedefs.h:83
uint32_t ULONG_PTR
Definition: typedefs.h:65
#define IN
Definition: typedefs.h:39
#define RtlMoveMemory(Destination, Source, Length)
Definition: typedefs.h:264
uint16_t * PWCHAR
Definition: typedefs.h:56
uint32_t ULONG
Definition: typedefs.h:59
#define OUT
Definition: typedefs.h:40
char * PCHAR
Definition: typedefs.h:51
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
#define STATUS_OBJECT_NAME_NOT_FOUND
Definition: udferr_usr.h:149
_In_ WDFCOLLECTION _In_ ULONG Index
_Must_inspect_result_ _In_ WDFDEVICE _In_ DEVICE_REGISTRY_PROPERTY _In_ ULONG _Out_ PULONG ResultLength
Definition: wdfdevice.h:3776
_Must_inspect_result_ _In_ WDFDEVICE _In_ ULONG _In_ ACCESS_MASK DesiredAccess
Definition: wdfdevice.h:2658
_Must_inspect_result_ _In_ WDFDEVICE _In_ PCUNICODE_STRING KeyName
Definition: wdfdevice.h:2699
_Must_inspect_result_ _In_ WDFDEVICE _In_ DEVICE_REGISTRY_PROPERTY _In_ ULONG BufferLength
Definition: wdfdevice.h:3771
_In_ WDFMEMORY _Out_opt_ size_t * BufferSize
Definition: wdfmemory.h:254
_Must_inspect_result_ _In_ WDFKEY _In_ PCUNICODE_STRING _In_ ULONG _Out_opt_ PULONG _Out_opt_ PULONG ValueType
Definition: wdfregistry.h:282
_Must_inspect_result_ _In_ WDFKEY _In_ PCUNICODE_STRING ValueName
Definition: wdfregistry.h:243
_Must_inspect_result_ _In_ WDFKEY _In_ PCUNICODE_STRING _In_ ULONG ValueLength
Definition: wdfregistry.h:275
_Must_inspect_result_ _In_ WDFKEY _In_ PCUNICODE_STRING _Out_opt_ PUSHORT _Inout_opt_ PUNICODE_STRING Value
Definition: wdfregistry.h:413
#define FORCEINLINE
Definition: wdftypes.h:67
_In_ ULONG _Out_opt_ PULONG RequiredLength
Definition: wmifuncs.h:30
struct _SID_AND_ATTRIBUTES * PSID_AND_ATTRIBUTES
Definition: security.c:130
#define TOKEN_QUERY
Definition: setypes.h:928
@ TokenUser
Definition: setypes.h:966
unsigned char UCHAR
Definition: xmlstorage.h:181
__wchar_t WCHAR
Definition: xmlstorage.h:180
#define NtCurrentThread()