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 switch (RelativeTo
& 0xff)
407 case RTL_REGISTRY_ABSOLUTE
:
411 case RTL_REGISTRY_CONTROL
:
412 base
= L
"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\";
415 case RTL_REGISTRY_DEVICEMAP
:
416 base
= L
"\\Registry\\Machine\\Hardware\\DeviceMap\\";
419 case RTL_REGISTRY_SERVICES
:
420 base
= L
"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\";
423 case RTL_REGISTRY_USER
:
424 base
= L
"\\Registry\\User\\CurrentUser\\";
427 case RTL_REGISTRY_WINDOWS_NT
:
428 base
= L
"\\Registry\\Machine\\Software\\Microsoft\\Windows NT\\CurrentVersion\\";
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
;
454 status
= RTL_KeyHandleCreateObject(RelativeTo
, Path
, ®key
, &string
);
455 if(status
!= STATUS_SUCCESS
)
458 status
= NtOpenKey(handle
, KEY_ALL_ACCESS
, ®key
);
459 RtlFreeUnicodeString( &string
);
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
;
478 TRACE("(%d, %s, %p, %p, %p)\n", RelativeTo
, debugstr_w(Path
), QueryTable
, Context
, Environment
);
481 return STATUS_INVALID_PARAMETER
;
483 /* get a valid handle */
484 if (RelativeTo
& RTL_REGISTRY_HANDLE
)
485 topkey
= handle
= (HANDLE
)Path
;
488 status
= RTL_GetKeyHandle(RelativeTo
, Path
, &topkey
);
491 if(status
!= STATUS_SUCCESS
)
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
)
504 if (QueryTable
->Flags
& RTL_QUERY_REGISTRY_SUBKEY
)
507 status
= RTL_GetKeyHandle(PtrToUlong(QueryTable
->Name
), Path
, &handle
);
508 if(status
!= STATUS_SUCCESS
)
518 if (QueryTable
->Flags
& RTL_QUERY_REGISTRY_NOVALUE
)
520 QueryTable
->QueryRoutine(QueryTable
->Name
, REG_NONE
, NULL
, 0,
521 Context
, QueryTable
->EntryContext
);
527 if (QueryTable
->Flags
& RTL_QUERY_REGISTRY_REQUIRED
)
529 ret
= STATUS_OBJECT_NAME_NOT_FOUND
;
535 if (QueryTable
->Name
== NULL
)
537 if (QueryTable
->Flags
& RTL_QUERY_REGISTRY_DIRECT
)
539 ret
= STATUS_INVALID_PARAMETER
;
543 /* Report all subkeys */
546 status
= NtEnumerateValueKey(handle
, i
,
547 KeyValueFullInformation
, pInfo
, buflen
, &len
);
548 if (status
== STATUS_NO_MORE_ENTRIES
)
550 if (status
== STATUS_BUFFER_OVERFLOW
||
551 status
== STATUS_BUFFER_TOO_SMALL
)
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
)
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
;
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
)
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
;
600 status
= RTL_ReportRegistryValue(NULL
, QueryTable
, Context
, Environment
);
601 if(status
!= STATUS_SUCCESS
&& status
!= STATUS_BUFFER_TOO_SMALL
)
609 status
= RTL_ReportRegistryValue(pInfo
, QueryTable
, Context
, Environment
);
610 if(status
!= STATUS_SUCCESS
&& status
!= STATUS_BUFFER_TOO_SMALL
)
615 if (QueryTable
->Flags
& RTL_QUERY_REGISTRY_DELETE
)
616 NtDeleteValueKey(handle
, &Value
);
622 RtlFreeHeap(GetProcessHeap(), 0, pInfo
);
623 if (handle
!= topkey
)
629 /*************************************************************************
630 * RtlCheckRegistryKey [NTDLL.@]
632 * Query multiple registry values with a single call.
635 * RelativeTo [I] Registry path that Path refers to
636 * Path [I] Path to key
639 * STATUS_SUCCESS if the specified key exists, or an NTSTATUS error code.
641 NTSTATUS WINAPI
RtlCheckRegistryKey(IN ULONG RelativeTo
, IN PWSTR Path
)
646 TRACE("(%d, %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
;
661 /*************************************************************************
662 * RtlCreateRegistryKey [NTDLL.@]
664 * Add a key to the registry given by absolute or relative path
667 * RelativeTo [I] Registry path that Path refers to
668 * path [I] Path to key
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
;
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
, ®key
, &string
);
687 if(status
!= STATUS_SUCCESS
)
690 status
= NtCreateKey(&handle
, KEY_ALL_ACCESS
, ®key
, 0, NULL
, REG_OPTION_NON_VOLATILE
, NULL
);
691 if (handle
) NtClose(handle
);
692 RtlFreeUnicodeString( &string
);
696 /*************************************************************************
697 * RtlDeleteRegistryValue [NTDLL.@]
699 * Query multiple registry values with a single call.
702 * RelativeTo [I] Registry path that Path refers to
703 * Path [I] Path to key
704 * ValueName [I] Name of the value to delete
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
)
713 UNICODE_STRING Value
;
715 TRACE("(%d, %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
);
729 /*************************************************************************
730 * RtlWriteRegistryValue [NTDLL.@]
732 * Sets the registry value with provided data.
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
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
)
753 TRACE( "(%d, %s, %s) -> %d: %p [%d]\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
);