ReactOS  0.4.11-dev-791-gf6f1255
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 
38 NTAPI
42  IN PVOID Buffer)
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) ||
51  (ValueType == REG_EXPAND_SZ) ||
52  (ValueType == REG_MULTI_SZ))
53  {
54  /* Normalize the length */
55  if (ValueLength > MAXUSHORT)
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 = RtlpAllocateMemory(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 */
84  RtlCopyMemory(Buffer, ValueData, ValueLength);
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;
95  RtlCopyMemory(Buffer, ValueData, ValueLength);
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;
111  RtlCopyMemory(Length, ValueData, ValueLength);
112  }
113  else
114  {
115  /* Return the REG_BINARY data */
116  RtlCopyMemory(Length, ValueData, ValueLength);
117  }
118  }
119  }
120 
121  /* All done */
122  return STATUS_SUCCESS;
123 }
124 
125 NTSTATUS
126 NTAPI
128  IN PKEY_VALUE_FULL_INFORMATION KeyValueInfo,
129  IN OUT PULONG InfoSize,
130  IN PVOID Context,
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 */
152  return (QueryTable->Flags & RTL_QUERY_REGISTRY_REQUIRED) ?
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 */
167  if (QueryTable->DefaultType == REG_NONE)
168  {
169  /* Return proper status code */
170  return (QueryTable->Flags & RTL_QUERY_REGISTRY_REQUIRED) ?
172  }
173 
174  /* We can setup a default value... capture the defaults */
175  Name = (PWCHAR)QueryTable->Name;
176  Type = QueryTable->DefaultType;
177  Data = QueryTable->DefaultData;
178  Length = QueryTable->DefaultLength;
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++);
187  Length = (ULONG_PTR)p - (ULONG_PTR)Data;
188  }
189  else if (Type == REG_MULTI_SZ)
190  {
191  /* This is a multi-string, calculate all characters */
192  while (*p) while (*p++);
193  Length = (ULONG_PTR)p - (ULONG_PTR)Data + sizeof(UNICODE_NULL);
194  }
195  }
196  }
197  else
198  {
199  /* Check if this isn't a direct return */
200  if (!(QueryTable->Flags & RTL_QUERY_REGISTRY_DIRECT))
201  {
202  /* Check if we have length */
203  if (KeyValueInfo->DataLength)
204  {
205  /* Increase the spare data */
206  SpareData += KeyValueInfo->DataOffset +
207  KeyValueInfo->DataLength;
208  }
209  else
210  {
211  /* Otherwise, the spare data only has the name data */
212  SpareData += FIELD_OFFSET(KEY_VALUE_FULL_INFORMATION, Name) +
213  KeyValueInfo->NameLength;
214  }
215 
216  /* Align the pointer and get new size of spare data */
217  SpareData = (PVOID)(((ULONG_PTR)SpareData + 7) & ~7);
218  SpareLength = DataEnd - SpareData;
219 
220  /* Check if we have space to copy the data */
221  RequiredLength = KeyValueInfo->NameLength + sizeof(UNICODE_NULL);
222  if ((SpareData > DataEnd) || (SpareLength < RequiredLength))
223  {
224  /* Fail and return the missing length */
225  *InfoSize = (ULONG)(SpareData - (PCHAR)KeyValueInfo) + RequiredLength;
227  }
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 */
242  Name = (PWCHAR)QueryTable->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 */
252  if (!(QueryTable->Flags & RTL_QUERY_REGISTRY_NOEXPAND))
253  {
254  /* Check if it's a multi-string */
255  if (Type == REG_MULTI_SZ)
256  {
257  /* Prepare defaults */
258  Status = STATUS_SUCCESS;
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 */
270  Length = (ULONG_PTR)p - (ULONG_PTR)Data;
271  if (QueryTable->Flags & RTL_QUERY_REGISTRY_DIRECT)
272  {
273  /* Do the query */
275  Data,
276  (ULONG)Length,
277  QueryTable->EntryContext);
278  QueryTable->EntryContext =
279  (PVOID)((ULONG_PTR)QueryTable->EntryContext +
280  sizeof(UNICODE_STRING));
281  }
282  else
283  {
284  /* Call the custom routine */
285  Status = QueryTable->QueryRoutine(Name,
286  REG_SZ,
287  Data,
288  (ULONG)Length,
289  Context,
290  QueryTable->EntryContext);
291  }
292 
293  /* Normalize status */
294  if (Status == STATUS_BUFFER_TOO_SMALL) Status = STATUS_SUCCESS;
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 desination 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 */
340  Destination.MaximumLength = 0;
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 */
351  Destination.MaximumLength = MAXUSHORT;
352  Destination.Buffer[MAXUSHORT / sizeof(WCHAR) - 1] = UNICODE_NULL;
353  }
354 
355  /* Expand the strings and set our type as one string */
356  Status = RtlExpandEnvironmentStrings_U(Environment,
357  &Source,
358  &Destination,
359  &RequiredLength);
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 */
366  Data = Destination.Buffer;
367  Length = Destination.Length + sizeof(UNICODE_NULL);
368  }
369  else
370  {
371  /* Check if our buffer is too small */
372  if (Status == STATUS_BUFFER_TOO_SMALL)
373  {
374  /* Set the required missing length */
375  *InfoSize = (ULONG)(SpareData - (PCHAR)KeyValueInfo) +
376  RequiredLength;
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,
385  Destination.MaximumLength);
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 */
404  if (QueryTable->Flags & RTL_QUERY_REGISTRY_DIRECT)
405  {
406  /* Return the data */
407  Status = RtlpQueryRegistryDirect(Type,
408  Data,
409  (ULONG)Length,
410  QueryTable->EntryContext);
411  }
412  else
413  {
414  /* Call the query routine */
415  Status = QueryTable->QueryRoutine(Name,
416  Type,
417  Data,
418  (ULONG)Length,
419  Context,
420  QueryTable->EntryContext);
421  }
422 
423  /* Normalize and return status */
424  return (Status == STATUS_BUFFER_TOO_SMALL) ? STATUS_SUCCESS : Status;
425 }
426 
427 _Success_(return!=NULL || BufferSize==0)
429 PVOID
430 NTAPI
431 RtlpAllocDeallocQueryBuffer(
433  _In_opt_ __drv_freesMem(Mem) PVOID OldBuffer,
434  _In_ SIZE_T OldBufferSize,
436 {
437  PVOID Buffer = NULL;
438 
439  /* Assume success */
440  if (Status) *Status = STATUS_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 */
449  Buffer = RtlpAllocateMemory(*BufferSize, TAG_RTLREGISTRY);
450  if (!(Buffer) && (Status)) *Status = STATUS_NO_MEMORY;
451  }
452 
453  /* Return the pointer */
454  return Buffer;
455 }
456 
457 NTSTATUS
458 NTAPI
460  IN PCWSTR Path,
461  IN BOOLEAN Create,
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  {
472  *KeyHandle = (HANDLE)Path;
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 */
496  Status = RtlFormatCurrentUserKeyPath(&KeyPath);
497 
498  /* Check if it worked */
499  if (NT_SUCCESS(Status))
500  {
501  /* Append the user key path */
502  Status = RtlAppendUnicodeStringToString(&KeyName, &KeyPath);
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 */
516  Status = RtlAppendUnicodeToString(&KeyName,
517  RtlpRegPaths[RelativeTo]);
518  }
519 
520  /* Check for failure, otherwise, append the path separator */
521  if (!NT_SUCCESS(Status)) return Status;
522  Status = RtlAppendUnicodeToString(&KeyName, L"\\");
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!
528  Status = RtlAppendUnicodeToString(&KeyName, Path);
529  if (!NT_SUCCESS(Status)) return Status;
530 
531  /* Initialize the object attributes */
532  InitializeObjectAttributes(&ObjectAttributes,
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,
544  &ObjectAttributes,
545  0,
546  NULL,
547  0,
548  NULL);
549  }
550  else
551  {
552  /* Otherwise, just open it with read access */
553  Status = ZwOpenKey(KeyHandle,
555  &ObjectAttributes);
556  }
557 
558  /* Return status */
559  return Status;
560 }
561 
563 VOID
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 */
572  ZwClose(KeyHandle);
573  }
574 }
575 
576 /* PUBLIC FUNCTIONS **********************************************************/
577 
578 /*
579  * @implemented
580  */
581 NTSTATUS
582 NTAPI
584  IN PWSTR Path)
585 {
588  PAGED_CODE_RTL();
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 */
598  ZwClose(KeyHandle);
599  return STATUS_SUCCESS;
600 }
601 
602 /*
603  * @implemented
604  */
605 NTSTATUS
606 NTAPI
608  IN PWSTR Path)
609 {
612  PAGED_CODE_RTL();
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 */
622  RtlpCloseRegistryHandle(RelativeTo, KeyHandle);
623  return STATUS_SUCCESS;
624 }
625 
626 /*
627  * @implemented
628  */
629 NTSTATUS
630 NTAPI
632  IN PCWSTR Path,
634 {
638  PAGED_CODE_RTL();
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 */
648  RtlInitUnicodeString(&Name, ValueName);
649  Status = ZwDeleteValueKey(KeyHandle, &Name);
650 
651  /* Close the handle and return status */
652  RtlpCloseRegistryHandle(RelativeTo, KeyHandle);
653  return Status;
654 }
655 
656 /*
657  * @implemented
658  */
659 NTSTATUS
660 NTAPI
662  IN PCWSTR Path,
667 {
671  PAGED_CODE_RTL();
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 */
681  RtlInitUnicodeString(&Name, ValueName);
682  Status = ZwSetValueKey(KeyHandle,
683  &Name,
684  0,
685  ValueType,
686  ValueData,
687  ValueLength);
688 
689  /* Close the handle and return status */
690  RtlpCloseRegistryHandle(RelativeTo, KeyHandle);
691  return Status;
692 }
693 
694 /*
695  * @implemented
696  */
697 NTSTATUS
698 NTAPI
701 {
703  UNICODE_STRING KeyPath;
705  PAGED_CODE_RTL();
706 
707  /* Get the user key */
708  Status = RtlFormatCurrentUserKeyPath(&KeyPath);
709  if (NT_SUCCESS(Status))
710  {
711  /* Initialize the attributes and open it */
712  InitializeObjectAttributes(&ObjectAttributes,
713  &KeyPath,
715  NULL,
716  NULL);
717  Status = ZwOpenKey(KeyHandle, DesiredAccess, &ObjectAttributes);
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 */
726  InitializeObjectAttributes(&ObjectAttributes,
727  &KeyPath,
729  NULL,
730  NULL);
731  Status = ZwOpenKey(KeyHandle, DesiredAccess, &ObjectAttributes);
732 
733  /* Return status */
734  return Status;
735 }
736 
737 /*
738  * @implemented
739  */
740 NTSTATUS
741 NTAPI
743 {
745  UCHAR Buffer[256];
746  PSID_AND_ATTRIBUTES SidBuffer;
747  ULONG Length;
748  UNICODE_STRING SidString;
750  PAGED_CODE_RTL();
751 
752  /* Open the thread token */
754  TOKEN_QUERY,
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 */
765  TOKEN_QUERY,
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 */
780  ZwClose(TokenHandle);
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  */
813 NTSTATUS
814 NTAPI
821 {
822  /* Check if we have object attributes */
823  if (ObjectAttributes)
824  {
825  /* Mask out the unsupported flags */
826  ObjectAttributes->Attributes &= ~(OBJ_PERMANENT | OBJ_EXCLUSIVE);
827  }
828 
829  /* Create the key */
830  return ZwCreateKey(KeyHandle,
831  DesiredAccess,
832  ObjectAttributes,
833  0,
834  NULL,
835  0,
836  Disposition);
837 }
838 
839 /*
840  * @implemented
841  */
842 NTSTATUS
843 NTAPI
846  IN ULONG Index,
847  IN ULONG Unused)
848 {
849  PKEY_BASIC_INFORMATION KeyInfo = NULL;
850  ULONG BufferLength = 0;
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,
869  BufferLength,
870  &ReturnedLength);
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 */
880  RtlMoveMemory(SubKeyName->Buffer,
881  KeyInfo->Name,
882  SubKeyName->Length);
883  }
884  else
885  {
886  /* Otherwise, we ran out of buffer space */
887  Status = STATUS_BUFFER_OVERFLOW;
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  */
899 NTSTATUS
900 NTAPI
902 {
903  /* This just deletes the key */
904  return ZwDeleteKey(KeyHandle);
905 }
906 
907 /*
908  * @implemented
909  */
910 NTSTATUS
911 NTAPI
915  IN ULONG Unused)
916 {
917  /* Check if we have object attributes */
918  if (ObjectAttributes)
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  */
931 NTSTATUS
932 NTAPI
935  OUT PVOID Data OPTIONAL,
936  IN OUT PULONG DataLength OPTIONAL,
937  IN ULONG Unused)
938 {
941  ULONG BufferLength = 0;
943 
944  /* Clear the value name */
945  RtlInitEmptyUnicodeString(&ValueName, NULL, 0);
946 
947  /* Check if we were already given a length */
948  if (DataLength) BufferLength = *DataLength;
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,
962  BufferLength,
963  &BufferLength);
964  if ((NT_SUCCESS(Status)) || (Status == STATUS_BUFFER_OVERFLOW))
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  */
986 NTSTATUS
987 NTAPI
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  */
1008 NTSTATUS
1009 NTAPI
1011  IN PCWSTR Path,
1013  IN PVOID Context,
1015 {
1016  NTSTATUS Status;
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 */
1026  Status = RtlpGetRegistryHandle(RelativeTo, Path, FALSE, &KeyHandle);
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 */
1034  BufferSize = RtlpAllocDeallocQueryBufferSize;
1035  KeyValueInfo = RtlpAllocDeallocQueryBuffer(&BufferSize, NULL, 0, &Status);
1036  if (!KeyValueInfo)
1037  {
1038  /* Close the handle if we have one and fail */
1039  RtlpCloseRegistryHandle(RelativeTo, KeyHandle);
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) ||
1050  (QueryTable->Flags & (RTL_QUERY_REGISTRY_SUBKEY |
1052  {
1053  /* Check if the request is invalid */
1054  if ((QueryTable->Flags & RTL_QUERY_REGISTRY_DIRECT) &&
1055  (!(QueryTable->Name) ||
1056  (QueryTable->Flags & RTL_QUERY_REGISTRY_SUBKEY) ||
1057  (QueryTable->QueryRoutine)))
1058  {
1059  /* Fail */
1060  Status = STATUS_INVALID_PARAMETER;
1061  break;
1062  }
1063 
1064  /* Check if we want a specific key */
1065  if (QueryTable->Flags & (RTL_QUERY_REGISTRY_TOPKEY |
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 */
1078  if (QueryTable->Flags & RTL_QUERY_REGISTRY_SUBKEY)
1079  {
1080  /* Make sure we have a name */
1081  if (!QueryTable->Name)
1082  {
1083  /* Fail */
1084  Status = STATUS_INVALID_PARAMETER;
1085  }
1086  else
1087  {
1088  /* Initialize the name */
1089  RtlInitUnicodeString(&KeyPath, QueryTable->Name);
1090 
1091  /* Get the key handle */
1092  InitializeObjectAttributes(&ObjectAttributes,
1093  &KeyPath,
1096  KeyHandle,
1097  NULL);
1098  Status = ZwOpenKey(&CurrentKey,
1100  &ObjectAttributes);
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);
1133  if (Status == STATUS_BUFFER_OVERFLOW)
1134  {
1135  /* Normalize status code */
1136  Status = STATUS_BUFFER_TOO_SMALL;
1137  }
1138 
1139  /* Check for failure */
1140  if (!NT_SUCCESS(Status))
1141  {
1142  /* Check if we didn't find it */
1143  if (Status == STATUS_OBJECT_NAME_NOT_FOUND)
1144  {
1145  /* Setup a default */
1146  KeyValueInfo->Type = REG_NONE;
1147  KeyValueInfo->DataLength = 0;
1148  ResultLength = (ULONG)InfoSize;
1149 
1150  /* Call the query routine */
1151  Status = RtlpCallQueryRegistryRoutine(QueryTable,
1152  KeyValueInfo,
1153  &ResultLength,
1154  Context,
1155  Environment);
1156  }
1157 
1158  /* Check for buffer being too small */
1159  if (Status == STATUS_BUFFER_TOO_SMALL)
1160  {
1161  /* Increase allocation size */
1162  BufferSize = ResultLength +
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;
1189  Status = RtlpCallQueryRegistryRoutine(QueryTable,
1190  KeyValueInfo,
1191  &ResultLength,
1192  Context,
1193  Environment);
1194 
1195  /* Check for buffer being too small */
1196  if (Status == STATUS_BUFFER_TOO_SMALL)
1197  {
1198  /* Increase allocation size */
1199  BufferSize = ResultLength +
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)) &&
1216  (QueryTable->Flags & RTL_QUERY_REGISTRY_DELETE))
1217  {
1218  /* Delete it */
1219  ZwDeleteValueKey(CurrentKey, &KeyValueName);
1220  }
1221  }
1222 
1223  /* We're done, break out */
1224  break;
1225  }
1226  }
1227  else if (QueryTable->Flags & RTL_QUERY_REGISTRY_NOVALUE)
1228  {
1229  /* Just call the query routine */
1230  Status = QueryTable->QueryRoutine(NULL,
1231  REG_NONE,
1232  NULL,
1233  0,
1234  Context,
1235  QueryTable->EntryContext);
1236  }
1237  else
1238  {
1239 ProcessValues:
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);
1251  if (Status == STATUS_BUFFER_OVERFLOW)
1252  {
1253  /* Normalize the status */
1254  Status = STATUS_BUFFER_TOO_SMALL;
1255  }
1256 
1257  /* Check if we found all the entries */
1258  if (Status == STATUS_NO_MORE_ENTRIES)
1259  {
1260  /* Check if this was the first entry and caller needs it */
1261  if (!(Value) &&
1262  (QueryTable->Flags & RTL_QUERY_REGISTRY_REQUIRED))
1263  {
1264  /* Fail */
1266  }
1267  else
1268  {
1269  /* Otherwise, it's ok */
1270  Status = STATUS_SUCCESS;
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;
1280  Status = RtlpCallQueryRegistryRoutine(QueryTable,
1281  KeyValueInfo,
1282  &ResultLength,
1283  Context,
1284  Environment);
1285  }
1286 
1287  /* Check if the query failed */
1288  if (Status == STATUS_BUFFER_TOO_SMALL)
1289  {
1290  /* Increase allocation size */
1291  BufferSize = ResultLength +
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;
1314  if (QueryTable->Flags & RTL_QUERY_REGISTRY_DELETE)
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 */
1340  if (KeyHandle) RtlpCloseRegistryHandle(RelativeTo, KeyHandle);
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 */
DWORD *typedef PVOID
Definition: winlogon.h:61
IN CINT OUT PVOID IN ULONG OUT PULONG ResultLength
Definition: conport.c:47
signed char * PCHAR
Definition: retypes.h:7
* PNTSTATUS
Definition: strlen.c:14
#define MAXIMUM_ALLOWED
Definition: nt_native.h:83
IN PUNICODE_STRING IN POBJECT_ATTRIBUTES ObjectAttributes
Definition: conport.c:35
_Must_inspect_result_ _Out_ PNDIS_STATUS _In_ NDIS_HANDLE _In_ ULONG _Out_ PNDIS_STRING KeyName
Definition: ndis.h:4693
_Must_inspect_result_ typedef _In_ PVOID Unused
Definition: iotypes.h:1128
_In_ PCWSTR _Inout_ _At_ QueryTable _Pre_unknown_ PRTL_QUERY_REGISTRY_TABLE QueryTable
Definition: rtlfuncs.h:3988
PVOID PVOID PWCHAR PVOID Environment
Definition: env.c:45
#define IN
Definition: typedefs.h:38
#define TRUE
Definition: types.h:120
NTSYSAPI VOID NTAPI RtlCopyMemory(VOID UNALIGNED *Destination, CONST VOID UNALIGNED *Source, ULONG Length)
#define RTL_QUERY_REGISTRY_NOVALUE
Definition: nt_native.h:135
static ACCESS_MASK const OBJECT_ATTRIBUTES ULONG TitleIndex
Definition: reg.c:130
static LONG(WINAPI *pRegCopyTreeA)(HKEY
Type
Definition: Type.h:6
#define STATUS_NO_MORE_ENTRIES
Definition: ntstatus.h:193
_Must_inspect_result_ _Out_ PNDIS_STATUS _In_ NDIS_HANDLE _In_ PNDIS_STRING SubKeyName
Definition: ndis.h:4705
_Must_inspect_result_ _Out_ PNDIS_STATUS _In_ NDIS_HANDLE _In_ ULONG _Out_ PNDIS_STRING _Out_ PNDIS_HANDLE KeyHandle
Definition: ndis.h:4693
USHORT MaximumLength
Definition: env_spec_w32.h:370
NTSTATUS NTAPI RtlOpenCurrentUser(IN ACCESS_MASK DesiredAccess, OUT PHANDLE KeyHandle)
Definition: registry.c:699
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
#define REG_BINARY
Definition: nt_native.h:1496
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
__wchar_t WCHAR
Definition: xmlstorage.h:180
NTSYSAPI NTSTATUS NTAPI ZwClose(_In_ HANDLE Handle)
_In_ BOOLEAN Create
Definition: pstypes.h:511
#define RTL_QUERY_REGISTRY_TOPKEY
Definition: nt_native.h:129
_In_ PCWSTR _In_z_ PCWSTR _In_ ULONG ValueType
Definition: rtlfuncs.h:4000
BOOLEAN NTAPI RtlFreeHeap(IN PVOID HeapHandle, IN ULONG Flags, IN PVOID HeapBase)
Definition: heap.c:603
NTSYSAPI NTSTATUS NTAPI ZwOpenProcessTokenEx(_In_ HANDLE ProcessHandle, _In_ ACCESS_MASK DesiredAccess, _In_ ULONG HandleAttributes, _Out_ PHANDLE TokenHandle)
struct _KEY_BASIC_INFORMATION KEY_BASIC_INFORMATION
#define NtCurrentThread()
PVOID *typedef PWSTR
Definition: winlogon.h:66
VOID * Source
Definition: acefiex.h:744
#define RTL_QUERY_REGISTRY_NOEXPAND
Definition: nt_native.h:139
#define OBJ_PERMANENT
Definition: winternl.h:226
PVOID ULONG ULONG PULONG Data
Definition: oprghdlr.h:14
static PVOID
Definition: registry.c:44
#define RtlpAllocateStringMemory
Definition: rtlp.h:140
VOID NTAPI RtlpFreeMemory(_In_ PVOID Mem, _In_ ULONG Tag)
Definition: rtlcompat.c:45
uint16_t * PWCHAR
Definition: typedefs.h:54
#define PAGED_CODE_RTL()
Definition: rtlp.h:16
NTSYSAPI NTSTATUS NTAPI ZwOpenThreadTokenEx(_In_ HANDLE ThreadHandle, _In_ ACCESS_MASK DesiredAccess, _In_ BOOLEAN OpenAsSelf, _In_ ULONG HandleAttributes, _Out_ PHANDLE TokenHandle)
#define WCHAR
Definition: msvc.h:43
#define BufferSize
Definition: acefiex.h:377
#define RTL_REGISTRY_USER
Definition: nt_native.h:166
_In_ ACCESS_MASK _In_ POBJECT_ATTRIBUTES _Reserved_ ULONG _In_opt_ PUNICODE_STRING _In_ ULONG _Out_opt_ PULONG Disposition
Definition: cmfuncs.h:50
IN BOOLEAN OUT PSTR Buffer
Definition: progress.h:34
#define _In_opt_
Definition: no_sal2.h:213
#define RtlMoveMemory(Destination, Source, Length)
Definition: typedefs.h:263
#define STATUS_BUFFER_TOO_SMALL
Definition: shellext.h:52
uint32_t ULONG_PTR
Definition: typedefs.h:63
_In_ PUNICODE_STRING ValueName
Definition: cmfuncs.h:264
GLenum GLclampf GLint i
Definition: glfuncs.h:14
#define RTL_QUERY_REGISTRY_DELETE
Definition: nt_native.h:153
ULONG_PTR * PSIZE_T
Definition: typedefs.h:78
NTSTATUS(* NTAPI)(IN PFILE_FULL_EA_INFORMATION EaBuffer, IN ULONG EaLength, OUT PULONG ErrorOffset)
Definition: IoEaTest.cpp:117
#define FALSE
Definition: types.h:117
#define UNICODE_NULL
PVOID NTAPI RtlpAllocateMemory(_In_ ULONG Bytes, _In_ ULONG Tag)
Definition: rtlcompat.c:34
long LONG
Definition: pedump.c:60
_In_ ULONG BufferLength
Definition: usbdlib.h:225
#define REG_MULTI_SZ
Definition: nt_native.h:1501
#define GENERIC_WRITE
Definition: nt_native.h:90
UINTN * BufferSize
Definition: acefiex.h:370
NTSTATUS NTAPI RtlpNtMakeTemporaryKey(IN HANDLE KeyHandle)
Definition: registry.c:901
smooth NULL
Definition: ftsmooth.c:416
#define RTL_QUERY_REGISTRY_SUBKEY
Definition: nt_native.h:125
#define FORCEINLINE
Definition: ntbasedef.h:221
_In_ ULONG _In_ ACCESS_MASK _In_ PSID Sid
Definition: rtlfuncs.h:1104
#define OBJ_EXCLUSIVE
Definition: winternl.h:227
_In_ ACCESS_MASK _In_ ULONG _Out_ PHANDLE TokenHandle
Definition: psfuncs.h:715
Definition: bufpool.h:45
NTSTATUS NTAPI RtlpQueryRegistryDirect(IN ULONG ValueType, IN PVOID ValueData, IN ULONG ValueLength, IN PVOID Buffer)
Definition: registry.c:39
#define RTL_REGISTRY_OPTIONAL
Definition: nt_native.h:169
_Success_(return!=NULL||BufferSize==0)
Definition: registry.c:427
NTSTATUS NTAPI RtlpNtOpenKey(OUT HANDLE KeyHandle, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes, IN ULONG Unused)
Definition: registry.c:912
SIZE_T RtlpAllocDeallocQueryBufferSize
Definition: libsupp.c:17
#define NtCurrentProcess()
Definition: nt_native.h:1657
#define PCHAR
Definition: match.c:90
PVOID NTAPI RtlAllocateHeap(IN PVOID HeapHandle, IN ULONG Flags, IN SIZE_T Size)
Definition: heap.c:585
NTSYSAPI NTSTATUS WINAPI RtlExpandEnvironmentStrings_U(PCWSTR, const UNICODE_STRING *, UNICODE_STRING *, ULONG *)
NTSTATUS NTAPI RtlFormatCurrentUserKeyPath(OUT PUNICODE_STRING KeyPath)
Definition: registry.c:742
FORCEINLINE VOID RtlpCloseRegistryHandle(_In_ ULONG RelativeTo, _In_ HANDLE KeyHandle)
Definition: registry.c:564
NTSTATUS RtlAppendUnicodeToString(IN PUNICODE_STRING Str1, IN PWSTR Str2)
Definition: string_lib.cpp:62
#define _Out_opt_
Definition: no_sal2.h:339
struct _SID_AND_ATTRIBUTES * PSID_AND_ATTRIBUTES
Definition: security.c:129
unsigned char BOOLEAN
#define __drv_allocatesMem(kind)
Definition: driverspecs.h:239
LONG NTSTATUS
Definition: precomp.h:26
#define TOKEN_QUERY
Definition: setypes.h:874
if(!(yy_init))
Definition: macro.lex.yy.c:717
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:24
#define MAX_PATH
Definition: compat.h:26
static const UCHAR Index[8]
Definition: usbohci.c:18
_In_ GUID _In_ PVOID ValueData
Definition: hubbusif.h:311
NTSYSAPI VOID NTAPI RtlFreeUnicodeString(PUNICODE_STRING UnicodeString)
_In_ PUNICODE_STRING _Inout_ PUNICODE_STRING Destination
Definition: rtlfuncs.h:2875
#define STATUS_NO_TOKEN
Definition: ntstatus.h:346
NTSYSAPI NTSTATUS NTAPI RtlConvertSidToUnicodeString(OUT PUNICODE_STRING DestinationString, IN PVOID Sid, IN BOOLEAN AllocateDestinationString)
NTSTATUS NTAPI NtClose(IN HANDLE Handle)
Definition: obhandle.c:3393
#define OBJ_CASE_INSENSITIVE
Definition: winternl.h:228
_In_ PUNICODE_STRING Name
Definition: mrx.h:218
NTSTATUS NTAPI RtlpNtEnumerateSubKey(IN HANDLE KeyHandle, OUT PUNICODE_STRING SubKeyName, IN ULONG Index, IN ULONG Unused)
Definition: registry.c:844
unsigned char UCHAR
Definition: xmlstorage.h:181
PCWSTR RtlpRegPaths[RTL_REGISTRY_MAXIMUM]
Definition: registry.c:25
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
static const WCHAR L[]
Definition: oid.c:1087
VOID UINTN Length
Definition: acefiex.h:744
_In_ GUID _In_ PVOID _In_ ULONG ValueLength
Definition: hubbusif.h:311
PVOID *typedef PHANDLE
Definition: ntsecpkg.h:414
#define RTL_REGISTRY_HANDLE
Definition: nt_native.h:168
_In_ ULONG _In_ BATTERY_QUERY_INFORMATION_LEVEL _In_ LONG _In_ ULONG _Out_ PULONG ReturnedLength
Definition: batclass.h:187
#define GENERIC_READ
Definition: compat.h:124
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 RTL_REGISTRY_ABSOLUTE
Definition: nt_native.h:161
#define TAG_USTR
Definition: libsupp.c:111
UINTN UINT8 Value
Definition: acefiex.h:751
Status
Definition: gdiplustypes.h:24
#define MAXULONG
Definition: typedefs.h:250
#define _In_
Definition: no_sal2.h:204
ULONG_PTR SIZE_T
Definition: typedefs.h:78
NTSTATUS NTAPI RtlpGetRegistryHandle(IN ULONG RelativeTo, IN PCWSTR Path, IN BOOLEAN Create, IN PHANDLE KeyHandle)
Definition: registry.c:459
NTSTATUS NTAPI RtlQueryRegistryValues(IN ULONG RelativeTo, IN PCWSTR Path, IN PRTL_QUERY_REGISTRY_TABLE QueryTable, IN PVOID Context, IN PVOID Environment OPTIONAL)
Definition: registry.c:1010
DWORD *typedef HANDLE
Definition: winlogon.h:61
PRTL_UNICODE_STRING_BUFFER Path
#define STATUS_OBJECT_NAME_NOT_FOUND
Definition: udferr_usr.h:149
#define STATUS_BUFFER_OVERFLOW
Definition: shellext.h:49
unsigned short USHORT
Definition: pedump.c:61
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
_In_ ULONG _Out_opt_ PULONG RequiredLength
Definition: wmifuncs.h:29
NTSTATUS NTAPI RtlpNtSetValueKey(IN HANDLE KeyHandle, IN ULONG Type, IN PVOID Data, IN ULONG DataLength)
Definition: registry.c:988
#define REG_EXPAND_SZ
Definition: nt_native.h:1494
_In_ PIO_STACK_LOCATION _Inout_ PFILE_OBJECT _Inout_ PVCB _Outptr_result_maybenull_ PDCB _In_ PDCB _In_ PDIRENT _In_ ULONG _In_ ULONG _In_ PUNICODE_STRING _In_ PACCESS_MASK DesiredAccess
Definition: create.c:4157
#define STATUS_NO_MEMORY
Definition: ntstatus.h:246
NTSYSAPI NTSTATUS NTAPI RtlAppendUnicodeStringToString(PUNICODE_STRING Destination, PUNICODE_STRING Source)
#define FIELD_OFFSET(t, f)
Definition: typedefs.h:254
unsigned int * PULONG
Definition: retypes.h:1
#define _On_failure_(annos)
Definition: no_sal2.h:322
#define _When_(expr, annos)
Definition: no_sal2.h:639
#define __drv_freesMem(kind)
Definition: driverspecs.h:254
#define _Post_satisfies_(a)
Definition: btrfs_drv.h:167
#define MAXUSHORT
Definition: typedefs.h:81
struct _UNICODE_STRING UNICODE_STRING
#define DPRINT1
Definition: precomp.h:8
#define TAG_RTLREGISTRY
Definition: registry.c:19
NTSTATUS NTAPI RtlCheckRegistryKey(IN ULONG RelativeTo, IN PWSTR Path)
Definition: registry.c:583
#define OUT
Definition: typedefs.h:39
#define c
Definition: ke_i.h:80
unsigned int ULONG
Definition: retypes.h:1
NTSYSAPI VOID NTAPI RtlInitUnicodeString(PUNICODE_STRING DestinationString, PCWSTR SourceString)
#define RTL_REGISTRY_MAXIMUM
Definition: nt_native.h:167
#define ULONG_PTR
Definition: config.h:101
#define InitializeObjectAttributes(p, n, a, r, s)
Definition: reg.c:106
const uint16_t * PCWSTR
Definition: typedefs.h:55
#define REG_NONE
Definition: nt_native.h:1492
GLfloat GLfloat p
Definition: glext.h:8902
NTSTATUS NTAPI RtlCreateRegistryKey(IN ULONG RelativeTo, IN PWSTR Path)
Definition: registry.c:607
_Must_inspect_result_ _Out_writes_to_ DataLength PHIDP_DATA _Inout_ PULONG DataLength
Definition: hidpi.h:333
return STATUS_SUCCESS
Definition: btrfs.c:2710
#define RTL_QUERY_REGISTRY_REQUIRED
Definition: nt_native.h:132
#define OBJ_KERNEL_HANDLE
Definition: winternl.h:231
IN HDEVINFO IN PSP_DEVINFO_DATA DeviceInfoData OPTIONAL
Definition: devinst.c:44
ULONG ACCESS_MASK
Definition: nt_native.h:40
NTSTATUS NTAPI RtlDeleteRegistryValue(IN ULONG RelativeTo, IN PCWSTR Path, IN PCWSTR ValueName)
Definition: registry.c:631
#define RTL_QUERY_REGISTRY_DIRECT
Definition: nt_native.h:144
#define REG_SZ
Definition: layer.c:22