2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * FILE: ntoskrnl/cm/rtlfunc.c
5 * PURPOSE: Rtlxxx function for registry access
11 #include <internal/ob.h>
14 #include <internal/pool.h>
15 #include <internal/registry.h>
18 #include <internal/debug.h>
23 RtlCheckRegistryKey(IN ULONG RelativeTo
,
29 Status
= RtlpGetRegistryHandle(RelativeTo
,
33 if (!NT_SUCCESS(Status
))
38 return STATUS_SUCCESS
;
43 RtlCreateRegistryKey(IN ULONG RelativeTo
,
49 Status
= RtlpGetRegistryHandle(RelativeTo
,
53 if (!NT_SUCCESS(Status
))
58 return STATUS_SUCCESS
;
63 RtlDeleteRegistryValue(IN ULONG RelativeTo
,
71 Status
= RtlpGetRegistryHandle(RelativeTo
,
75 if (!NT_SUCCESS(Status
))
78 RtlInitUnicodeString(&Name
,
81 NtDeleteValueKey(KeyHandle
,
86 return STATUS_SUCCESS
;
91 RtlOpenCurrentUser(IN ACCESS_MASK DesiredAccess
,
92 OUT PHANDLE KeyHandle
)
94 OBJECT_ATTRIBUTES ObjectAttributes
;
95 UNICODE_STRING KeyPath
;
98 Status
= RtlFormatCurrentUserKeyPath(&KeyPath
);
99 if (NT_SUCCESS(Status
))
101 InitializeObjectAttributes(&ObjectAttributes
,
103 OBJ_CASE_INSENSITIVE
,
106 Status
= NtOpenKey(KeyHandle
,
109 RtlFreeUnicodeString(&KeyPath
);
110 if (NT_SUCCESS(Status
))
111 return STATUS_SUCCESS
;
114 RtlInitUnicodeString(&KeyPath
,
115 L
"\\Registry\\User\\.Default");
117 InitializeObjectAttributes(&ObjectAttributes
,
119 OBJ_CASE_INSENSITIVE
,
122 Status
= NtOpenKey(KeyHandle
,
130 RtlQueryRegistryValues(IN ULONG RelativeTo
,
132 IN PRTL_QUERY_REGISTRY_TABLE QueryTable
,
134 IN PVOID Environment
)
137 HANDLE BaseKeyHandle
;
138 HANDLE CurrentKeyHandle
;
139 PRTL_QUERY_REGISTRY_TABLE QueryEntry
;
140 OBJECT_ATTRIBUTES ObjectAttributes
;
141 UNICODE_STRING KeyName
;
142 PKEY_VALUE_PARTIAL_INFORMATION ValueInfo
;
146 DPRINT("RtlQueryRegistryValues() called\n");
148 Status
= RtlpGetRegistryHandle(RelativeTo
,
152 if (!NT_SUCCESS(Status
))
154 DPRINT("RtlpGetRegistryHandle() failed with status %x\n", Status
);
158 CurrentKeyHandle
= BaseKeyHandle
;
159 QueryEntry
= QueryTable
;
160 while ((QueryEntry
->QueryRoutine
!= NULL
) ||
161 (QueryEntry
->Name
!= NULL
))
164 //if ((QueryEntry->QueryRoutine == NULL) &&
165 // ((QueryEntry->Flags & (RTL_QUERY_REGISTRY_SUBKEY | RTL_QUERY_REGISTRY_DIRECT)) != 0))
166 // Which is more correct?
167 if ((QueryEntry
->QueryRoutine
== NULL
) &&
168 ((QueryEntry
->Flags
& RTL_QUERY_REGISTRY_SUBKEY
) != 0))
170 DPRINT("Bad parameters\n");
171 Status
= STATUS_INVALID_PARAMETER
;
175 DPRINT("Name: %S\n", QueryEntry
->Name
);
177 if (((QueryEntry
->Flags
& (RTL_QUERY_REGISTRY_SUBKEY
| RTL_QUERY_REGISTRY_TOPKEY
)) != 0) &&
178 (BaseKeyHandle
!= CurrentKeyHandle
))
180 NtClose(CurrentKeyHandle
);
181 CurrentKeyHandle
= BaseKeyHandle
;
184 if (QueryEntry
->Flags
& RTL_QUERY_REGISTRY_SUBKEY
)
186 DPRINT("Open new subkey: %S\n", QueryEntry
->Name
);
188 RtlInitUnicodeString(&KeyName
,
190 InitializeObjectAttributes(&ObjectAttributes
,
192 OBJ_CASE_INSENSITIVE
,
195 Status
= NtOpenKey(&CurrentKeyHandle
,
198 if (!NT_SUCCESS(Status
))
201 else if (QueryEntry
->Flags
& RTL_QUERY_REGISTRY_DIRECT
)
203 DPRINT("Query value directly: %S\n", QueryEntry
->Name
);
205 RtlInitUnicodeString(&KeyName
,
208 BufferSize
= sizeof (KEY_VALUE_PARTIAL_INFORMATION
) + 4096;
209 ValueInfo
= ExAllocatePool(PagedPool
, BufferSize
);
210 if (ValueInfo
== NULL
)
212 Status
= STATUS_NO_MEMORY
;
216 Status
= ZwQueryValueKey(CurrentKeyHandle
,
218 KeyValuePartialInformation
,
222 if (!NT_SUCCESS(Status
))
224 DPRINT("ZwQueryValueKey() failed with status %x\n", Status
);
225 ExFreePool(ValueInfo
);
230 if (ValueInfo
->Type
== REG_SZ
)
232 PUNICODE_STRING ValueString
;
233 ValueString
= (PUNICODE_STRING
)QueryEntry
->EntryContext
;
234 if (ValueString
->Buffer
== 0)
236 RtlInitUnicodeString(ValueString
, NULL
);
237 ValueString
->MaximumLength
= 256 * sizeof(WCHAR
);
238 ValueString
->Buffer
= ExAllocatePool(PagedPool
, ValueString
->MaximumLength
);
239 if (!ValueString
->Buffer
)
241 ValueString
->Buffer
[0] = 0;
243 ValueString
->Length
= RtlMin(ValueInfo
->DataLength
,
244 ValueString
->MaximumLength
- sizeof(WCHAR
));
245 memcpy(ValueString
->Buffer
,
247 ValueInfo
->DataLength
);
248 ((PWSTR
)ValueString
->Buffer
)[ValueString
->Length
/ sizeof(WCHAR
)] = 0;
252 memcpy(QueryEntry
->EntryContext
,
254 ValueInfo
->DataLength
);
258 ExFreePool (ValueInfo
);
262 DPRINT("Query value via query routine: %S\n", QueryEntry
->Name
);
266 if (QueryEntry
->Flags
& RTL_QUERY_REGISTRY_DELETE
)
268 DPRINT("Delete value: %S\n", QueryEntry
->Name
);
275 if (CurrentKeyHandle
!= BaseKeyHandle
)
276 NtClose(CurrentKeyHandle
);
278 NtClose(BaseKeyHandle
);
285 RtlWriteRegistryValue(IN ULONG RelativeTo
,
290 IN ULONG ValueLength
)
296 Status
= RtlpGetRegistryHandle(RelativeTo
,
300 if (!NT_SUCCESS(Status
))
303 RtlInitUnicodeString(&Name
,
306 NtSetValueKey(KeyHandle
,
315 return STATUS_SUCCESS
;
319 RtlFormatCurrentUserKeyPath(IN OUT PUNICODE_STRING KeyPath
)
322 RtlCreateUnicodeString(KeyPath
,
323 L
"\\Registry\\User\\.Default");
325 return STATUS_SUCCESS
;
328 /* ------------------------------------------ Private Implementation */
332 RtlpGetRegistryHandle(ULONG RelativeTo
,
337 UNICODE_STRING KeyName
;
338 WCHAR KeyBuffer
[MAX_PATH
];
339 OBJECT_ATTRIBUTES ObjectAttributes
;
342 if (RelativeTo
& RTL_REGISTRY_HANDLE
)
344 Status
= NtDuplicateObject(
345 PsGetCurrentProcessId(),
347 PsGetCurrentProcessId(),
351 DUPLICATE_SAME_ACCESS
);
355 if (RelativeTo
& RTL_REGISTRY_OPTIONAL
)
356 RelativeTo
&= ~RTL_REGISTRY_OPTIONAL
;
358 if (RelativeTo
>= RTL_REGISTRY_MAXIMUM
)
359 return STATUS_INVALID_PARAMETER
;
362 KeyName
.MaximumLength
= MAX_PATH
;
363 KeyName
.Buffer
= KeyBuffer
;
368 case RTL_REGISTRY_SERVICES
:
369 RtlAppendUnicodeToString(&KeyName
,
370 L
"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\");
373 case RTL_REGISTRY_CONTROL
:
374 RtlAppendUnicodeToString(&KeyName
,
375 L
"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\");
378 case RTL_REGISTRY_WINDOWS_NT
:
379 RtlAppendUnicodeToString(&KeyName
,
380 L
"\\Registry\\Machine\\Software\\Microsoft\\Windows NT\\CurrentVersion\\");
383 case RTL_REGISTRY_DEVICEMAP
:
384 RtlAppendUnicodeToString(&KeyName
,
385 L
"\\Registry\\Machine\\Hardware\\DeviceMap\\");
388 case RTL_REGISTRY_USER
:
389 Status
= RtlFormatCurrentUserKeyPath(&KeyName
);
390 if (!NT_SUCCESS(Status
))
394 /* ReactOS specific */
395 case RTL_REGISTRY_ENUM
:
396 RtlAppendUnicodeToString(&KeyName
,
397 L
"\\Registry\\Machine\\System\\CurrentControlSet\\Enum\\");
401 if (Path
[0] != L
'\\')
403 RtlAppendUnicodeToString(&KeyName
,
409 RtlAppendUnicodeToString(&KeyName
,
413 InitializeObjectAttributes(&ObjectAttributes
,
415 OBJ_CASE_INSENSITIVE
,
421 Status
= NtCreateKey(KeyHandle
,
431 Status
= NtOpenKey(KeyHandle
,
441 RtlpCreateRegistryKeyPath(PWSTR Path
)
443 OBJECT_ATTRIBUTES ObjectAttributes
;
444 WCHAR KeyBuffer
[MAX_PATH
];
445 UNICODE_STRING KeyName
;
451 if (_wcsnicmp(Path
, L
"\\Registry\\", 10) != 0)
453 return STATUS_INVALID_PARAMETER
;
456 wcsncpy(KeyBuffer
, Path
, MAX_PATH
-1);
457 RtlInitUnicodeString(&KeyName
, KeyBuffer
);
459 /* Skip \\Registry\\ */
460 Current
= KeyName
.Buffer
;
461 Current
= wcschr(Current
, '\\') + 1;
462 Current
= wcschr(Current
, '\\') + 1;
465 Next
= wcschr(Current
, '\\');
475 InitializeObjectAttributes(
478 OBJ_CASE_INSENSITIVE
,
482 DPRINT("Create '%S'\n", KeyName
.Buffer
);
484 Status
= NtCreateKey(
492 if (!NT_SUCCESS(Status
))
494 DPRINT("NtCreateKey() failed with status %x\n", Status
);
506 } while (Next
!= NULL
);
508 return STATUS_SUCCESS
;