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
30 #include "wine/port.h"
37 #define WIN32_NO_STATUS
38 #include "wine/library.h"
39 #include "ntdll_misc.h"
40 #include "wine/debug.h"
41 #include "wine/unicode.h"
43 WINE_DEFAULT_DEBUG_CHANNEL(reg
);
45 /* maximum length of a value name in bytes (without terminating null) */
46 #define MAX_VALUE_LENGTH (16383 * sizeof(WCHAR))
48 /******************************************************************************
49 * NtCreateKey [NTDLL.@]
50 * ZwCreateKey [NTDLL.@]
52 NTSTATUS WINAPI
NtCreateKey( PHANDLE retkey
, ACCESS_MASK access
, const OBJECT_ATTRIBUTES
*attr
,
53 ULONG TitleIndex
, const UNICODE_STRING
*class, ULONG options
,
58 struct object_attributes
*objattr
;
60 if (!retkey
|| !attr
) return STATUS_ACCESS_VIOLATION
;
61 if (attr
->Length
> sizeof(OBJECT_ATTRIBUTES
)) return STATUS_INVALID_PARAMETER
;
63 TRACE( "(%p,%s,%s,%x,%x,%p)\n", attr
->RootDirectory
, debugstr_us(attr
->ObjectName
),
64 debugstr_us(class), options
, access
, retkey
);
66 if ((ret
= alloc_object_attributes( attr
, &objattr
, &len
))) return ret
;
68 SERVER_START_REQ( create_key
)
71 req
->options
= options
;
72 wine_server_add_data( req
, objattr
, len
);
73 if (class) wine_server_add_data( req
, class->Buffer
, class->Length
);
74 if (!(ret
= wine_server_call( req
)))
76 *retkey
= wine_server_ptr_handle( reply
->hkey
);
77 if (dispos
) *dispos
= reply
->created
? REG_CREATED_NEW_KEY
: REG_OPENED_EXISTING_KEY
;
82 TRACE("<- %p\n", *retkey
);
83 RtlFreeHeap( GetProcessHeap(), 0, objattr
);
87 NTSTATUS WINAPI
NtCreateKeyTransacted( PHANDLE retkey
, ACCESS_MASK access
, const OBJECT_ATTRIBUTES
*attr
,
88 ULONG TitleIndex
, const UNICODE_STRING
*class, ULONG options
,
89 HANDLE transacted
, ULONG
*dispos
)
91 FIXME( "(%p,%s,%s,%x,%x,%p,%p)\n", attr
->RootDirectory
, debugstr_us(attr
->ObjectName
),
92 debugstr_us(class), options
, access
, transacted
, retkey
);
93 return STATUS_NOT_IMPLEMENTED
;
96 NTSTATUS WINAPI
NtRenameKey( HANDLE handle
, UNICODE_STRING
*name
)
98 FIXME( "(%p %s)\n", handle
, debugstr_us(name
) );
99 return STATUS_NOT_IMPLEMENTED
;
102 /******************************************************************************
103 * RtlpNtCreateKey [NTDLL.@]
107 NTSTATUS WINAPI
RtlpNtCreateKey( PHANDLE retkey
, ACCESS_MASK access
, const OBJECT_ATTRIBUTES
*attr
,
108 ULONG TitleIndex
, const UNICODE_STRING
*class, ULONG options
,
111 OBJECT_ATTRIBUTES oa
;
116 oa
.Attributes
&= ~(OBJ_PERMANENT
|OBJ_EXCLUSIVE
);
120 return NtCreateKey(retkey
, access
, attr
, 0, NULL
, 0, dispos
);
123 static NTSTATUS
open_key( PHANDLE retkey
, ACCESS_MASK access
, const OBJECT_ATTRIBUTES
*attr
, ULONG options
)
127 if (!retkey
|| !attr
|| !attr
->ObjectName
) return STATUS_ACCESS_VIOLATION
;
128 if ((ret
= validate_open_object_attributes( attr
))) return ret
;
130 TRACE( "(%p,%s,%x,%p)\n", attr
->RootDirectory
,
131 debugstr_us(attr
->ObjectName
), access
, retkey
);
133 FIXME("options %x not implemented\n", options
);
135 SERVER_START_REQ( open_key
)
137 req
->parent
= wine_server_obj_handle( attr
->RootDirectory
);
138 req
->access
= access
;
139 req
->attributes
= attr
->Attributes
;
140 wine_server_add_data( req
, attr
->ObjectName
->Buffer
, attr
->ObjectName
->Length
);
141 ret
= wine_server_call( req
);
142 *retkey
= wine_server_ptr_handle( reply
->hkey
);
145 TRACE("<- %p\n", *retkey
);
149 /******************************************************************************
150 * NtOpenKeyEx [NTDLL.@]
151 * ZwOpenKeyEx [NTDLL.@]
153 NTSTATUS WINAPI
NtOpenKeyEx( PHANDLE retkey
, ACCESS_MASK access
, const OBJECT_ATTRIBUTES
*attr
, ULONG options
)
155 return open_key( retkey
, access
, attr
, options
);
158 /******************************************************************************
159 * NtOpenKey [NTDLL.@]
160 * ZwOpenKey [NTDLL.@]
162 * OUT HANDLE retkey (returns 0 when failure)
163 * IN ACCESS_MASK access
164 * IN POBJECT_ATTRIBUTES attr
166 NTSTATUS WINAPI
NtOpenKey( PHANDLE retkey
, ACCESS_MASK access
, const OBJECT_ATTRIBUTES
*attr
)
168 return open_key( retkey
, access
, attr
, 0 );
171 NTSTATUS WINAPI
NtOpenKeyTransactedEx( PHANDLE retkey
, ACCESS_MASK access
, const OBJECT_ATTRIBUTES
*attr
,
172 ULONG options
, HANDLE transaction
)
174 FIXME( "(%p %x %p %x %p)\n", retkey
, access
, attr
, options
, transaction
);
175 return STATUS_NOT_IMPLEMENTED
;
178 NTSTATUS WINAPI
NtOpenKeyTransacted( PHANDLE retkey
, ACCESS_MASK access
, const OBJECT_ATTRIBUTES
*attr
,
181 return NtOpenKeyTransactedEx( retkey
, access
, attr
, 0, transaction
);
184 /******************************************************************************
185 * RtlpNtOpenKey [NTDLL.@]
189 NTSTATUS WINAPI
RtlpNtOpenKey( PHANDLE retkey
, ACCESS_MASK access
, OBJECT_ATTRIBUTES
*attr
)
192 attr
->Attributes
&= ~(OBJ_PERMANENT
|OBJ_EXCLUSIVE
);
193 return NtOpenKey(retkey
, access
, attr
);
196 /******************************************************************************
197 * NtDeleteKey [NTDLL.@]
198 * ZwDeleteKey [NTDLL.@]
200 NTSTATUS WINAPI
NtDeleteKey( HANDLE hkey
)
204 TRACE( "(%p)\n", hkey
);
206 SERVER_START_REQ( delete_key
)
208 req
->hkey
= wine_server_obj_handle( hkey
);
209 ret
= wine_server_call( req
);
215 /******************************************************************************
216 * RtlpNtMakeTemporaryKey [NTDLL.@]
220 NTSTATUS WINAPI
RtlpNtMakeTemporaryKey( HANDLE hkey
)
222 return NtDeleteKey(hkey
);
225 /******************************************************************************
226 * NtDeleteValueKey [NTDLL.@]
227 * ZwDeleteValueKey [NTDLL.@]
229 NTSTATUS WINAPI
NtDeleteValueKey( HANDLE hkey
, const UNICODE_STRING
*name
)
233 TRACE( "(%p,%s)\n", hkey
, debugstr_us(name
) );
234 if (name
->Length
> MAX_VALUE_LENGTH
) return STATUS_OBJECT_NAME_NOT_FOUND
;
236 SERVER_START_REQ( delete_key_value
)
238 req
->hkey
= wine_server_obj_handle( hkey
);
239 wine_server_add_data( req
, name
->Buffer
, name
->Length
);
240 ret
= wine_server_call( req
);
247 /******************************************************************************
250 * Implementation of NtQueryKey and NtEnumerateKey
252 static NTSTATUS
enumerate_key( HANDLE handle
, int index
, KEY_INFORMATION_CLASS info_class
,
253 void *info
, DWORD length
, DWORD
*result_len
)
262 case KeyBasicInformation
: data_ptr
= ((KEY_BASIC_INFORMATION
*)info
)->Name
; break;
263 case KeyFullInformation
: data_ptr
= ((KEY_FULL_INFORMATION
*)info
)->Class
; break;
264 case KeyNodeInformation
: data_ptr
= ((KEY_NODE_INFORMATION
*)info
)->Name
; break;
265 case KeyNameInformation
: data_ptr
= ((KEY_NAME_INFORMATION
*)info
)->Name
; break;
266 case KeyCachedInformation
: data_ptr
= ((KEY_CACHED_INFORMATION
*)info
)+1; break;
268 FIXME( "Information class %d not implemented\n", info_class
);
269 return STATUS_INVALID_PARAMETER
;
271 fixed_size
= (char *)data_ptr
- (char *)info
;
273 SERVER_START_REQ( enum_key
)
275 req
->hkey
= wine_server_obj_handle( handle
);
277 req
->info_class
= info_class
;
278 if (length
> fixed_size
) wine_server_set_reply( req
, data_ptr
, length
- fixed_size
);
279 if (!(ret
= wine_server_call( req
)))
283 case KeyBasicInformation
:
285 KEY_BASIC_INFORMATION keyinfo
;
286 fixed_size
= (char *)keyinfo
.Name
- (char *)&keyinfo
;
287 keyinfo
.LastWriteTime
.QuadPart
= reply
->modif
;
288 keyinfo
.TitleIndex
= 0;
289 keyinfo
.NameLength
= reply
->namelen
;
290 memcpy( info
, &keyinfo
, min( length
, fixed_size
) );
293 case KeyFullInformation
:
295 KEY_FULL_INFORMATION keyinfo
;
296 fixed_size
= (char *)keyinfo
.Class
- (char *)&keyinfo
;
297 keyinfo
.LastWriteTime
.QuadPart
= reply
->modif
;
298 keyinfo
.TitleIndex
= 0;
299 keyinfo
.ClassLength
= wine_server_reply_size(reply
);
300 keyinfo
.ClassOffset
= keyinfo
.ClassLength
? fixed_size
: -1;
301 keyinfo
.SubKeys
= reply
->subkeys
;
302 keyinfo
.MaxNameLen
= reply
->max_subkey
;
303 keyinfo
.MaxClassLen
= reply
->max_class
;
304 keyinfo
.Values
= reply
->values
;
305 keyinfo
.MaxValueNameLen
= reply
->max_value
;
306 keyinfo
.MaxValueDataLen
= reply
->max_data
;
307 memcpy( info
, &keyinfo
, min( length
, fixed_size
) );
310 case KeyNodeInformation
:
312 KEY_NODE_INFORMATION keyinfo
;
313 fixed_size
= (char *)keyinfo
.Name
- (char *)&keyinfo
;
314 keyinfo
.LastWriteTime
.QuadPart
= reply
->modif
;
315 keyinfo
.TitleIndex
= 0;
316 if (reply
->namelen
< wine_server_reply_size(reply
))
318 keyinfo
.ClassLength
= wine_server_reply_size(reply
) - reply
->namelen
;
319 keyinfo
.ClassOffset
= fixed_size
+ reply
->namelen
;
323 keyinfo
.ClassLength
= 0;
324 keyinfo
.ClassOffset
= -1;
326 keyinfo
.NameLength
= reply
->namelen
;
327 memcpy( info
, &keyinfo
, min( length
, fixed_size
) );
330 case KeyNameInformation
:
332 KEY_NAME_INFORMATION keyinfo
;
333 fixed_size
= (char *)keyinfo
.Name
- (char *)&keyinfo
;
334 keyinfo
.NameLength
= reply
->namelen
;
335 memcpy( info
, &keyinfo
, min( length
, fixed_size
) );
338 case KeyCachedInformation
:
340 KEY_CACHED_INFORMATION keyinfo
;
341 fixed_size
= sizeof(keyinfo
);
342 keyinfo
.LastWriteTime
.QuadPart
= reply
->modif
;
343 keyinfo
.TitleIndex
= 0;
344 keyinfo
.SubKeys
= reply
->subkeys
;
345 keyinfo
.MaxNameLen
= reply
->max_subkey
;
346 keyinfo
.Values
= reply
->values
;
347 keyinfo
.MaxValueNameLen
= reply
->max_value
;
348 keyinfo
.MaxValueDataLen
= reply
->max_data
;
349 keyinfo
.NameLength
= reply
->namelen
;
350 memcpy( info
, &keyinfo
, min( length
, fixed_size
) );
356 *result_len
= fixed_size
+ reply
->total
;
357 if (length
< *result_len
) ret
= STATUS_BUFFER_OVERFLOW
;
366 /******************************************************************************
367 * NtEnumerateKey [NTDLL.@]
368 * ZwEnumerateKey [NTDLL.@]
371 * the name copied into the buffer is NOT 0-terminated
373 NTSTATUS WINAPI
NtEnumerateKey( HANDLE handle
, ULONG index
, KEY_INFORMATION_CLASS info_class
,
374 void *info
, DWORD length
, DWORD
*result_len
)
376 /* -1 means query key, so avoid it here */
377 if (index
== (ULONG
)-1) return STATUS_NO_MORE_ENTRIES
;
378 return enumerate_key( handle
, index
, info_class
, info
, length
, result_len
);
382 /******************************************************************************
383 * RtlpNtEnumerateSubKey [NTDLL.@]
386 NTSTATUS WINAPI
RtlpNtEnumerateSubKey( HANDLE handle
, UNICODE_STRING
*out
, ULONG index
)
388 KEY_BASIC_INFORMATION
*info
;
389 DWORD dwLen
, dwResultLen
;
394 dwLen
= out
->Length
+ sizeof(KEY_BASIC_INFORMATION
);
395 info
= RtlAllocateHeap( GetProcessHeap(), 0, dwLen
);
397 return STATUS_NO_MEMORY
;
405 ret
= NtEnumerateKey( handle
, index
, KeyBasicInformation
, info
, dwLen
, &dwResultLen
);
406 dwResultLen
-= sizeof(KEY_BASIC_INFORMATION
);
408 if (ret
== STATUS_BUFFER_OVERFLOW
)
409 out
->Length
= dwResultLen
;
412 if (out
->Length
< info
->NameLength
)
414 out
->Length
= dwResultLen
;
415 ret
= STATUS_BUFFER_OVERFLOW
;
419 out
->Length
= info
->NameLength
;
420 memcpy(out
->Buffer
, info
->Name
, info
->NameLength
);
424 RtlFreeHeap( GetProcessHeap(), 0, info
);
428 /******************************************************************************
429 * NtQueryKey [NTDLL.@]
430 * ZwQueryKey [NTDLL.@]
432 NTSTATUS WINAPI
NtQueryKey( HANDLE handle
, KEY_INFORMATION_CLASS info_class
,
433 void *info
, DWORD length
, DWORD
*result_len
)
435 return enumerate_key( handle
, -1, info_class
, info
, length
, result_len
);
439 /* fill the key value info structure for a specific info class */
440 static void copy_key_value_info( KEY_VALUE_INFORMATION_CLASS info_class
, void *info
,
441 DWORD length
, int type
, int name_len
, int data_len
)
445 case KeyValueBasicInformation
:
447 KEY_VALUE_BASIC_INFORMATION keyinfo
;
448 keyinfo
.TitleIndex
= 0;
450 keyinfo
.NameLength
= name_len
;
451 length
= min( length
, (char *)keyinfo
.Name
- (char *)&keyinfo
);
452 memcpy( info
, &keyinfo
, length
);
455 case KeyValueFullInformation
:
457 KEY_VALUE_FULL_INFORMATION keyinfo
;
458 keyinfo
.TitleIndex
= 0;
460 keyinfo
.DataOffset
= (char *)keyinfo
.Name
- (char *)&keyinfo
+ name_len
;
461 keyinfo
.DataLength
= data_len
;
462 keyinfo
.NameLength
= name_len
;
463 length
= min( length
, (char *)keyinfo
.Name
- (char *)&keyinfo
);
464 memcpy( info
, &keyinfo
, length
);
467 case KeyValuePartialInformation
:
469 KEY_VALUE_PARTIAL_INFORMATION keyinfo
;
470 keyinfo
.TitleIndex
= 0;
472 keyinfo
.DataLength
= data_len
;
473 length
= min( length
, (char *)keyinfo
.Data
- (char *)&keyinfo
);
474 memcpy( info
, &keyinfo
, length
);
483 /******************************************************************************
484 * NtEnumerateValueKey [NTDLL.@]
485 * ZwEnumerateValueKey [NTDLL.@]
487 NTSTATUS WINAPI
NtEnumerateValueKey( HANDLE handle
, ULONG index
,
488 KEY_VALUE_INFORMATION_CLASS info_class
,
489 void *info
, DWORD length
, DWORD
*result_len
)
495 TRACE( "(%p,%u,%d,%p,%d)\n", handle
, index
, info_class
, info
, length
);
497 /* compute the length we want to retrieve */
500 case KeyValueBasicInformation
: ptr
= ((KEY_VALUE_BASIC_INFORMATION
*)info
)->Name
; break;
501 case KeyValueFullInformation
: ptr
= ((KEY_VALUE_FULL_INFORMATION
*)info
)->Name
; break;
502 case KeyValuePartialInformation
: ptr
= ((KEY_VALUE_PARTIAL_INFORMATION
*)info
)->Data
; break;
504 FIXME( "Information class %d not implemented\n", info_class
);
505 return STATUS_INVALID_PARAMETER
;
507 fixed_size
= (char *)ptr
- (char *)info
;
509 SERVER_START_REQ( enum_key_value
)
511 req
->hkey
= wine_server_obj_handle( handle
);
513 req
->info_class
= info_class
;
514 if (length
> fixed_size
) wine_server_set_reply( req
, ptr
, length
- fixed_size
);
515 if (!(ret
= wine_server_call( req
)))
517 copy_key_value_info( info_class
, info
, length
, reply
->type
, reply
->namelen
,
518 wine_server_reply_size(reply
) - reply
->namelen
);
519 *result_len
= fixed_size
+ reply
->total
;
520 if (length
< *result_len
) ret
= STATUS_BUFFER_OVERFLOW
;
528 /******************************************************************************
529 * NtQueryValueKey [NTDLL.@]
530 * ZwQueryValueKey [NTDLL.@]
533 * the name in the KeyValueInformation is never set
535 NTSTATUS WINAPI
NtQueryValueKey( HANDLE handle
, const UNICODE_STRING
*name
,
536 KEY_VALUE_INFORMATION_CLASS info_class
,
537 void *info
, DWORD length
, DWORD
*result_len
)
541 unsigned int fixed_size
, min_size
;
543 TRACE( "(%p,%s,%d,%p,%d)\n", handle
, debugstr_us(name
), info_class
, info
, length
);
545 if (name
->Length
> MAX_VALUE_LENGTH
) return STATUS_OBJECT_NAME_NOT_FOUND
;
547 /* compute the length we want to retrieve */
550 case KeyValueBasicInformation
:
552 KEY_VALUE_BASIC_INFORMATION
*basic_info
= info
;
553 min_size
= FIELD_OFFSET(KEY_VALUE_BASIC_INFORMATION
, Name
);
554 fixed_size
= min_size
+ name
->Length
;
555 if (min_size
< length
)
556 memcpy(basic_info
->Name
, name
->Buffer
, min(length
- min_size
, name
->Length
));
560 case KeyValueFullInformation
:
562 KEY_VALUE_FULL_INFORMATION
*full_info
= info
;
563 min_size
= FIELD_OFFSET(KEY_VALUE_FULL_INFORMATION
, Name
);
564 fixed_size
= min_size
+ name
->Length
;
565 if (min_size
< length
)
566 memcpy(full_info
->Name
, name
->Buffer
, min(length
- min_size
, name
->Length
));
567 data_ptr
= (UCHAR
*)full_info
->Name
+ name
->Length
;
570 case KeyValuePartialInformation
:
571 min_size
= fixed_size
= FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION
, Data
);
572 data_ptr
= ((KEY_VALUE_PARTIAL_INFORMATION
*)info
)->Data
;
575 FIXME( "Information class %d not implemented\n", info_class
);
576 return STATUS_INVALID_PARAMETER
;
579 SERVER_START_REQ( get_key_value
)
581 req
->hkey
= wine_server_obj_handle( handle
);
582 wine_server_add_data( req
, name
->Buffer
, name
->Length
);
583 if (length
> fixed_size
&& data_ptr
) wine_server_set_reply( req
, data_ptr
, length
- fixed_size
);
584 if (!(ret
= wine_server_call( req
)))
586 copy_key_value_info( info_class
, info
, length
, reply
->type
,
587 name
->Length
, reply
->total
);
588 *result_len
= fixed_size
+ (info_class
== KeyValueBasicInformation
? 0 : reply
->total
);
589 if (length
< min_size
) ret
= STATUS_BUFFER_TOO_SMALL
;
590 else if (length
< *result_len
) ret
= STATUS_BUFFER_OVERFLOW
;
597 /******************************************************************************
598 * RtlpNtQueryValueKey [NTDLL.@]
601 NTSTATUS WINAPI
RtlpNtQueryValueKey( HANDLE handle
, ULONG
*result_type
, PBYTE dest
,
602 DWORD
*result_len
, void *unknown
)
604 KEY_VALUE_PARTIAL_INFORMATION
*info
;
608 DWORD dwLen
= sizeof (KEY_VALUE_PARTIAL_INFORMATION
) + (result_len
? *result_len
: 0);
610 info
= RtlAllocateHeap( GetProcessHeap(), 0, dwLen
);
612 return STATUS_NO_MEMORY
;
615 ret
= NtQueryValueKey( handle
, &name
, KeyValuePartialInformation
, info
, dwLen
, &dwResultLen
);
617 if (!ret
|| ret
== STATUS_BUFFER_OVERFLOW
)
620 *result_len
= info
->DataLength
;
623 *result_type
= info
->Type
;
625 if (ret
!= STATUS_BUFFER_OVERFLOW
)
626 memcpy( dest
, info
->Data
, info
->DataLength
);
629 RtlFreeHeap( GetProcessHeap(), 0, info
);
633 /******************************************************************************
634 * NtFlushKey [NTDLL.@]
635 * ZwFlushKey [NTDLL.@]
637 NTSTATUS WINAPI
NtFlushKey(HANDLE key
)
641 TRACE("key=%p\n", key
);
643 SERVER_START_REQ( flush_key
)
645 req
->hkey
= wine_server_obj_handle( key
);
646 ret
= wine_server_call( req
);
653 /******************************************************************************
654 * NtLoadKey [NTDLL.@]
655 * ZwLoadKey [NTDLL.@]
657 NTSTATUS WINAPI
NtLoadKey( const OBJECT_ATTRIBUTES
*attr
, OBJECT_ATTRIBUTES
*file
)
663 struct object_attributes
*objattr
;
665 TRACE("(%p,%p)\n", attr
, file
);
667 ret
= NtCreateFile(&hive
, GENERIC_READ
| SYNCHRONIZE
, file
, &io
, NULL
, FILE_ATTRIBUTE_NORMAL
, 0,
668 FILE_OPEN
, 0, NULL
, 0);
671 if ((ret
= alloc_object_attributes( attr
, &objattr
, &len
))) return ret
;
673 SERVER_START_REQ( load_registry
)
675 req
->file
= wine_server_obj_handle( hive
);
676 wine_server_add_data( req
, objattr
, len
);
677 ret
= wine_server_call( req
);
682 RtlFreeHeap( GetProcessHeap(), 0, objattr
);
686 /******************************************************************************
687 * NtNotifyChangeMultipleKeys [NTDLL.@]
688 * ZwNotifyChangeMultipleKeys [NTDLL.@]
690 NTSTATUS WINAPI
NtNotifyChangeMultipleKeys(
693 OBJECT_ATTRIBUTES
*SubordinateObjects
,
695 PIO_APC_ROUTINE ApcRoutine
,
697 PIO_STATUS_BLOCK IoStatusBlock
,
698 ULONG CompletionFilter
,
699 BOOLEAN WatchSubtree
,
702 BOOLEAN Asynchronous
)
706 TRACE("(%p,%u,%p,%p,%p,%p,%p,0x%08x, 0x%08x,%p,0x%08x,0x%08x)\n",
707 KeyHandle
, Count
, SubordinateObjects
, Event
, ApcRoutine
, ApcContext
, IoStatusBlock
, CompletionFilter
,
708 Asynchronous
, ChangeBuffer
, Length
, WatchSubtree
);
710 if (Count
|| SubordinateObjects
|| ApcRoutine
|| ApcContext
|| ChangeBuffer
|| Length
)
711 FIXME("Unimplemented optional parameter\n");
715 OBJECT_ATTRIBUTES attr
;
716 InitializeObjectAttributes( &attr
, NULL
, 0, NULL
, NULL
);
717 ret
= NtCreateEvent( &Event
, EVENT_ALL_ACCESS
, &attr
, SynchronizationEvent
, FALSE
);
718 if (ret
!= STATUS_SUCCESS
)
722 SERVER_START_REQ( set_registry_notification
)
724 req
->hkey
= wine_server_obj_handle( KeyHandle
);
725 req
->event
= wine_server_obj_handle( Event
);
726 req
->subtree
= WatchSubtree
;
727 req
->filter
= CompletionFilter
;
728 ret
= wine_server_call( req
);
734 if (ret
== STATUS_PENDING
)
735 ret
= NtWaitForSingleObject( Event
, FALSE
, NULL
);
742 /******************************************************************************
743 * NtNotifyChangeKey [NTDLL.@]
744 * ZwNotifyChangeKey [NTDLL.@]
746 NTSTATUS WINAPI
NtNotifyChangeKey(
749 IN PIO_APC_ROUTINE ApcRoutine OPTIONAL
,
750 IN PVOID ApcContext OPTIONAL
,
751 OUT PIO_STATUS_BLOCK IoStatusBlock
,
752 IN ULONG CompletionFilter
,
753 IN BOOLEAN WatchSubtree
,
754 OUT PVOID ChangeBuffer
,
756 IN BOOLEAN Asynchronous
)
758 return NtNotifyChangeMultipleKeys(KeyHandle
, 0, NULL
, Event
, ApcRoutine
, ApcContext
,
759 IoStatusBlock
, CompletionFilter
, WatchSubtree
,
760 ChangeBuffer
, Length
, Asynchronous
);
763 /******************************************************************************
764 * NtQueryMultipleValueKey [NTDLL]
765 * ZwQueryMultipleValueKey
768 NTSTATUS WINAPI
NtQueryMultipleValueKey(
770 PKEY_MULTIPLE_VALUE_INFORMATION ListOfValuesToQuery
,
772 PVOID MultipleValueInformation
,
776 FIXME("(%p,%p,0x%08x,%p,0x%08x,%p) stub!\n",
777 KeyHandle
, ListOfValuesToQuery
, NumberOfItems
, MultipleValueInformation
,
778 Length
,ReturnLength
);
779 return STATUS_SUCCESS
;
782 /******************************************************************************
783 * NtReplaceKey [NTDLL.@]
784 * ZwReplaceKey [NTDLL.@]
786 NTSTATUS WINAPI
NtReplaceKey(
787 IN POBJECT_ATTRIBUTES ObjectAttributes
,
789 IN POBJECT_ATTRIBUTES ReplacedObjectAttributes
)
791 FIXME("(%s,%p,%s),stub!\n", debugstr_ObjectAttributes(ObjectAttributes
), Key
,
792 debugstr_ObjectAttributes(ReplacedObjectAttributes
) );
793 return STATUS_SUCCESS
;
795 /******************************************************************************
796 * NtRestoreKey [NTDLL.@]
797 * ZwRestoreKey [NTDLL.@]
799 NTSTATUS WINAPI
NtRestoreKey(
804 FIXME("(%p,%p,0x%08x) stub\n",
805 KeyHandle
, FileHandle
, RestoreFlags
);
806 return STATUS_SUCCESS
;
808 /******************************************************************************
809 * NtSaveKey [NTDLL.@]
810 * ZwSaveKey [NTDLL.@]
812 NTSTATUS WINAPI
NtSaveKey(IN HANDLE KeyHandle
, IN HANDLE FileHandle
)
816 TRACE("(%p,%p)\n", KeyHandle
, FileHandle
);
818 SERVER_START_REQ( save_registry
)
820 req
->hkey
= wine_server_obj_handle( KeyHandle
);
821 req
->file
= wine_server_obj_handle( FileHandle
);
822 ret
= wine_server_call( req
);
828 /******************************************************************************
829 * NtSetInformationKey [NTDLL.@]
830 * ZwSetInformationKey [NTDLL.@]
832 NTSTATUS WINAPI
NtSetInformationKey(
834 IN
const int KeyInformationClass
,
835 IN PVOID KeyInformation
,
836 IN ULONG KeyInformationLength
)
838 FIXME("(%p,0x%08x,%p,0x%08x) stub\n",
839 KeyHandle
, KeyInformationClass
, KeyInformation
, KeyInformationLength
);
840 return STATUS_SUCCESS
;
844 /******************************************************************************
845 * NtSetValueKey [NTDLL.@]
846 * ZwSetValueKey [NTDLL.@]
849 * win95 does not care about count for REG_SZ and finds out the len by itself (js)
850 * NT does definitely care (aj)
852 NTSTATUS WINAPI
NtSetValueKey( HANDLE hkey
, const UNICODE_STRING
*name
, ULONG TitleIndex
,
853 ULONG type
, const void *data
, ULONG count
)
857 TRACE( "(%p,%s,%d,%p,%d)\n", hkey
, debugstr_us(name
), type
, data
, count
);
859 if (name
->Length
> MAX_VALUE_LENGTH
) return STATUS_INVALID_PARAMETER
;
861 SERVER_START_REQ( set_key_value
)
863 req
->hkey
= wine_server_obj_handle( hkey
);
865 req
->namelen
= name
->Length
;
866 wine_server_add_data( req
, name
->Buffer
, name
->Length
);
867 wine_server_add_data( req
, data
, count
);
868 ret
= wine_server_call( req
);
874 /******************************************************************************
875 * RtlpNtSetValueKey [NTDLL.@]
878 NTSTATUS WINAPI
RtlpNtSetValueKey( HANDLE hkey
, ULONG type
, const void *data
,
884 return NtSetValueKey( hkey
, &name
, 0, type
, data
, count
);
887 /******************************************************************************
888 * NtUnloadKey [NTDLL.@]
889 * ZwUnloadKey [NTDLL.@]
891 NTSTATUS WINAPI
NtUnloadKey(IN POBJECT_ATTRIBUTES attr
)
895 TRACE("(%p)\n", attr
);
897 SERVER_START_REQ( unload_registry
)
899 req
->hkey
= wine_server_obj_handle( attr
->RootDirectory
);
900 ret
= wine_server_call(req
);
907 /******************************************************************************
908 * RtlFormatCurrentUserKeyPath [NTDLL.@]
911 NTSTATUS WINAPI
RtlFormatCurrentUserKeyPath( IN OUT PUNICODE_STRING KeyPath
)
913 static const WCHAR pathW
[] = {'\\','R','e','g','i','s','t','r','y','\\','U','s','e','r','\\'};
917 status
= NtOpenThreadToken(GetCurrentThread(), TOKEN_READ
, TRUE
, &token
);
918 if (status
== STATUS_NO_TOKEN
)
919 status
= NtOpenProcessToken(GetCurrentProcess(), TOKEN_READ
, &token
);
920 if (status
== STATUS_SUCCESS
)
922 char buffer
[sizeof(TOKEN_USER
) + sizeof(SID
) + sizeof(DWORD
)*SID_MAX_SUB_AUTHORITIES
];
923 DWORD len
= sizeof(buffer
);
925 status
= NtQueryInformationToken(token
, TokenUser
, buffer
, len
, &len
);
926 if (status
== STATUS_SUCCESS
)
928 KeyPath
->MaximumLength
= 0;
929 status
= RtlConvertSidToUnicodeString(KeyPath
, ((TOKEN_USER
*)buffer
)->User
.Sid
, FALSE
);
930 if (status
== STATUS_BUFFER_OVERFLOW
)
932 PWCHAR buf
= RtlAllocateHeap(GetProcessHeap(), 0,
933 sizeof(pathW
) + KeyPath
->Length
+ sizeof(WCHAR
));
936 memcpy(buf
, pathW
, sizeof(pathW
));
937 KeyPath
->MaximumLength
= KeyPath
->Length
+ sizeof(WCHAR
);
938 KeyPath
->Buffer
= (PWCHAR
)((LPBYTE
)buf
+ sizeof(pathW
));
939 status
= RtlConvertSidToUnicodeString(KeyPath
,
940 ((TOKEN_USER
*)buffer
)->User
.Sid
, FALSE
);
941 KeyPath
->Buffer
= buf
;
942 KeyPath
->Length
+= sizeof(pathW
);
943 KeyPath
->MaximumLength
+= sizeof(pathW
);
946 status
= STATUS_NO_MEMORY
;
954 /******************************************************************************
955 * RtlOpenCurrentUser [NTDLL.@]
958 * If we return just HKEY_CURRENT_USER the advapi tries to find a remote
959 * registry (odd handle) and fails.
961 NTSTATUS WINAPI
RtlOpenCurrentUser(
962 IN ACCESS_MASK DesiredAccess
, /* [in] */
963 OUT PHANDLE KeyHandle
) /* [out] handle of HKEY_CURRENT_USER */
965 OBJECT_ATTRIBUTES ObjectAttributes
;
966 UNICODE_STRING ObjectName
;
969 TRACE("(0x%08x, %p)\n",DesiredAccess
, KeyHandle
);
971 if ((ret
= RtlFormatCurrentUserKeyPath(&ObjectName
))) return ret
;
972 InitializeObjectAttributes(&ObjectAttributes
,&ObjectName
,OBJ_CASE_INSENSITIVE
,0, NULL
);
973 ret
= NtCreateKey(KeyHandle
, DesiredAccess
, &ObjectAttributes
, 0, NULL
, 0, NULL
);
974 RtlFreeUnicodeString(&ObjectName
);
979 static NTSTATUS
RTL_ReportRegistryValue(PKEY_VALUE_FULL_INFORMATION pInfo
,
980 PRTL_QUERY_REGISTRY_TABLE pQuery
, PVOID pContext
, PVOID pEnvironment
)
983 UNICODE_STRING src
, dst
;
988 NTSTATUS status
= STATUS_SUCCESS
;
995 if (pQuery
->Flags
& RTL_QUERY_REGISTRY_DIRECT
)
996 return STATUS_INVALID_PARAMETER
;
999 status
= pQuery
->QueryRoutine(pQuery
->Name
, pQuery
->DefaultType
, pQuery
->DefaultData
,
1000 pQuery
->DefaultLength
, pContext
, pQuery
->EntryContext
);
1004 len
= pInfo
->DataLength
;
1006 if (pQuery
->Flags
& RTL_QUERY_REGISTRY_DIRECT
)
1008 str
= pQuery
->EntryContext
;
1013 if (!(pQuery
->Flags
& RTL_QUERY_REGISTRY_NOEXPAND
))
1015 RtlInitUnicodeString(&src
, (WCHAR
*)(((CHAR
*)pInfo
) + pInfo
->DataOffset
));
1017 dst
.MaximumLength
= 0;
1018 RtlExpandEnvironmentStrings_U(pEnvironment
, &src
, &dst
, &res
);
1020 dst
.MaximumLength
= res
;
1021 dst
.Buffer
= RtlAllocateHeap(GetProcessHeap(), 0, res
* sizeof(WCHAR
));
1022 RtlExpandEnvironmentStrings_U(pEnvironment
, &src
, &dst
, &res
);
1023 status
= pQuery
->QueryRoutine(pQuery
->Name
, pInfo
->Type
, dst
.Buffer
,
1024 dst
.Length
, pContext
, pQuery
->EntryContext
);
1025 RtlFreeHeap(GetProcessHeap(), 0, dst
.Buffer
);
1030 if (str
->Buffer
== NULL
)
1031 RtlCreateUnicodeString(str
, (WCHAR
*)(((CHAR
*)pInfo
) + pInfo
->DataOffset
));
1033 RtlAppendUnicodeToString(str
, (WCHAR
*)(((CHAR
*)pInfo
) + pInfo
->DataOffset
));
1037 if (!(pQuery
->Flags
& RTL_QUERY_REGISTRY_NOEXPAND
))
1038 return STATUS_INVALID_PARAMETER
;
1040 if (str
->Buffer
== NULL
)
1042 str
->Buffer
= RtlAllocateHeap(GetProcessHeap(), 0, len
);
1043 str
->MaximumLength
= len
;
1045 len
= min(len
, str
->MaximumLength
);
1046 memcpy(str
->Buffer
, ((CHAR
*)pInfo
) + pInfo
->DataOffset
, len
);
1051 bin
= pQuery
->EntryContext
;
1052 if (pInfo
->DataLength
<= sizeof(ULONG
))
1053 memcpy(bin
, ((CHAR
*)pInfo
) + pInfo
->DataOffset
,
1057 if (bin
[0] <= sizeof(ULONG
))
1059 memcpy(&bin
[1], ((CHAR
*)pInfo
) + pInfo
->DataOffset
,
1060 min(-bin
[0], pInfo
->DataLength
));
1064 len
= min(bin
[0], pInfo
->DataLength
);
1066 bin
[2] = pInfo
->Type
;
1067 memcpy(&bin
[3], ((CHAR
*)pInfo
) + pInfo
->DataOffset
, len
);
1075 if((pQuery
->Flags
& RTL_QUERY_REGISTRY_NOEXPAND
) ||
1076 (pInfo
->Type
!= REG_EXPAND_SZ
&& pInfo
->Type
!= REG_MULTI_SZ
))
1078 status
= pQuery
->QueryRoutine(pQuery
->Name
, pInfo
->Type
,
1079 ((CHAR
*)pInfo
) + pInfo
->DataOffset
, pInfo
->DataLength
,
1080 pContext
, pQuery
->EntryContext
);
1082 else if (pInfo
->Type
== REG_EXPAND_SZ
)
1084 RtlInitUnicodeString(&src
, (WCHAR
*)(((CHAR
*)pInfo
) + pInfo
->DataOffset
));
1086 dst
.MaximumLength
= 0;
1087 RtlExpandEnvironmentStrings_U(pEnvironment
, &src
, &dst
, &res
);
1089 dst
.MaximumLength
= res
;
1090 dst
.Buffer
= RtlAllocateHeap(GetProcessHeap(), 0, res
* sizeof(WCHAR
));
1091 RtlExpandEnvironmentStrings_U(pEnvironment
, &src
, &dst
, &res
);
1092 status
= pQuery
->QueryRoutine(pQuery
->Name
, pInfo
->Type
, dst
.Buffer
,
1093 dst
.Length
, pContext
, pQuery
->EntryContext
);
1094 RtlFreeHeap(GetProcessHeap(), 0, dst
.Buffer
);
1096 else /* REG_MULTI_SZ */
1098 if(pQuery
->Flags
& RTL_QUERY_REGISTRY_NOEXPAND
)
1100 for (offset
= 0; offset
<= pInfo
->DataLength
; offset
+= len
+ sizeof(WCHAR
))
1102 wstr
= (WCHAR
*)(((CHAR
*)pInfo
) + offset
);
1103 len
= strlenW(wstr
) * sizeof(WCHAR
);
1104 status
= pQuery
->QueryRoutine(pQuery
->Name
, pInfo
->Type
, wstr
, len
,
1105 pContext
, pQuery
->EntryContext
);
1106 if(status
!= STATUS_SUCCESS
&& status
!= STATUS_BUFFER_TOO_SMALL
)
1112 while(count
<=pInfo
->DataLength
)
1114 String
= (WCHAR
*)(((CHAR
*)pInfo
) + pInfo
->DataOffset
)+count
;
1115 count
+=strlenW(String
)+1;
1116 RtlInitUnicodeString(&src
, (WCHAR
*)(((CHAR
*)pInfo
) + pInfo
->DataOffset
));
1118 dst
.MaximumLength
= 0;
1119 RtlExpandEnvironmentStrings_U(pEnvironment
, &src
, &dst
, &res
);
1121 dst
.MaximumLength
= res
;
1122 dst
.Buffer
= RtlAllocateHeap(GetProcessHeap(), 0, res
* sizeof(WCHAR
));
1123 RtlExpandEnvironmentStrings_U(pEnvironment
, &src
, &dst
, &res
);
1124 status
= pQuery
->QueryRoutine(pQuery
->Name
, pInfo
->Type
, dst
.Buffer
,
1125 dst
.Length
, pContext
, pQuery
->EntryContext
);
1126 RtlFreeHeap(GetProcessHeap(), 0, dst
.Buffer
);
1127 if(status
!= STATUS_SUCCESS
&& status
!= STATUS_BUFFER_TOO_SMALL
)
1137 static NTSTATUS
RTL_GetKeyHandle(ULONG RelativeTo
, PCWSTR Path
, PHANDLE handle
)
1139 UNICODE_STRING KeyString
;
1140 OBJECT_ATTRIBUTES regkey
;
1145 static const WCHAR empty
[] = {0};
1146 static const WCHAR control
[] = {'\\','R','e','g','i','s','t','r','y','\\','M','a','c','h','i','n','e',
1147 '\\','S','y','s','t','e','m','\\','C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\',
1148 'C','o','n','t','r','o','l','\\',0};
1150 static const WCHAR devicemap
[] = {'\\','R','e','g','i','s','t','r','y','\\','M','a','c','h','i','n','e','\\',
1151 'H','a','r','d','w','a','r','e','\\','D','e','v','i','c','e','M','a','p','\\',0};
1153 static const WCHAR services
[] = {'\\','R','e','g','i','s','t','r','y','\\','M','a','c','h','i','n','e','\\',
1154 'S','y','s','t','e','m','\\','C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\',
1155 'S','e','r','v','i','c','e','s','\\',0};
1157 static const WCHAR user
[] = {'\\','R','e','g','i','s','t','r','y','\\','U','s','e','r','\\',
1158 'C','u','r','r','e','n','t','U','s','e','r','\\',0};
1160 static const WCHAR windows_nt
[] = {'\\','R','e','g','i','s','t','r','y','\\','M','a','c','h','i','n','e','\\',
1161 'S','o','f','t','w','a','r','e','\\','M','i','c','r','o','s','o','f','t','\\',
1162 'W','i','n','d','o','w','s',' ','N','T','\\','C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',0};
1164 switch (RelativeTo
& 0xff)
1166 case RTL_REGISTRY_ABSOLUTE
:
1170 case RTL_REGISTRY_CONTROL
:
1174 case RTL_REGISTRY_DEVICEMAP
:
1178 case RTL_REGISTRY_SERVICES
:
1182 case RTL_REGISTRY_USER
:
1186 case RTL_REGISTRY_WINDOWS_NT
:
1191 return STATUS_INVALID_PARAMETER
;
1194 len
= (strlenW(base
) + strlenW(Path
) + 1) * sizeof(WCHAR
);
1195 KeyString
.Buffer
= RtlAllocateHeap(GetProcessHeap(), 0, len
);
1196 if (KeyString
.Buffer
== NULL
)
1197 return STATUS_NO_MEMORY
;
1199 strcpyW(KeyString
.Buffer
, base
);
1200 strcatW(KeyString
.Buffer
, Path
);
1201 KeyString
.Length
= len
- sizeof(WCHAR
);
1202 KeyString
.MaximumLength
= len
;
1203 InitializeObjectAttributes(®key
, &KeyString
, OBJ_CASE_INSENSITIVE
, NULL
, NULL
);
1204 status
= NtOpenKey(handle
, KEY_ALL_ACCESS
, ®key
);
1205 RtlFreeHeap(GetProcessHeap(), 0, KeyString
.Buffer
);
1209 /*************************************************************************
1210 * RtlQueryRegistryValues [NTDLL.@]
1212 * Query multiple registry values with a single call.
1215 * RelativeTo [I] Registry path that Path refers to
1216 * Path [I] Path to key
1217 * QueryTable [I] Table of key values to query
1218 * Context [I] Parameter to pass to the application defined QueryRoutine function
1219 * Environment [I] Optional parameter to use when performing expansion
1222 * STATUS_SUCCESS or an appropriate NTSTATUS error code.
1224 NTSTATUS WINAPI
RtlQueryRegistryValues(IN ULONG RelativeTo
, IN PCWSTR Path
,
1225 IN PRTL_QUERY_REGISTRY_TABLE QueryTable
, IN PVOID Context
,
1226 IN PVOID Environment OPTIONAL
)
1228 UNICODE_STRING Value
;
1229 HANDLE handle
, topkey
;
1230 PKEY_VALUE_FULL_INFORMATION pInfo
= NULL
;
1231 ULONG len
, buflen
= 0;
1232 NTSTATUS status
=STATUS_SUCCESS
, ret
= STATUS_SUCCESS
;
1235 TRACE("(%d, %s, %p, %p, %p)\n", RelativeTo
, debugstr_w(Path
), QueryTable
, Context
, Environment
);
1238 return STATUS_INVALID_PARAMETER
;
1240 /* get a valid handle */
1241 if (RelativeTo
& RTL_REGISTRY_HANDLE
)
1242 topkey
= handle
= (HANDLE
)Path
;
1245 status
= RTL_GetKeyHandle(RelativeTo
, Path
, &topkey
);
1248 if(status
!= STATUS_SUCCESS
)
1251 /* Process query table entries */
1252 for (; QueryTable
->QueryRoutine
!= NULL
|| QueryTable
->Name
!= NULL
; ++QueryTable
)
1254 if (QueryTable
->Flags
&
1255 (RTL_QUERY_REGISTRY_SUBKEY
| RTL_QUERY_REGISTRY_TOPKEY
))
1257 /* topkey must be kept open just in case we will reuse it later */
1258 if (handle
!= topkey
)
1261 if (QueryTable
->Flags
& RTL_QUERY_REGISTRY_SUBKEY
)
1264 status
= RTL_GetKeyHandle(PtrToUlong(QueryTable
->Name
), Path
, &handle
);
1265 if(status
!= STATUS_SUCCESS
)
1275 if (QueryTable
->Flags
& RTL_QUERY_REGISTRY_NOVALUE
)
1277 QueryTable
->QueryRoutine(QueryTable
->Name
, REG_NONE
, NULL
, 0,
1278 Context
, QueryTable
->EntryContext
);
1284 if (QueryTable
->Flags
& RTL_QUERY_REGISTRY_REQUIRED
)
1286 ret
= STATUS_OBJECT_NAME_NOT_FOUND
;
1292 if (QueryTable
->Name
== NULL
)
1294 if (QueryTable
->Flags
& RTL_QUERY_REGISTRY_DIRECT
)
1296 ret
= STATUS_INVALID_PARAMETER
;
1300 /* Report all subkeys */
1303 status
= NtEnumerateValueKey(handle
, i
,
1304 KeyValueFullInformation
, pInfo
, buflen
, &len
);
1305 if (status
== STATUS_NO_MORE_ENTRIES
)
1307 if (status
== STATUS_BUFFER_OVERFLOW
||
1308 status
== STATUS_BUFFER_TOO_SMALL
)
1311 RtlFreeHeap(GetProcessHeap(), 0, pInfo
);
1312 pInfo
= RtlAllocateHeap(GetProcessHeap(), 0, buflen
);
1313 NtEnumerateValueKey(handle
, i
, KeyValueFullInformation
,
1314 pInfo
, buflen
, &len
);
1317 status
= RTL_ReportRegistryValue(pInfo
, QueryTable
, Context
, Environment
);
1318 if(status
!= STATUS_SUCCESS
&& status
!= STATUS_BUFFER_TOO_SMALL
)
1323 if (QueryTable
->Flags
& RTL_QUERY_REGISTRY_DELETE
)
1325 RtlInitUnicodeString(&Value
, pInfo
->Name
);
1326 NtDeleteValueKey(handle
, &Value
);
1330 if (i
== 0 && (QueryTable
->Flags
& RTL_QUERY_REGISTRY_REQUIRED
))
1332 ret
= STATUS_OBJECT_NAME_NOT_FOUND
;
1338 RtlInitUnicodeString(&Value
, QueryTable
->Name
);
1339 status
= NtQueryValueKey(handle
, &Value
, KeyValueFullInformation
,
1340 pInfo
, buflen
, &len
);
1341 if (status
== STATUS_BUFFER_OVERFLOW
||
1342 status
== STATUS_BUFFER_TOO_SMALL
)
1345 RtlFreeHeap(GetProcessHeap(), 0, pInfo
);
1346 pInfo
= RtlAllocateHeap(GetProcessHeap(), 0, buflen
);
1347 status
= NtQueryValueKey(handle
, &Value
,
1348 KeyValueFullInformation
, pInfo
, buflen
, &len
);
1350 if (status
!= STATUS_SUCCESS
)
1352 if (QueryTable
->Flags
& RTL_QUERY_REGISTRY_REQUIRED
)
1354 ret
= STATUS_OBJECT_NAME_NOT_FOUND
;
1357 status
= RTL_ReportRegistryValue(NULL
, QueryTable
, Context
, Environment
);
1358 if(status
!= STATUS_SUCCESS
&& status
!= STATUS_BUFFER_TOO_SMALL
)
1366 status
= RTL_ReportRegistryValue(pInfo
, QueryTable
, Context
, Environment
);
1367 if(status
!= STATUS_SUCCESS
&& status
!= STATUS_BUFFER_TOO_SMALL
)
1372 if (QueryTable
->Flags
& RTL_QUERY_REGISTRY_DELETE
)
1373 NtDeleteValueKey(handle
, &Value
);
1379 RtlFreeHeap(GetProcessHeap(), 0, pInfo
);
1380 if (handle
!= topkey
)
1386 /*************************************************************************
1387 * RtlCheckRegistryKey [NTDLL.@]
1389 * Query multiple registry values with a single call.
1392 * RelativeTo [I] Registry path that Path refers to
1393 * Path [I] Path to key
1396 * STATUS_SUCCESS if the specified key exists, or an NTSTATUS error code.
1398 NTSTATUS WINAPI
RtlCheckRegistryKey(IN ULONG RelativeTo
, IN PWSTR Path
)
1403 TRACE("(%d, %s)\n", RelativeTo
, debugstr_w(Path
));
1405 if((!RelativeTo
) && Path
== NULL
)
1406 return STATUS_OBJECT_PATH_SYNTAX_BAD
;
1407 if(RelativeTo
& RTL_REGISTRY_HANDLE
)
1408 return STATUS_SUCCESS
;
1410 status
= RTL_GetKeyHandle(RelativeTo
, Path
, &handle
);
1411 if (handle
) NtClose(handle
);
1412 if (status
== STATUS_INVALID_HANDLE
) status
= STATUS_OBJECT_NAME_NOT_FOUND
;
1416 /*************************************************************************
1417 * RtlDeleteRegistryValue [NTDLL.@]
1419 * Query multiple registry values with a single call.
1422 * RelativeTo [I] Registry path that Path refers to
1423 * Path [I] Path to key
1424 * ValueName [I] Name of the value to delete
1427 * STATUS_SUCCESS if the specified key is successfully deleted, or an NTSTATUS error code.
1429 NTSTATUS WINAPI
RtlDeleteRegistryValue(IN ULONG RelativeTo
, IN PCWSTR Path
, IN PCWSTR ValueName
)
1433 UNICODE_STRING Value
;
1435 TRACE("(%d, %s, %s)\n", RelativeTo
, debugstr_w(Path
), debugstr_w(ValueName
));
1437 RtlInitUnicodeString(&Value
, ValueName
);
1438 if(RelativeTo
== RTL_REGISTRY_HANDLE
)
1440 return NtDeleteValueKey((HANDLE
)Path
, &Value
);
1442 status
= RTL_GetKeyHandle(RelativeTo
, Path
, &handle
);
1443 if (status
) return status
;
1444 status
= NtDeleteValueKey(handle
, &Value
);
1449 /*************************************************************************
1450 * RtlWriteRegistryValue [NTDLL.@]
1452 * Sets the registry value with provided data.
1455 * RelativeTo [I] Registry path that path parameter refers to
1456 * path [I] Path to the key (or handle - see RTL_GetKeyHandle)
1457 * name [I] Name of the registry value to set
1458 * type [I] Type of the registry key to set
1459 * data [I] Pointer to the user data to be set
1460 * length [I] Length of the user data pointed by data
1463 * STATUS_SUCCESS if the specified key is successfully set,
1464 * or an NTSTATUS error code.
1466 NTSTATUS WINAPI
RtlWriteRegistryValue( ULONG RelativeTo
, PCWSTR path
, PCWSTR name
,
1467 ULONG type
, PVOID data
, ULONG length
)
1473 TRACE( "(%d, %s, %s) -> %d: %p [%d]\n", RelativeTo
, debugstr_w(path
), debugstr_w(name
),
1474 type
, data
, length
);
1476 RtlInitUnicodeString( &str
, name
);
1478 if (RelativeTo
== RTL_REGISTRY_HANDLE
)
1479 return NtSetValueKey( (HANDLE
)path
, &str
, 0, type
, data
, length
);
1481 status
= RTL_GetKeyHandle( RelativeTo
, path
, &hkey
);
1482 if (status
!= STATUS_SUCCESS
) return status
;
1484 status
= NtSetValueKey( hkey
, &str
, 0, type
, data
, length
);
1490 /*************************************************************************
1491 * NtQueryLicenseValue [NTDLL.@]
1494 * On Windows all license properties are stored in a single key, but
1495 * unless there is some app which explicitly depends on that, there is
1496 * no good reason to reproduce that.
1498 NTSTATUS WINAPI
NtQueryLicenseValue( const UNICODE_STRING
*name
, ULONG
*result_type
,
1499 PVOID data
, ULONG length
, ULONG
*result_len
)
1501 static const WCHAR LicenseInformationW
[] = {'M','a','c','h','i','n','e','\\',
1502 'S','o','f','t','w','a','r','e','\\',
1503 'W','i','n','e','\\','L','i','c','e','n','s','e',
1504 'I','n','f','o','r','m','a','t','i','o','n',0};
1505 KEY_VALUE_PARTIAL_INFORMATION
*info
;
1506 NTSTATUS status
= STATUS_OBJECT_NAME_NOT_FOUND
;
1507 DWORD info_length
, count
;
1508 OBJECT_ATTRIBUTES attr
;
1509 UNICODE_STRING keyW
;
1512 if (!name
|| !name
->Buffer
|| !name
->Length
|| !result_len
)
1513 return STATUS_INVALID_PARAMETER
;
1515 info_length
= FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION
, Data
) + length
;
1516 info
= RtlAllocateHeap( GetProcessHeap(), 0, info_length
);
1517 if (!info
) return STATUS_NO_MEMORY
;
1519 attr
.Length
= sizeof(attr
);
1520 attr
.RootDirectory
= 0;
1521 attr
.ObjectName
= &keyW
;
1522 attr
.Attributes
= 0;
1523 attr
.SecurityDescriptor
= NULL
;
1524 attr
.SecurityQualityOfService
= NULL
;
1525 RtlInitUnicodeString( &keyW
, LicenseInformationW
);
1527 /* @@ Wine registry key: HKLM\Software\Wine\LicenseInformation */
1528 if (!NtOpenKey( &hkey
, KEY_READ
, &attr
))
1530 status
= NtQueryValueKey( hkey
, name
, KeyValuePartialInformation
,
1531 info
, info_length
, &count
);
1532 if (!status
|| status
== STATUS_BUFFER_OVERFLOW
)
1535 *result_type
= info
->Type
;
1537 *result_len
= info
->DataLength
;
1539 if (status
== STATUS_BUFFER_OVERFLOW
)
1540 status
= STATUS_BUFFER_TOO_SMALL
;
1542 memcpy( data
, info
->Data
, info
->DataLength
);
1547 if (status
== STATUS_OBJECT_NAME_NOT_FOUND
)
1548 FIXME( "License key %s not found\n", debugstr_w(name
->Buffer
) );
1550 RtlFreeHeap( GetProcessHeap(), 0, info
);