windows.networking.hostname/tests: Add IHostNameFactory::CreateHostName() tests.
[wine.git] / dlls / ntdll / reg.c
blob57208d5d811d07e0b98ce471191c44c4cb4069d2
1 /*
2 * Registry functions
4 * Copyright (C) 1999 Juergen Schmied
5 * Copyright (C) 2000 Alexandre Julliard
6 * Copyright 2005 Ivan Leo Puoti, Laurent Pinchart
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
22 * NOTES:
23 * HKEY_LOCAL_MACHINE \\REGISTRY\\MACHINE
24 * HKEY_USERS \\REGISTRY\\USER
25 * HKEY_CURRENT_CONFIG \\REGISTRY\\MACHINE\\SYSTEM\\CURRENTCONTROLSET\\HARDWARE PROFILES\\CURRENT
26 * HKEY_CLASSES \\REGISTRY\\MACHINE\\SOFTWARE\\CLASSES
29 #include <stdarg.h>
30 #include <stdio.h>
31 #include <string.h>
33 #include "ntstatus.h"
34 #define WIN32_NO_STATUS
35 #include "ntdll_misc.h"
36 #include "wine/debug.h"
38 WINE_DEFAULT_DEBUG_CHANNEL(reg);
41 /******************************************************************************
42 * RtlpNtCreateKey [NTDLL.@]
44 * See NtCreateKey.
46 NTSTATUS WINAPI RtlpNtCreateKey( PHANDLE retkey, ACCESS_MASK access, const OBJECT_ATTRIBUTES *attr,
47 ULONG TitleIndex, const UNICODE_STRING *class, ULONG options,
48 PULONG dispos )
50 OBJECT_ATTRIBUTES oa;
52 if (attr)
54 oa = *attr;
55 oa.Attributes &= ~(OBJ_PERMANENT|OBJ_EXCLUSIVE);
56 attr = &oa;
59 return NtCreateKey(retkey, access, attr, 0, NULL, 0, dispos);
62 /******************************************************************************
63 * RtlpNtOpenKey [NTDLL.@]
65 * See NtOpenKey.
67 NTSTATUS WINAPI RtlpNtOpenKey( PHANDLE retkey, ACCESS_MASK access, OBJECT_ATTRIBUTES *attr )
69 if (attr)
70 attr->Attributes &= ~(OBJ_PERMANENT|OBJ_EXCLUSIVE);
71 return NtOpenKey(retkey, access, attr);
74 /******************************************************************************
75 * RtlpNtMakeTemporaryKey [NTDLL.@]
77 * See NtDeleteKey.
79 NTSTATUS WINAPI RtlpNtMakeTemporaryKey( HANDLE hkey )
81 return NtDeleteKey(hkey);
84 /******************************************************************************
85 * RtlpNtEnumerateSubKey [NTDLL.@]
88 NTSTATUS WINAPI RtlpNtEnumerateSubKey( HANDLE handle, UNICODE_STRING *out, ULONG index )
90 KEY_BASIC_INFORMATION *info;
91 DWORD dwLen, dwResultLen;
92 NTSTATUS ret;
94 if (out->MaximumLength)
96 dwLen = out->MaximumLength + offsetof(KEY_BASIC_INFORMATION, Name);
97 info = RtlAllocateHeap( GetProcessHeap(), 0, dwLen );
98 if (!info)
99 return STATUS_NO_MEMORY;
101 else
103 dwLen = 0;
104 info = NULL;
107 ret = NtEnumerateKey( handle, index, KeyBasicInformation, info, dwLen, &dwResultLen );
108 dwResultLen -= offsetof(KEY_BASIC_INFORMATION, Name);
110 if (ret == STATUS_BUFFER_OVERFLOW)
111 out->Length = dwResultLen;
112 else if (!ret)
114 if (out->MaximumLength < info->NameLength)
116 out->Length = dwResultLen;
117 ret = STATUS_BUFFER_OVERFLOW;
119 else
121 out->Length = info->NameLength;
122 memcpy(out->Buffer, info->Name, info->NameLength);
126 RtlFreeHeap( GetProcessHeap(), 0, info );
127 return ret;
130 /******************************************************************************
131 * RtlpNtQueryValueKey [NTDLL.@]
134 NTSTATUS WINAPI RtlpNtQueryValueKey( HANDLE handle, ULONG *result_type, PBYTE dest,
135 DWORD *result_len, void *unknown )
137 KEY_VALUE_PARTIAL_INFORMATION *info;
138 UNICODE_STRING name;
139 NTSTATUS ret;
140 DWORD dwResultLen;
141 DWORD dwLen = offsetof(KEY_VALUE_PARTIAL_INFORMATION, Data[result_len ? *result_len : 0]);
143 info = RtlAllocateHeap( GetProcessHeap(), 0, dwLen );
144 if (!info)
145 return STATUS_NO_MEMORY;
147 name.Length = 0;
148 ret = NtQueryValueKey( handle, &name, KeyValuePartialInformation, info, dwLen, &dwResultLen );
150 if (!ret || ret == STATUS_BUFFER_OVERFLOW)
152 if (result_len)
153 *result_len = info->DataLength;
155 if (result_type)
156 *result_type = info->Type;
158 if (ret != STATUS_BUFFER_OVERFLOW)
159 memcpy( dest, info->Data, info->DataLength );
162 RtlFreeHeap( GetProcessHeap(), 0, info );
163 return ret;
166 /******************************************************************************
167 * RtlpNtSetValueKey [NTDLL.@]
170 NTSTATUS WINAPI RtlpNtSetValueKey( HANDLE hkey, ULONG type, const void *data,
171 ULONG count )
173 UNICODE_STRING name;
175 name.Length = 0;
176 return NtSetValueKey( hkey, &name, 0, type, data, count );
179 /******************************************************************************
180 * RtlFormatCurrentUserKeyPath [NTDLL.@]
183 NTSTATUS WINAPI RtlFormatCurrentUserKeyPath( IN OUT PUNICODE_STRING KeyPath)
185 static const WCHAR pathW[] = {'\\','R','e','g','i','s','t','r','y','\\','U','s','e','r','\\'};
186 char buffer[sizeof(TOKEN_USER) + sizeof(SID) + sizeof(DWORD)*SID_MAX_SUB_AUTHORITIES];
187 DWORD len = sizeof(buffer);
188 NTSTATUS status;
190 status = NtQueryInformationToken(GetCurrentThreadEffectiveToken(), TokenUser, buffer, len, &len);
191 if (status == STATUS_SUCCESS)
193 KeyPath->MaximumLength = 0;
194 status = RtlConvertSidToUnicodeString(KeyPath, ((TOKEN_USER *)buffer)->User.Sid, FALSE);
195 if (status == STATUS_BUFFER_OVERFLOW)
197 PWCHAR buf = RtlAllocateHeap(GetProcessHeap(), 0,
198 sizeof(pathW) + KeyPath->Length + sizeof(WCHAR));
199 if (buf)
201 memcpy(buf, pathW, sizeof(pathW));
202 KeyPath->MaximumLength = KeyPath->Length + sizeof(WCHAR);
203 KeyPath->Buffer = (PWCHAR)((LPBYTE)buf + sizeof(pathW));
204 status = RtlConvertSidToUnicodeString(KeyPath,
205 ((TOKEN_USER *)buffer)->User.Sid, FALSE);
206 KeyPath->Buffer = buf;
207 KeyPath->Length += sizeof(pathW);
208 KeyPath->MaximumLength += sizeof(pathW);
210 else
211 status = STATUS_NO_MEMORY;
214 return status;
217 /******************************************************************************
218 * RtlOpenCurrentUser [NTDLL.@]
220 * NOTES
221 * If we return just HKEY_CURRENT_USER the advapi tries to find a remote
222 * registry (odd handle) and fails.
224 NTSTATUS WINAPI RtlOpenCurrentUser(
225 IN ACCESS_MASK DesiredAccess, /* [in] */
226 OUT PHANDLE KeyHandle) /* [out] handle of HKEY_CURRENT_USER */
228 OBJECT_ATTRIBUTES ObjectAttributes;
229 UNICODE_STRING ObjectName;
230 NTSTATUS ret;
232 TRACE("(0x%08lx, %p)\n",DesiredAccess, KeyHandle);
234 if ((ret = RtlFormatCurrentUserKeyPath(&ObjectName))) return ret;
235 InitializeObjectAttributes(&ObjectAttributes,&ObjectName,OBJ_CASE_INSENSITIVE,0, NULL);
236 ret = NtCreateKey(KeyHandle, DesiredAccess, &ObjectAttributes, 0, NULL, 0, NULL);
237 RtlFreeUnicodeString(&ObjectName);
238 return ret;
242 static NTSTATUS RTL_ReportRegistryValue(PKEY_VALUE_FULL_INFORMATION pInfo,
243 PRTL_QUERY_REGISTRY_TABLE pQuery, PVOID pContext, PVOID pEnvironment)
245 PUNICODE_STRING str;
246 UNICODE_STRING src, dst;
247 LONG *bin;
248 ULONG offset;
249 PWSTR wstr;
250 DWORD res;
251 NTSTATUS status = STATUS_SUCCESS;
252 ULONG len;
253 LPWSTR String;
254 ULONG count = 0;
256 if (pInfo == NULL)
258 if (pQuery->Flags & RTL_QUERY_REGISTRY_DIRECT)
259 return STATUS_INVALID_PARAMETER;
260 else
262 status = pQuery->QueryRoutine(pQuery->Name, pQuery->DefaultType, pQuery->DefaultData,
263 pQuery->DefaultLength, pContext, pQuery->EntryContext);
265 return status;
267 len = pInfo->DataLength;
269 if (pQuery->Flags & RTL_QUERY_REGISTRY_DIRECT)
271 str = pQuery->EntryContext;
273 switch(pInfo->Type)
275 case REG_EXPAND_SZ:
276 if (!(pQuery->Flags & RTL_QUERY_REGISTRY_NOEXPAND))
278 RtlInitUnicodeString(&src, (WCHAR*)(((CHAR*)pInfo) + pInfo->DataOffset));
279 res = 0;
280 dst.MaximumLength = 0;
281 RtlExpandEnvironmentStrings_U(pEnvironment, &src, &dst, &res);
282 dst.Length = 0;
283 dst.MaximumLength = res;
284 dst.Buffer = RtlAllocateHeap(GetProcessHeap(), 0, res * sizeof(WCHAR));
285 RtlExpandEnvironmentStrings_U(pEnvironment, &src, &dst, &res);
286 status = pQuery->QueryRoutine(pQuery->Name, pInfo->Type, dst.Buffer,
287 dst.Length, pContext, pQuery->EntryContext);
288 RtlFreeHeap(GetProcessHeap(), 0, dst.Buffer);
291 case REG_SZ:
292 case REG_LINK:
293 if (str->Buffer == NULL)
294 RtlCreateUnicodeString(str, (WCHAR*)(((CHAR*)pInfo) + pInfo->DataOffset));
295 else
296 RtlAppendUnicodeToString(str, (WCHAR*)(((CHAR*)pInfo) + pInfo->DataOffset));
297 break;
299 case REG_MULTI_SZ:
300 if (!(pQuery->Flags & RTL_QUERY_REGISTRY_NOEXPAND))
301 return STATUS_INVALID_PARAMETER;
303 if (str->Buffer == NULL)
305 str->Buffer = RtlAllocateHeap(GetProcessHeap(), 0, len);
306 str->MaximumLength = len;
308 len = min(len, str->MaximumLength);
309 memcpy(str->Buffer, ((CHAR*)pInfo) + pInfo->DataOffset, len);
310 str->Length = len;
311 break;
313 default:
314 bin = pQuery->EntryContext;
315 if (pInfo->DataLength <= sizeof(ULONG))
316 memcpy(bin, ((CHAR*)pInfo) + pInfo->DataOffset,
317 pInfo->DataLength);
318 else
320 if (bin[0] <= sizeof(ULONG))
322 memcpy(&bin[1], ((CHAR*)pInfo) + pInfo->DataOffset,
323 min(-bin[0], pInfo->DataLength));
325 else
327 len = min(bin[0], pInfo->DataLength);
328 bin[1] = len;
329 bin[2] = pInfo->Type;
330 memcpy(&bin[3], ((CHAR*)pInfo) + pInfo->DataOffset, len);
333 break;
336 else
338 if((pQuery->Flags & RTL_QUERY_REGISTRY_NOEXPAND) ||
339 (pInfo->Type != REG_EXPAND_SZ && pInfo->Type != REG_MULTI_SZ))
341 status = pQuery->QueryRoutine(pQuery->Name, pInfo->Type,
342 ((CHAR*)pInfo) + pInfo->DataOffset, pInfo->DataLength,
343 pContext, pQuery->EntryContext);
345 else if (pInfo->Type == REG_EXPAND_SZ)
347 RtlInitUnicodeString(&src, (WCHAR*)(((CHAR*)pInfo) + pInfo->DataOffset));
348 res = 0;
349 dst.MaximumLength = 0;
350 RtlExpandEnvironmentStrings_U(pEnvironment, &src, &dst, &res);
351 dst.Length = 0;
352 dst.MaximumLength = res;
353 dst.Buffer = RtlAllocateHeap(GetProcessHeap(), 0, res * sizeof(WCHAR));
354 RtlExpandEnvironmentStrings_U(pEnvironment, &src, &dst, &res);
355 status = pQuery->QueryRoutine(pQuery->Name, pInfo->Type, dst.Buffer,
356 dst.Length, pContext, pQuery->EntryContext);
357 RtlFreeHeap(GetProcessHeap(), 0, dst.Buffer);
359 else /* REG_MULTI_SZ */
361 if(pQuery->Flags & RTL_QUERY_REGISTRY_NOEXPAND)
363 for (offset = 0; offset <= pInfo->DataLength; offset += len + sizeof(WCHAR))
365 wstr = (WCHAR*)(((CHAR*)pInfo) + offset);
366 len = wcslen(wstr) * sizeof(WCHAR);
367 status = pQuery->QueryRoutine(pQuery->Name, pInfo->Type, wstr, len,
368 pContext, pQuery->EntryContext);
369 if(status != STATUS_SUCCESS && status != STATUS_BUFFER_TOO_SMALL)
370 return status;
373 else
375 while(count<=pInfo->DataLength)
377 String = (WCHAR*)(((CHAR*)pInfo) + pInfo->DataOffset)+count;
378 count+=wcslen(String)+1;
379 RtlInitUnicodeString(&src, (WCHAR*)(((CHAR*)pInfo) + pInfo->DataOffset));
380 res = 0;
381 dst.MaximumLength = 0;
382 RtlExpandEnvironmentStrings_U(pEnvironment, &src, &dst, &res);
383 dst.Length = 0;
384 dst.MaximumLength = res;
385 dst.Buffer = RtlAllocateHeap(GetProcessHeap(), 0, res * sizeof(WCHAR));
386 RtlExpandEnvironmentStrings_U(pEnvironment, &src, &dst, &res);
387 status = pQuery->QueryRoutine(pQuery->Name, pInfo->Type, dst.Buffer,
388 dst.Length, pContext, pQuery->EntryContext);
389 RtlFreeHeap(GetProcessHeap(), 0, dst.Buffer);
390 if(status != STATUS_SUCCESS && status != STATUS_BUFFER_TOO_SMALL)
391 return status;
396 return status;
400 static NTSTATUS RTL_KeyHandleCreateObject(ULONG RelativeTo, PCWSTR Path, POBJECT_ATTRIBUTES regkey, PUNICODE_STRING str)
402 PCWSTR base;
403 INT len;
405 switch (RelativeTo & 0xff)
407 case RTL_REGISTRY_ABSOLUTE:
408 base = L"";
409 break;
411 case RTL_REGISTRY_CONTROL:
412 base = L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\";
413 break;
415 case RTL_REGISTRY_DEVICEMAP:
416 base = L"\\Registry\\Machine\\Hardware\\DeviceMap\\";
417 break;
419 case RTL_REGISTRY_SERVICES:
420 base = L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\";
421 break;
423 case RTL_REGISTRY_USER:
424 base = L"\\Registry\\User\\CurrentUser\\";
425 break;
427 case RTL_REGISTRY_WINDOWS_NT:
428 base = L"\\Registry\\Machine\\Software\\Microsoft\\Windows NT\\CurrentVersion\\";
429 break;
431 default:
432 return STATUS_INVALID_PARAMETER;
435 len = (wcslen(base) + wcslen(Path) + 1) * sizeof(WCHAR);
436 str->Buffer = RtlAllocateHeap(GetProcessHeap(), 0, len);
437 if (str->Buffer == NULL)
438 return STATUS_NO_MEMORY;
440 wcscpy(str->Buffer, base);
441 wcscat(str->Buffer, Path);
442 str->Length = len - sizeof(WCHAR);
443 str->MaximumLength = len;
444 InitializeObjectAttributes(regkey, str, OBJ_CASE_INSENSITIVE, NULL, NULL);
445 return STATUS_SUCCESS;
448 static NTSTATUS RTL_GetKeyHandle(ULONG RelativeTo, PCWSTR Path, PHANDLE handle)
450 OBJECT_ATTRIBUTES regkey;
451 UNICODE_STRING string;
452 NTSTATUS status;
454 status = RTL_KeyHandleCreateObject(RelativeTo, Path, &regkey, &string);
455 if(status != STATUS_SUCCESS)
456 return status;
458 status = NtOpenKey(handle, KEY_ALL_ACCESS, &regkey);
459 RtlFreeUnicodeString( &string );
460 return status;
463 /******************************************************************************
464 * RtlQueryRegistryValues (NTDLL.@)
465 * RtlQueryRegistryValuesEx (NTDLL.@)
467 NTSTATUS WINAPI RtlQueryRegistryValues(IN ULONG RelativeTo, IN PCWSTR Path,
468 IN PRTL_QUERY_REGISTRY_TABLE QueryTable, IN PVOID Context,
469 IN PVOID Environment OPTIONAL)
471 UNICODE_STRING Value;
472 HANDLE handle, topkey;
473 PKEY_VALUE_FULL_INFORMATION pInfo = NULL;
474 ULONG len, buflen = 0;
475 NTSTATUS status=STATUS_SUCCESS, ret = STATUS_SUCCESS;
476 INT i;
478 TRACE("(%ld, %s, %p, %p, %p)\n", RelativeTo, debugstr_w(Path), QueryTable, Context, Environment);
480 if(Path == NULL)
481 return STATUS_INVALID_PARAMETER;
483 /* get a valid handle */
484 if (RelativeTo & RTL_REGISTRY_HANDLE)
485 topkey = handle = (HANDLE)Path;
486 else
488 status = RTL_GetKeyHandle(RelativeTo, Path, &topkey);
489 handle = topkey;
491 if(status != STATUS_SUCCESS)
492 return status;
494 /* Process query table entries */
495 for (; QueryTable->QueryRoutine != NULL || QueryTable->Name != NULL; ++QueryTable)
497 if (QueryTable->Flags &
498 (RTL_QUERY_REGISTRY_SUBKEY | RTL_QUERY_REGISTRY_TOPKEY))
500 /* topkey must be kept open just in case we will reuse it later */
501 if (handle != topkey)
502 NtClose(handle);
504 if (QueryTable->Flags & RTL_QUERY_REGISTRY_SUBKEY)
506 handle = 0;
507 status = RTL_GetKeyHandle(PtrToUlong(QueryTable->Name), Path, &handle);
508 if(status != STATUS_SUCCESS)
510 ret = status;
511 goto out;
514 else
515 handle = topkey;
518 if (QueryTable->Flags & RTL_QUERY_REGISTRY_NOVALUE)
520 QueryTable->QueryRoutine(QueryTable->Name, REG_NONE, NULL, 0,
521 Context, QueryTable->EntryContext);
522 continue;
525 if (!handle)
527 if (QueryTable->Flags & RTL_QUERY_REGISTRY_REQUIRED)
529 ret = STATUS_OBJECT_NAME_NOT_FOUND;
530 goto out;
532 continue;
535 if (QueryTable->Name == NULL)
537 if (QueryTable->Flags & RTL_QUERY_REGISTRY_DIRECT)
539 ret = STATUS_INVALID_PARAMETER;
540 goto out;
543 /* Report all subkeys */
544 for (i = 0;; ++i)
546 status = NtEnumerateValueKey(handle, i,
547 KeyValueFullInformation, pInfo, buflen, &len);
548 if (status == STATUS_NO_MORE_ENTRIES)
549 break;
550 if (status == STATUS_BUFFER_OVERFLOW ||
551 status == STATUS_BUFFER_TOO_SMALL)
553 buflen = len;
554 RtlFreeHeap(GetProcessHeap(), 0, pInfo);
555 pInfo = RtlAllocateHeap(GetProcessHeap(), 0, buflen);
556 NtEnumerateValueKey(handle, i, KeyValueFullInformation,
557 pInfo, buflen, &len);
560 status = RTL_ReportRegistryValue(pInfo, QueryTable, Context, Environment);
561 if(status != STATUS_SUCCESS && status != STATUS_BUFFER_TOO_SMALL)
563 ret = status;
564 goto out;
566 if (QueryTable->Flags & RTL_QUERY_REGISTRY_DELETE)
568 RtlInitUnicodeString(&Value, pInfo->Name);
569 NtDeleteValueKey(handle, &Value);
573 if (i == 0 && (QueryTable->Flags & RTL_QUERY_REGISTRY_REQUIRED))
575 ret = STATUS_OBJECT_NAME_NOT_FOUND;
576 goto out;
579 else
581 RtlInitUnicodeString(&Value, QueryTable->Name);
582 status = NtQueryValueKey(handle, &Value, KeyValueFullInformation,
583 pInfo, buflen, &len);
584 if (status == STATUS_BUFFER_OVERFLOW ||
585 status == STATUS_BUFFER_TOO_SMALL)
587 buflen = len;
588 RtlFreeHeap(GetProcessHeap(), 0, pInfo);
589 pInfo = RtlAllocateHeap(GetProcessHeap(), 0, buflen);
590 status = NtQueryValueKey(handle, &Value,
591 KeyValueFullInformation, pInfo, buflen, &len);
593 if (status != STATUS_SUCCESS)
595 if (QueryTable->Flags & RTL_QUERY_REGISTRY_REQUIRED)
597 ret = STATUS_OBJECT_NAME_NOT_FOUND;
598 goto out;
600 status = RTL_ReportRegistryValue(NULL, QueryTable, Context, Environment);
601 if(status != STATUS_SUCCESS && status != STATUS_BUFFER_TOO_SMALL)
603 ret = status;
604 goto out;
607 else
609 status = RTL_ReportRegistryValue(pInfo, QueryTable, Context, Environment);
610 if(status != STATUS_SUCCESS && status != STATUS_BUFFER_TOO_SMALL)
612 ret = status;
613 goto out;
615 if (QueryTable->Flags & RTL_QUERY_REGISTRY_DELETE)
616 NtDeleteValueKey(handle, &Value);
621 out:
622 RtlFreeHeap(GetProcessHeap(), 0, pInfo);
623 if (handle != topkey)
624 NtClose(handle);
625 NtClose(topkey);
626 return ret;
629 /*************************************************************************
630 * RtlCheckRegistryKey [NTDLL.@]
632 * Query multiple registry values with a single call.
634 * PARAMS
635 * RelativeTo [I] Registry path that Path refers to
636 * Path [I] Path to key
638 * RETURNS
639 * STATUS_SUCCESS if the specified key exists, or an NTSTATUS error code.
641 NTSTATUS WINAPI RtlCheckRegistryKey(IN ULONG RelativeTo, IN PWSTR Path)
643 HANDLE handle;
644 NTSTATUS status;
646 TRACE("(%ld, %s)\n", RelativeTo, debugstr_w(Path));
648 if(!RelativeTo && (Path == NULL || Path[0] == 0))
649 return STATUS_OBJECT_PATH_SYNTAX_BAD;
650 if(RelativeTo & RTL_REGISTRY_HANDLE)
651 return STATUS_SUCCESS;
652 if((RelativeTo <= RTL_REGISTRY_USER) && (Path == NULL || Path[0] == 0))
653 return STATUS_SUCCESS;
655 status = RTL_GetKeyHandle(RelativeTo, Path, &handle);
656 if (handle) NtClose(handle);
657 if (status == STATUS_INVALID_HANDLE) status = STATUS_OBJECT_NAME_NOT_FOUND;
658 return status;
661 /*************************************************************************
662 * RtlCreateRegistryKey [NTDLL.@]
664 * Add a key to the registry given by absolute or relative path
666 * PARAMS
667 * RelativeTo [I] Registry path that Path refers to
668 * path [I] Path to key
670 * RETURNS
671 * STATUS_SUCCESS or an appropriate NTSTATUS error code.
673 NTSTATUS WINAPI RtlCreateRegistryKey(ULONG RelativeTo, PWSTR path)
675 OBJECT_ATTRIBUTES regkey;
676 UNICODE_STRING string;
677 HANDLE handle;
678 NTSTATUS status;
680 RelativeTo &= ~RTL_REGISTRY_OPTIONAL;
682 if (!RelativeTo && (path == NULL || path[0] == 0))
683 return STATUS_OBJECT_PATH_SYNTAX_BAD;
684 if (RelativeTo <= RTL_REGISTRY_USER && (path == NULL || path[0] == 0))
685 return STATUS_SUCCESS;
686 status = RTL_KeyHandleCreateObject(RelativeTo, path, &regkey, &string);
687 if(status != STATUS_SUCCESS)
688 return status;
690 status = NtCreateKey(&handle, KEY_ALL_ACCESS, &regkey, 0, NULL, REG_OPTION_NON_VOLATILE, NULL);
691 if (handle) NtClose(handle);
692 RtlFreeUnicodeString( &string );
693 return status;
696 /*************************************************************************
697 * RtlDeleteRegistryValue [NTDLL.@]
699 * Query multiple registry values with a single call.
701 * PARAMS
702 * RelativeTo [I] Registry path that Path refers to
703 * Path [I] Path to key
704 * ValueName [I] Name of the value to delete
706 * RETURNS
707 * STATUS_SUCCESS if the specified key is successfully deleted, or an NTSTATUS error code.
709 NTSTATUS WINAPI RtlDeleteRegistryValue(IN ULONG RelativeTo, IN PCWSTR Path, IN PCWSTR ValueName)
711 NTSTATUS status;
712 HANDLE handle;
713 UNICODE_STRING Value;
715 TRACE("(%ld, %s, %s)\n", RelativeTo, debugstr_w(Path), debugstr_w(ValueName));
717 RtlInitUnicodeString(&Value, ValueName);
718 if(RelativeTo == RTL_REGISTRY_HANDLE)
720 return NtDeleteValueKey((HANDLE)Path, &Value);
722 status = RTL_GetKeyHandle(RelativeTo, Path, &handle);
723 if (status) return status;
724 status = NtDeleteValueKey(handle, &Value);
725 NtClose(handle);
726 return status;
729 /*************************************************************************
730 * RtlWriteRegistryValue [NTDLL.@]
732 * Sets the registry value with provided data.
734 * PARAMS
735 * RelativeTo [I] Registry path that path parameter refers to
736 * path [I] Path to the key (or handle - see RTL_GetKeyHandle)
737 * name [I] Name of the registry value to set
738 * type [I] Type of the registry key to set
739 * data [I] Pointer to the user data to be set
740 * length [I] Length of the user data pointed by data
742 * RETURNS
743 * STATUS_SUCCESS if the specified key is successfully set,
744 * or an NTSTATUS error code.
746 NTSTATUS WINAPI RtlWriteRegistryValue( ULONG RelativeTo, PCWSTR path, PCWSTR name,
747 ULONG type, PVOID data, ULONG length )
749 HANDLE hkey;
750 NTSTATUS status;
751 UNICODE_STRING str;
753 TRACE( "(%ld, %s, %s) -> %ld: %p [%ld]\n", RelativeTo, debugstr_w(path), debugstr_w(name),
754 type, data, length );
756 RtlInitUnicodeString( &str, name );
758 if (RelativeTo == RTL_REGISTRY_HANDLE)
759 return NtSetValueKey( (HANDLE)path, &str, 0, type, data, length );
761 status = RTL_GetKeyHandle( RelativeTo, path, &hkey );
762 if (status != STATUS_SUCCESS) return status;
764 status = NtSetValueKey( hkey, &str, 0, type, data, length );
765 NtClose( hkey );
767 return status;