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
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
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.@]
46 NTSTATUS WINAPI
RtlpNtCreateKey( PHANDLE retkey
, ACCESS_MASK access
, const OBJECT_ATTRIBUTES
*attr
,
47 ULONG TitleIndex
, const UNICODE_STRING
*class, ULONG options
,
55 oa
.Attributes
&= ~(OBJ_PERMANENT
|OBJ_EXCLUSIVE
);
59 return NtCreateKey(retkey
, access
, attr
, 0, NULL
, 0, dispos
);
62 /******************************************************************************
63 * RtlpNtOpenKey [NTDLL.@]
67 NTSTATUS WINAPI
RtlpNtOpenKey( PHANDLE retkey
, ACCESS_MASK access
, OBJECT_ATTRIBUTES
*attr
)
70 attr
->Attributes
&= ~(OBJ_PERMANENT
|OBJ_EXCLUSIVE
);
71 return NtOpenKey(retkey
, access
, attr
);
74 /******************************************************************************
75 * RtlpNtMakeTemporaryKey [NTDLL.@]
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
;
96 dwLen
= out
->Length
+ sizeof(KEY_BASIC_INFORMATION
);
97 info
= RtlAllocateHeap( GetProcessHeap(), 0, dwLen
);
99 return STATUS_NO_MEMORY
;
107 ret
= NtEnumerateKey( handle
, index
, KeyBasicInformation
, info
, dwLen
, &dwResultLen
);
108 dwResultLen
-= sizeof(KEY_BASIC_INFORMATION
);
110 if (ret
== STATUS_BUFFER_OVERFLOW
)
111 out
->Length
= dwResultLen
;
114 if (out
->Length
< info
->NameLength
)
116 out
->Length
= dwResultLen
;
117 ret
= STATUS_BUFFER_OVERFLOW
;
121 out
->Length
= info
->NameLength
;
122 memcpy(out
->Buffer
, info
->Name
, info
->NameLength
);
126 RtlFreeHeap( GetProcessHeap(), 0, info
);
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
;
141 DWORD dwLen
= sizeof (KEY_VALUE_PARTIAL_INFORMATION
) + (result_len
? *result_len
: 0);
143 info
= RtlAllocateHeap( GetProcessHeap(), 0, dwLen
);
145 return STATUS_NO_MEMORY
;
148 ret
= NtQueryValueKey( handle
, &name
, KeyValuePartialInformation
, info
, dwLen
, &dwResultLen
);
150 if (!ret
|| ret
== STATUS_BUFFER_OVERFLOW
)
153 *result_len
= info
->DataLength
;
156 *result_type
= info
->Type
;
158 if (ret
!= STATUS_BUFFER_OVERFLOW
)
159 memcpy( dest
, info
->Data
, info
->DataLength
);
162 RtlFreeHeap( GetProcessHeap(), 0, info
);
166 /******************************************************************************
167 * RtlpNtSetValueKey [NTDLL.@]
170 NTSTATUS WINAPI
RtlpNtSetValueKey( HANDLE hkey
, ULONG type
, const void *data
,
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
);
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
));
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
);
211 status
= STATUS_NO_MEMORY
;
217 /******************************************************************************
218 * RtlOpenCurrentUser [NTDLL.@]
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
;
232 TRACE("(0x%08x, %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
);
242 static NTSTATUS
RTL_ReportRegistryValue(PKEY_VALUE_FULL_INFORMATION pInfo
,
243 PRTL_QUERY_REGISTRY_TABLE pQuery
, PVOID pContext
, PVOID pEnvironment
)
246 UNICODE_STRING src
, dst
;
251 NTSTATUS status
= STATUS_SUCCESS
;
258 if (pQuery
->Flags
& RTL_QUERY_REGISTRY_DIRECT
)
259 return STATUS_INVALID_PARAMETER
;
262 status
= pQuery
->QueryRoutine(pQuery
->Name
, pQuery
->DefaultType
, pQuery
->DefaultData
,
263 pQuery
->DefaultLength
, pContext
, pQuery
->EntryContext
);
267 len
= pInfo
->DataLength
;
269 if (pQuery
->Flags
& RTL_QUERY_REGISTRY_DIRECT
)
271 str
= pQuery
->EntryContext
;
276 if (!(pQuery
->Flags
& RTL_QUERY_REGISTRY_NOEXPAND
))
278 RtlInitUnicodeString(&src
, (WCHAR
*)(((CHAR
*)pInfo
) + pInfo
->DataOffset
));
280 dst
.MaximumLength
= 0;
281 RtlExpandEnvironmentStrings_U(pEnvironment
, &src
, &dst
, &res
);
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
);
293 if (str
->Buffer
== NULL
)
294 RtlCreateUnicodeString(str
, (WCHAR
*)(((CHAR
*)pInfo
) + pInfo
->DataOffset
));
296 RtlAppendUnicodeToString(str
, (WCHAR
*)(((CHAR
*)pInfo
) + pInfo
->DataOffset
));
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
);
314 bin
= pQuery
->EntryContext
;
315 if (pInfo
->DataLength
<= sizeof(ULONG
))
316 memcpy(bin
, ((CHAR
*)pInfo
) + pInfo
->DataOffset
,
320 if (bin
[0] <= sizeof(ULONG
))
322 memcpy(&bin
[1], ((CHAR
*)pInfo
) + pInfo
->DataOffset
,
323 min(-bin
[0], pInfo
->DataLength
));
327 len
= min(bin
[0], pInfo
->DataLength
);
329 bin
[2] = pInfo
->Type
;
330 memcpy(&bin
[3], ((CHAR
*)pInfo
) + pInfo
->DataOffset
, len
);
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
));
349 dst
.MaximumLength
= 0;
350 RtlExpandEnvironmentStrings_U(pEnvironment
, &src
, &dst
, &res
);
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
)
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
));
381 dst
.MaximumLength
= 0;
382 RtlExpandEnvironmentStrings_U(pEnvironment
, &src
, &dst
, &res
);
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
)
400 static NTSTATUS
RTL_KeyHandleCreateObject(ULONG RelativeTo
, PCWSTR Path
, POBJECT_ATTRIBUTES regkey
, PUNICODE_STRING str
)
405 static const WCHAR empty
[] = {0};
406 static const WCHAR control
[] = {'\\','R','e','g','i','s','t','r','y','\\','M','a','c','h','i','n','e',
407 '\\','S','y','s','t','e','m','\\','C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\',
408 'C','o','n','t','r','o','l','\\',0};
410 static const WCHAR devicemap
[] = {'\\','R','e','g','i','s','t','r','y','\\','M','a','c','h','i','n','e','\\',
411 'H','a','r','d','w','a','r','e','\\','D','e','v','i','c','e','M','a','p','\\',0};
413 static const WCHAR services
[] = {'\\','R','e','g','i','s','t','r','y','\\','M','a','c','h','i','n','e','\\',
414 'S','y','s','t','e','m','\\','C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\',
415 'S','e','r','v','i','c','e','s','\\',0};
417 static const WCHAR user
[] = {'\\','R','e','g','i','s','t','r','y','\\','U','s','e','r','\\',
418 'C','u','r','r','e','n','t','U','s','e','r','\\',0};
420 static const WCHAR windows_nt
[] = {'\\','R','e','g','i','s','t','r','y','\\','M','a','c','h','i','n','e','\\',
421 'S','o','f','t','w','a','r','e','\\','M','i','c','r','o','s','o','f','t','\\',
422 'W','i','n','d','o','w','s',' ','N','T','\\','C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',0};
424 switch (RelativeTo
& 0xff)
426 case RTL_REGISTRY_ABSOLUTE
:
430 case RTL_REGISTRY_CONTROL
:
434 case RTL_REGISTRY_DEVICEMAP
:
438 case RTL_REGISTRY_SERVICES
:
442 case RTL_REGISTRY_USER
:
446 case RTL_REGISTRY_WINDOWS_NT
:
451 return STATUS_INVALID_PARAMETER
;
454 len
= (wcslen(base
) + wcslen(Path
) + 1) * sizeof(WCHAR
);
455 str
->Buffer
= RtlAllocateHeap(GetProcessHeap(), 0, len
);
456 if (str
->Buffer
== NULL
)
457 return STATUS_NO_MEMORY
;
459 wcscpy(str
->Buffer
, base
);
460 wcscat(str
->Buffer
, Path
);
461 str
->Length
= len
- sizeof(WCHAR
);
462 str
->MaximumLength
= len
;
463 InitializeObjectAttributes(regkey
, str
, OBJ_CASE_INSENSITIVE
, NULL
, NULL
);
464 return STATUS_SUCCESS
;
467 static NTSTATUS
RTL_GetKeyHandle(ULONG RelativeTo
, PCWSTR Path
, PHANDLE handle
)
469 OBJECT_ATTRIBUTES regkey
;
470 UNICODE_STRING string
;
473 status
= RTL_KeyHandleCreateObject(RelativeTo
, Path
, ®key
, &string
);
474 if(status
!= STATUS_SUCCESS
)
477 status
= NtOpenKey(handle
, KEY_ALL_ACCESS
, ®key
);
478 RtlFreeUnicodeString( &string
);
482 /*************************************************************************
483 * RtlQueryRegistryValues [NTDLL.@]
485 * Query multiple registry values with a single call.
488 * RelativeTo [I] Registry path that Path refers to
489 * Path [I] Path to key
490 * QueryTable [I] Table of key values to query
491 * Context [I] Parameter to pass to the application defined QueryRoutine function
492 * Environment [I] Optional parameter to use when performing expansion
495 * STATUS_SUCCESS or an appropriate NTSTATUS error code.
497 NTSTATUS WINAPI
RtlQueryRegistryValues(IN ULONG RelativeTo
, IN PCWSTR Path
,
498 IN PRTL_QUERY_REGISTRY_TABLE QueryTable
, IN PVOID Context
,
499 IN PVOID Environment OPTIONAL
)
501 UNICODE_STRING Value
;
502 HANDLE handle
, topkey
;
503 PKEY_VALUE_FULL_INFORMATION pInfo
= NULL
;
504 ULONG len
, buflen
= 0;
505 NTSTATUS status
=STATUS_SUCCESS
, ret
= STATUS_SUCCESS
;
508 TRACE("(%d, %s, %p, %p, %p)\n", RelativeTo
, debugstr_w(Path
), QueryTable
, Context
, Environment
);
511 return STATUS_INVALID_PARAMETER
;
513 /* get a valid handle */
514 if (RelativeTo
& RTL_REGISTRY_HANDLE
)
515 topkey
= handle
= (HANDLE
)Path
;
518 status
= RTL_GetKeyHandle(RelativeTo
, Path
, &topkey
);
521 if(status
!= STATUS_SUCCESS
)
524 /* Process query table entries */
525 for (; QueryTable
->QueryRoutine
!= NULL
|| QueryTable
->Name
!= NULL
; ++QueryTable
)
527 if (QueryTable
->Flags
&
528 (RTL_QUERY_REGISTRY_SUBKEY
| RTL_QUERY_REGISTRY_TOPKEY
))
530 /* topkey must be kept open just in case we will reuse it later */
531 if (handle
!= topkey
)
534 if (QueryTable
->Flags
& RTL_QUERY_REGISTRY_SUBKEY
)
537 status
= RTL_GetKeyHandle(PtrToUlong(QueryTable
->Name
), Path
, &handle
);
538 if(status
!= STATUS_SUCCESS
)
548 if (QueryTable
->Flags
& RTL_QUERY_REGISTRY_NOVALUE
)
550 QueryTable
->QueryRoutine(QueryTable
->Name
, REG_NONE
, NULL
, 0,
551 Context
, QueryTable
->EntryContext
);
557 if (QueryTable
->Flags
& RTL_QUERY_REGISTRY_REQUIRED
)
559 ret
= STATUS_OBJECT_NAME_NOT_FOUND
;
565 if (QueryTable
->Name
== NULL
)
567 if (QueryTable
->Flags
& RTL_QUERY_REGISTRY_DIRECT
)
569 ret
= STATUS_INVALID_PARAMETER
;
573 /* Report all subkeys */
576 status
= NtEnumerateValueKey(handle
, i
,
577 KeyValueFullInformation
, pInfo
, buflen
, &len
);
578 if (status
== STATUS_NO_MORE_ENTRIES
)
580 if (status
== STATUS_BUFFER_OVERFLOW
||
581 status
== STATUS_BUFFER_TOO_SMALL
)
584 RtlFreeHeap(GetProcessHeap(), 0, pInfo
);
585 pInfo
= RtlAllocateHeap(GetProcessHeap(), 0, buflen
);
586 NtEnumerateValueKey(handle
, i
, KeyValueFullInformation
,
587 pInfo
, buflen
, &len
);
590 status
= RTL_ReportRegistryValue(pInfo
, QueryTable
, Context
, Environment
);
591 if(status
!= STATUS_SUCCESS
&& status
!= STATUS_BUFFER_TOO_SMALL
)
596 if (QueryTable
->Flags
& RTL_QUERY_REGISTRY_DELETE
)
598 RtlInitUnicodeString(&Value
, pInfo
->Name
);
599 NtDeleteValueKey(handle
, &Value
);
603 if (i
== 0 && (QueryTable
->Flags
& RTL_QUERY_REGISTRY_REQUIRED
))
605 ret
= STATUS_OBJECT_NAME_NOT_FOUND
;
611 RtlInitUnicodeString(&Value
, QueryTable
->Name
);
612 status
= NtQueryValueKey(handle
, &Value
, KeyValueFullInformation
,
613 pInfo
, buflen
, &len
);
614 if (status
== STATUS_BUFFER_OVERFLOW
||
615 status
== STATUS_BUFFER_TOO_SMALL
)
618 RtlFreeHeap(GetProcessHeap(), 0, pInfo
);
619 pInfo
= RtlAllocateHeap(GetProcessHeap(), 0, buflen
);
620 status
= NtQueryValueKey(handle
, &Value
,
621 KeyValueFullInformation
, pInfo
, buflen
, &len
);
623 if (status
!= STATUS_SUCCESS
)
625 if (QueryTable
->Flags
& RTL_QUERY_REGISTRY_REQUIRED
)
627 ret
= STATUS_OBJECT_NAME_NOT_FOUND
;
630 status
= RTL_ReportRegistryValue(NULL
, QueryTable
, Context
, Environment
);
631 if(status
!= STATUS_SUCCESS
&& status
!= STATUS_BUFFER_TOO_SMALL
)
639 status
= RTL_ReportRegistryValue(pInfo
, QueryTable
, Context
, Environment
);
640 if(status
!= STATUS_SUCCESS
&& status
!= STATUS_BUFFER_TOO_SMALL
)
645 if (QueryTable
->Flags
& RTL_QUERY_REGISTRY_DELETE
)
646 NtDeleteValueKey(handle
, &Value
);
652 RtlFreeHeap(GetProcessHeap(), 0, pInfo
);
653 if (handle
!= topkey
)
659 /*************************************************************************
660 * RtlCheckRegistryKey [NTDLL.@]
662 * Query multiple registry values with a single call.
665 * RelativeTo [I] Registry path that Path refers to
666 * Path [I] Path to key
669 * STATUS_SUCCESS if the specified key exists, or an NTSTATUS error code.
671 NTSTATUS WINAPI
RtlCheckRegistryKey(IN ULONG RelativeTo
, IN PWSTR Path
)
676 TRACE("(%d, %s)\n", RelativeTo
, debugstr_w(Path
));
678 if(!RelativeTo
&& (Path
== NULL
|| Path
[0] == 0))
679 return STATUS_OBJECT_PATH_SYNTAX_BAD
;
680 if(RelativeTo
& RTL_REGISTRY_HANDLE
)
681 return STATUS_SUCCESS
;
682 if((RelativeTo
<= RTL_REGISTRY_USER
) && (Path
== NULL
|| Path
[0] == 0))
683 return STATUS_SUCCESS
;
685 status
= RTL_GetKeyHandle(RelativeTo
, Path
, &handle
);
686 if (handle
) NtClose(handle
);
687 if (status
== STATUS_INVALID_HANDLE
) status
= STATUS_OBJECT_NAME_NOT_FOUND
;
691 /*************************************************************************
692 * RtlCreateRegistryKey [NTDLL.@]
694 * Add a key to the registry given by absolute or relative path
697 * RelativeTo [I] Registry path that Path refers to
698 * path [I] Path to key
701 * STATUS_SUCCESS or an appropriate NTSTATUS error code.
703 NTSTATUS WINAPI
RtlCreateRegistryKey(ULONG RelativeTo
, PWSTR path
)
705 OBJECT_ATTRIBUTES regkey
;
706 UNICODE_STRING string
;
710 RelativeTo
&= ~RTL_REGISTRY_OPTIONAL
;
712 if (!RelativeTo
&& (path
== NULL
|| path
[0] == 0))
713 return STATUS_OBJECT_PATH_SYNTAX_BAD
;
714 if (RelativeTo
<= RTL_REGISTRY_USER
&& (path
== NULL
|| path
[0] == 0))
715 return STATUS_SUCCESS
;
716 status
= RTL_KeyHandleCreateObject(RelativeTo
, path
, ®key
, &string
);
717 if(status
!= STATUS_SUCCESS
)
720 status
= NtCreateKey(&handle
, KEY_ALL_ACCESS
, ®key
, 0, NULL
, REG_OPTION_NON_VOLATILE
, NULL
);
721 if (handle
) NtClose(handle
);
722 RtlFreeUnicodeString( &string
);
726 /*************************************************************************
727 * RtlDeleteRegistryValue [NTDLL.@]
729 * Query multiple registry values with a single call.
732 * RelativeTo [I] Registry path that Path refers to
733 * Path [I] Path to key
734 * ValueName [I] Name of the value to delete
737 * STATUS_SUCCESS if the specified key is successfully deleted, or an NTSTATUS error code.
739 NTSTATUS WINAPI
RtlDeleteRegistryValue(IN ULONG RelativeTo
, IN PCWSTR Path
, IN PCWSTR ValueName
)
743 UNICODE_STRING Value
;
745 TRACE("(%d, %s, %s)\n", RelativeTo
, debugstr_w(Path
), debugstr_w(ValueName
));
747 RtlInitUnicodeString(&Value
, ValueName
);
748 if(RelativeTo
== RTL_REGISTRY_HANDLE
)
750 return NtDeleteValueKey((HANDLE
)Path
, &Value
);
752 status
= RTL_GetKeyHandle(RelativeTo
, Path
, &handle
);
753 if (status
) return status
;
754 status
= NtDeleteValueKey(handle
, &Value
);
759 /*************************************************************************
760 * RtlWriteRegistryValue [NTDLL.@]
762 * Sets the registry value with provided data.
765 * RelativeTo [I] Registry path that path parameter refers to
766 * path [I] Path to the key (or handle - see RTL_GetKeyHandle)
767 * name [I] Name of the registry value to set
768 * type [I] Type of the registry key to set
769 * data [I] Pointer to the user data to be set
770 * length [I] Length of the user data pointed by data
773 * STATUS_SUCCESS if the specified key is successfully set,
774 * or an NTSTATUS error code.
776 NTSTATUS WINAPI
RtlWriteRegistryValue( ULONG RelativeTo
, PCWSTR path
, PCWSTR name
,
777 ULONG type
, PVOID data
, ULONG length
)
783 TRACE( "(%d, %s, %s) -> %d: %p [%d]\n", RelativeTo
, debugstr_w(path
), debugstr_w(name
),
784 type
, data
, length
);
786 RtlInitUnicodeString( &str
, name
);
788 if (RelativeTo
== RTL_REGISTRY_HANDLE
)
789 return NtSetValueKey( (HANDLE
)path
, &str
, 0, type
, data
, length
);
791 status
= RTL_GetKeyHandle( RelativeTo
, path
, &hkey
);
792 if (status
!= STATUS_SUCCESS
) return status
;
794 status
= NtSetValueKey( hkey
, &str
, 0, type
, data
, length
);