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','\\'};
914 char buffer
[sizeof(TOKEN_USER
) + sizeof(SID
) + sizeof(DWORD
)*SID_MAX_SUB_AUTHORITIES
];
915 DWORD len
= sizeof(buffer
);
918 status
= NtQueryInformationToken(GetCurrentThreadEffectiveToken(), TokenUser
, buffer
, len
, &len
);
919 if (status
== STATUS_SUCCESS
)
921 KeyPath
->MaximumLength
= 0;
922 status
= RtlConvertSidToUnicodeString(KeyPath
, ((TOKEN_USER
*)buffer
)->User
.Sid
, FALSE
);
923 if (status
== STATUS_BUFFER_OVERFLOW
)
925 PWCHAR buf
= RtlAllocateHeap(GetProcessHeap(), 0,
926 sizeof(pathW
) + KeyPath
->Length
+ sizeof(WCHAR
));
929 memcpy(buf
, pathW
, sizeof(pathW
));
930 KeyPath
->MaximumLength
= KeyPath
->Length
+ sizeof(WCHAR
);
931 KeyPath
->Buffer
= (PWCHAR
)((LPBYTE
)buf
+ sizeof(pathW
));
932 status
= RtlConvertSidToUnicodeString(KeyPath
,
933 ((TOKEN_USER
*)buffer
)->User
.Sid
, FALSE
);
934 KeyPath
->Buffer
= buf
;
935 KeyPath
->Length
+= sizeof(pathW
);
936 KeyPath
->MaximumLength
+= sizeof(pathW
);
939 status
= STATUS_NO_MEMORY
;
945 /******************************************************************************
946 * RtlOpenCurrentUser [NTDLL.@]
949 * If we return just HKEY_CURRENT_USER the advapi tries to find a remote
950 * registry (odd handle) and fails.
952 NTSTATUS WINAPI
RtlOpenCurrentUser(
953 IN ACCESS_MASK DesiredAccess
, /* [in] */
954 OUT PHANDLE KeyHandle
) /* [out] handle of HKEY_CURRENT_USER */
956 OBJECT_ATTRIBUTES ObjectAttributes
;
957 UNICODE_STRING ObjectName
;
960 TRACE("(0x%08x, %p)\n",DesiredAccess
, KeyHandle
);
962 if ((ret
= RtlFormatCurrentUserKeyPath(&ObjectName
))) return ret
;
963 InitializeObjectAttributes(&ObjectAttributes
,&ObjectName
,OBJ_CASE_INSENSITIVE
,0, NULL
);
964 ret
= NtCreateKey(KeyHandle
, DesiredAccess
, &ObjectAttributes
, 0, NULL
, 0, NULL
);
965 RtlFreeUnicodeString(&ObjectName
);
970 static NTSTATUS
RTL_ReportRegistryValue(PKEY_VALUE_FULL_INFORMATION pInfo
,
971 PRTL_QUERY_REGISTRY_TABLE pQuery
, PVOID pContext
, PVOID pEnvironment
)
974 UNICODE_STRING src
, dst
;
979 NTSTATUS status
= STATUS_SUCCESS
;
986 if (pQuery
->Flags
& RTL_QUERY_REGISTRY_DIRECT
)
987 return STATUS_INVALID_PARAMETER
;
990 status
= pQuery
->QueryRoutine(pQuery
->Name
, pQuery
->DefaultType
, pQuery
->DefaultData
,
991 pQuery
->DefaultLength
, pContext
, pQuery
->EntryContext
);
995 len
= pInfo
->DataLength
;
997 if (pQuery
->Flags
& RTL_QUERY_REGISTRY_DIRECT
)
999 str
= pQuery
->EntryContext
;
1004 if (!(pQuery
->Flags
& RTL_QUERY_REGISTRY_NOEXPAND
))
1006 RtlInitUnicodeString(&src
, (WCHAR
*)(((CHAR
*)pInfo
) + pInfo
->DataOffset
));
1008 dst
.MaximumLength
= 0;
1009 RtlExpandEnvironmentStrings_U(pEnvironment
, &src
, &dst
, &res
);
1011 dst
.MaximumLength
= res
;
1012 dst
.Buffer
= RtlAllocateHeap(GetProcessHeap(), 0, res
* sizeof(WCHAR
));
1013 RtlExpandEnvironmentStrings_U(pEnvironment
, &src
, &dst
, &res
);
1014 status
= pQuery
->QueryRoutine(pQuery
->Name
, pInfo
->Type
, dst
.Buffer
,
1015 dst
.Length
, pContext
, pQuery
->EntryContext
);
1016 RtlFreeHeap(GetProcessHeap(), 0, dst
.Buffer
);
1021 if (str
->Buffer
== NULL
)
1022 RtlCreateUnicodeString(str
, (WCHAR
*)(((CHAR
*)pInfo
) + pInfo
->DataOffset
));
1024 RtlAppendUnicodeToString(str
, (WCHAR
*)(((CHAR
*)pInfo
) + pInfo
->DataOffset
));
1028 if (!(pQuery
->Flags
& RTL_QUERY_REGISTRY_NOEXPAND
))
1029 return STATUS_INVALID_PARAMETER
;
1031 if (str
->Buffer
== NULL
)
1033 str
->Buffer
= RtlAllocateHeap(GetProcessHeap(), 0, len
);
1034 str
->MaximumLength
= len
;
1036 len
= min(len
, str
->MaximumLength
);
1037 memcpy(str
->Buffer
, ((CHAR
*)pInfo
) + pInfo
->DataOffset
, len
);
1042 bin
= pQuery
->EntryContext
;
1043 if (pInfo
->DataLength
<= sizeof(ULONG
))
1044 memcpy(bin
, ((CHAR
*)pInfo
) + pInfo
->DataOffset
,
1048 if (bin
[0] <= sizeof(ULONG
))
1050 memcpy(&bin
[1], ((CHAR
*)pInfo
) + pInfo
->DataOffset
,
1051 min(-bin
[0], pInfo
->DataLength
));
1055 len
= min(bin
[0], pInfo
->DataLength
);
1057 bin
[2] = pInfo
->Type
;
1058 memcpy(&bin
[3], ((CHAR
*)pInfo
) + pInfo
->DataOffset
, len
);
1066 if((pQuery
->Flags
& RTL_QUERY_REGISTRY_NOEXPAND
) ||
1067 (pInfo
->Type
!= REG_EXPAND_SZ
&& pInfo
->Type
!= REG_MULTI_SZ
))
1069 status
= pQuery
->QueryRoutine(pQuery
->Name
, pInfo
->Type
,
1070 ((CHAR
*)pInfo
) + pInfo
->DataOffset
, pInfo
->DataLength
,
1071 pContext
, pQuery
->EntryContext
);
1073 else if (pInfo
->Type
== REG_EXPAND_SZ
)
1075 RtlInitUnicodeString(&src
, (WCHAR
*)(((CHAR
*)pInfo
) + pInfo
->DataOffset
));
1077 dst
.MaximumLength
= 0;
1078 RtlExpandEnvironmentStrings_U(pEnvironment
, &src
, &dst
, &res
);
1080 dst
.MaximumLength
= res
;
1081 dst
.Buffer
= RtlAllocateHeap(GetProcessHeap(), 0, res
* sizeof(WCHAR
));
1082 RtlExpandEnvironmentStrings_U(pEnvironment
, &src
, &dst
, &res
);
1083 status
= pQuery
->QueryRoutine(pQuery
->Name
, pInfo
->Type
, dst
.Buffer
,
1084 dst
.Length
, pContext
, pQuery
->EntryContext
);
1085 RtlFreeHeap(GetProcessHeap(), 0, dst
.Buffer
);
1087 else /* REG_MULTI_SZ */
1089 if(pQuery
->Flags
& RTL_QUERY_REGISTRY_NOEXPAND
)
1091 for (offset
= 0; offset
<= pInfo
->DataLength
; offset
+= len
+ sizeof(WCHAR
))
1093 wstr
= (WCHAR
*)(((CHAR
*)pInfo
) + offset
);
1094 len
= strlenW(wstr
) * sizeof(WCHAR
);
1095 status
= pQuery
->QueryRoutine(pQuery
->Name
, pInfo
->Type
, wstr
, len
,
1096 pContext
, pQuery
->EntryContext
);
1097 if(status
!= STATUS_SUCCESS
&& status
!= STATUS_BUFFER_TOO_SMALL
)
1103 while(count
<=pInfo
->DataLength
)
1105 String
= (WCHAR
*)(((CHAR
*)pInfo
) + pInfo
->DataOffset
)+count
;
1106 count
+=strlenW(String
)+1;
1107 RtlInitUnicodeString(&src
, (WCHAR
*)(((CHAR
*)pInfo
) + pInfo
->DataOffset
));
1109 dst
.MaximumLength
= 0;
1110 RtlExpandEnvironmentStrings_U(pEnvironment
, &src
, &dst
, &res
);
1112 dst
.MaximumLength
= res
;
1113 dst
.Buffer
= RtlAllocateHeap(GetProcessHeap(), 0, res
* sizeof(WCHAR
));
1114 RtlExpandEnvironmentStrings_U(pEnvironment
, &src
, &dst
, &res
);
1115 status
= pQuery
->QueryRoutine(pQuery
->Name
, pInfo
->Type
, dst
.Buffer
,
1116 dst
.Length
, pContext
, pQuery
->EntryContext
);
1117 RtlFreeHeap(GetProcessHeap(), 0, dst
.Buffer
);
1118 if(status
!= STATUS_SUCCESS
&& status
!= STATUS_BUFFER_TOO_SMALL
)
1128 static NTSTATUS
RTL_GetKeyHandle(ULONG RelativeTo
, PCWSTR Path
, PHANDLE handle
)
1130 UNICODE_STRING KeyString
;
1131 OBJECT_ATTRIBUTES regkey
;
1136 static const WCHAR empty
[] = {0};
1137 static const WCHAR control
[] = {'\\','R','e','g','i','s','t','r','y','\\','M','a','c','h','i','n','e',
1138 '\\','S','y','s','t','e','m','\\','C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\',
1139 'C','o','n','t','r','o','l','\\',0};
1141 static const WCHAR devicemap
[] = {'\\','R','e','g','i','s','t','r','y','\\','M','a','c','h','i','n','e','\\',
1142 'H','a','r','d','w','a','r','e','\\','D','e','v','i','c','e','M','a','p','\\',0};
1144 static const WCHAR services
[] = {'\\','R','e','g','i','s','t','r','y','\\','M','a','c','h','i','n','e','\\',
1145 'S','y','s','t','e','m','\\','C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\',
1146 'S','e','r','v','i','c','e','s','\\',0};
1148 static const WCHAR user
[] = {'\\','R','e','g','i','s','t','r','y','\\','U','s','e','r','\\',
1149 'C','u','r','r','e','n','t','U','s','e','r','\\',0};
1151 static const WCHAR windows_nt
[] = {'\\','R','e','g','i','s','t','r','y','\\','M','a','c','h','i','n','e','\\',
1152 'S','o','f','t','w','a','r','e','\\','M','i','c','r','o','s','o','f','t','\\',
1153 'W','i','n','d','o','w','s',' ','N','T','\\','C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',0};
1155 switch (RelativeTo
& 0xff)
1157 case RTL_REGISTRY_ABSOLUTE
:
1161 case RTL_REGISTRY_CONTROL
:
1165 case RTL_REGISTRY_DEVICEMAP
:
1169 case RTL_REGISTRY_SERVICES
:
1173 case RTL_REGISTRY_USER
:
1177 case RTL_REGISTRY_WINDOWS_NT
:
1182 return STATUS_INVALID_PARAMETER
;
1185 len
= (strlenW(base
) + strlenW(Path
) + 1) * sizeof(WCHAR
);
1186 KeyString
.Buffer
= RtlAllocateHeap(GetProcessHeap(), 0, len
);
1187 if (KeyString
.Buffer
== NULL
)
1188 return STATUS_NO_MEMORY
;
1190 strcpyW(KeyString
.Buffer
, base
);
1191 strcatW(KeyString
.Buffer
, Path
);
1192 KeyString
.Length
= len
- sizeof(WCHAR
);
1193 KeyString
.MaximumLength
= len
;
1194 InitializeObjectAttributes(®key
, &KeyString
, OBJ_CASE_INSENSITIVE
, NULL
, NULL
);
1195 status
= NtOpenKey(handle
, KEY_ALL_ACCESS
, ®key
);
1196 RtlFreeHeap(GetProcessHeap(), 0, KeyString
.Buffer
);
1200 /*************************************************************************
1201 * RtlQueryRegistryValues [NTDLL.@]
1203 * Query multiple registry values with a single call.
1206 * RelativeTo [I] Registry path that Path refers to
1207 * Path [I] Path to key
1208 * QueryTable [I] Table of key values to query
1209 * Context [I] Parameter to pass to the application defined QueryRoutine function
1210 * Environment [I] Optional parameter to use when performing expansion
1213 * STATUS_SUCCESS or an appropriate NTSTATUS error code.
1215 NTSTATUS WINAPI
RtlQueryRegistryValues(IN ULONG RelativeTo
, IN PCWSTR Path
,
1216 IN PRTL_QUERY_REGISTRY_TABLE QueryTable
, IN PVOID Context
,
1217 IN PVOID Environment OPTIONAL
)
1219 UNICODE_STRING Value
;
1220 HANDLE handle
, topkey
;
1221 PKEY_VALUE_FULL_INFORMATION pInfo
= NULL
;
1222 ULONG len
, buflen
= 0;
1223 NTSTATUS status
=STATUS_SUCCESS
, ret
= STATUS_SUCCESS
;
1226 TRACE("(%d, %s, %p, %p, %p)\n", RelativeTo
, debugstr_w(Path
), QueryTable
, Context
, Environment
);
1229 return STATUS_INVALID_PARAMETER
;
1231 /* get a valid handle */
1232 if (RelativeTo
& RTL_REGISTRY_HANDLE
)
1233 topkey
= handle
= (HANDLE
)Path
;
1236 status
= RTL_GetKeyHandle(RelativeTo
, Path
, &topkey
);
1239 if(status
!= STATUS_SUCCESS
)
1242 /* Process query table entries */
1243 for (; QueryTable
->QueryRoutine
!= NULL
|| QueryTable
->Name
!= NULL
; ++QueryTable
)
1245 if (QueryTable
->Flags
&
1246 (RTL_QUERY_REGISTRY_SUBKEY
| RTL_QUERY_REGISTRY_TOPKEY
))
1248 /* topkey must be kept open just in case we will reuse it later */
1249 if (handle
!= topkey
)
1252 if (QueryTable
->Flags
& RTL_QUERY_REGISTRY_SUBKEY
)
1255 status
= RTL_GetKeyHandle(PtrToUlong(QueryTable
->Name
), Path
, &handle
);
1256 if(status
!= STATUS_SUCCESS
)
1266 if (QueryTable
->Flags
& RTL_QUERY_REGISTRY_NOVALUE
)
1268 QueryTable
->QueryRoutine(QueryTable
->Name
, REG_NONE
, NULL
, 0,
1269 Context
, QueryTable
->EntryContext
);
1275 if (QueryTable
->Flags
& RTL_QUERY_REGISTRY_REQUIRED
)
1277 ret
= STATUS_OBJECT_NAME_NOT_FOUND
;
1283 if (QueryTable
->Name
== NULL
)
1285 if (QueryTable
->Flags
& RTL_QUERY_REGISTRY_DIRECT
)
1287 ret
= STATUS_INVALID_PARAMETER
;
1291 /* Report all subkeys */
1294 status
= NtEnumerateValueKey(handle
, i
,
1295 KeyValueFullInformation
, pInfo
, buflen
, &len
);
1296 if (status
== STATUS_NO_MORE_ENTRIES
)
1298 if (status
== STATUS_BUFFER_OVERFLOW
||
1299 status
== STATUS_BUFFER_TOO_SMALL
)
1302 RtlFreeHeap(GetProcessHeap(), 0, pInfo
);
1303 pInfo
= RtlAllocateHeap(GetProcessHeap(), 0, buflen
);
1304 NtEnumerateValueKey(handle
, i
, KeyValueFullInformation
,
1305 pInfo
, buflen
, &len
);
1308 status
= RTL_ReportRegistryValue(pInfo
, QueryTable
, Context
, Environment
);
1309 if(status
!= STATUS_SUCCESS
&& status
!= STATUS_BUFFER_TOO_SMALL
)
1314 if (QueryTable
->Flags
& RTL_QUERY_REGISTRY_DELETE
)
1316 RtlInitUnicodeString(&Value
, pInfo
->Name
);
1317 NtDeleteValueKey(handle
, &Value
);
1321 if (i
== 0 && (QueryTable
->Flags
& RTL_QUERY_REGISTRY_REQUIRED
))
1323 ret
= STATUS_OBJECT_NAME_NOT_FOUND
;
1329 RtlInitUnicodeString(&Value
, QueryTable
->Name
);
1330 status
= NtQueryValueKey(handle
, &Value
, KeyValueFullInformation
,
1331 pInfo
, buflen
, &len
);
1332 if (status
== STATUS_BUFFER_OVERFLOW
||
1333 status
== STATUS_BUFFER_TOO_SMALL
)
1336 RtlFreeHeap(GetProcessHeap(), 0, pInfo
);
1337 pInfo
= RtlAllocateHeap(GetProcessHeap(), 0, buflen
);
1338 status
= NtQueryValueKey(handle
, &Value
,
1339 KeyValueFullInformation
, pInfo
, buflen
, &len
);
1341 if (status
!= STATUS_SUCCESS
)
1343 if (QueryTable
->Flags
& RTL_QUERY_REGISTRY_REQUIRED
)
1345 ret
= STATUS_OBJECT_NAME_NOT_FOUND
;
1348 status
= RTL_ReportRegistryValue(NULL
, QueryTable
, Context
, Environment
);
1349 if(status
!= STATUS_SUCCESS
&& status
!= STATUS_BUFFER_TOO_SMALL
)
1357 status
= RTL_ReportRegistryValue(pInfo
, QueryTable
, Context
, Environment
);
1358 if(status
!= STATUS_SUCCESS
&& status
!= STATUS_BUFFER_TOO_SMALL
)
1363 if (QueryTable
->Flags
& RTL_QUERY_REGISTRY_DELETE
)
1364 NtDeleteValueKey(handle
, &Value
);
1370 RtlFreeHeap(GetProcessHeap(), 0, pInfo
);
1371 if (handle
!= topkey
)
1377 /*************************************************************************
1378 * RtlCheckRegistryKey [NTDLL.@]
1380 * Query multiple registry values with a single call.
1383 * RelativeTo [I] Registry path that Path refers to
1384 * Path [I] Path to key
1387 * STATUS_SUCCESS if the specified key exists, or an NTSTATUS error code.
1389 NTSTATUS WINAPI
RtlCheckRegistryKey(IN ULONG RelativeTo
, IN PWSTR Path
)
1394 TRACE("(%d, %s)\n", RelativeTo
, debugstr_w(Path
));
1396 if((!RelativeTo
) && Path
== NULL
)
1397 return STATUS_OBJECT_PATH_SYNTAX_BAD
;
1398 if(RelativeTo
& RTL_REGISTRY_HANDLE
)
1399 return STATUS_SUCCESS
;
1401 status
= RTL_GetKeyHandle(RelativeTo
, Path
, &handle
);
1402 if (handle
) NtClose(handle
);
1403 if (status
== STATUS_INVALID_HANDLE
) status
= STATUS_OBJECT_NAME_NOT_FOUND
;
1407 /*************************************************************************
1408 * RtlDeleteRegistryValue [NTDLL.@]
1410 * Query multiple registry values with a single call.
1413 * RelativeTo [I] Registry path that Path refers to
1414 * Path [I] Path to key
1415 * ValueName [I] Name of the value to delete
1418 * STATUS_SUCCESS if the specified key is successfully deleted, or an NTSTATUS error code.
1420 NTSTATUS WINAPI
RtlDeleteRegistryValue(IN ULONG RelativeTo
, IN PCWSTR Path
, IN PCWSTR ValueName
)
1424 UNICODE_STRING Value
;
1426 TRACE("(%d, %s, %s)\n", RelativeTo
, debugstr_w(Path
), debugstr_w(ValueName
));
1428 RtlInitUnicodeString(&Value
, ValueName
);
1429 if(RelativeTo
== RTL_REGISTRY_HANDLE
)
1431 return NtDeleteValueKey((HANDLE
)Path
, &Value
);
1433 status
= RTL_GetKeyHandle(RelativeTo
, Path
, &handle
);
1434 if (status
) return status
;
1435 status
= NtDeleteValueKey(handle
, &Value
);
1440 /*************************************************************************
1441 * RtlWriteRegistryValue [NTDLL.@]
1443 * Sets the registry value with provided data.
1446 * RelativeTo [I] Registry path that path parameter refers to
1447 * path [I] Path to the key (or handle - see RTL_GetKeyHandle)
1448 * name [I] Name of the registry value to set
1449 * type [I] Type of the registry key to set
1450 * data [I] Pointer to the user data to be set
1451 * length [I] Length of the user data pointed by data
1454 * STATUS_SUCCESS if the specified key is successfully set,
1455 * or an NTSTATUS error code.
1457 NTSTATUS WINAPI
RtlWriteRegistryValue( ULONG RelativeTo
, PCWSTR path
, PCWSTR name
,
1458 ULONG type
, PVOID data
, ULONG length
)
1464 TRACE( "(%d, %s, %s) -> %d: %p [%d]\n", RelativeTo
, debugstr_w(path
), debugstr_w(name
),
1465 type
, data
, length
);
1467 RtlInitUnicodeString( &str
, name
);
1469 if (RelativeTo
== RTL_REGISTRY_HANDLE
)
1470 return NtSetValueKey( (HANDLE
)path
, &str
, 0, type
, data
, length
);
1472 status
= RTL_GetKeyHandle( RelativeTo
, path
, &hkey
);
1473 if (status
!= STATUS_SUCCESS
) return status
;
1475 status
= NtSetValueKey( hkey
, &str
, 0, type
, data
, length
);
1481 /*************************************************************************
1482 * NtQueryLicenseValue [NTDLL.@]
1485 * On Windows all license properties are stored in a single key, but
1486 * unless there is some app which explicitly depends on that, there is
1487 * no good reason to reproduce that.
1489 NTSTATUS WINAPI
NtQueryLicenseValue( const UNICODE_STRING
*name
, ULONG
*result_type
,
1490 PVOID data
, ULONG length
, ULONG
*result_len
)
1492 static const WCHAR LicenseInformationW
[] = {'M','a','c','h','i','n','e','\\',
1493 'S','o','f','t','w','a','r','e','\\',
1494 'W','i','n','e','\\','L','i','c','e','n','s','e',
1495 'I','n','f','o','r','m','a','t','i','o','n',0};
1496 KEY_VALUE_PARTIAL_INFORMATION
*info
;
1497 NTSTATUS status
= STATUS_OBJECT_NAME_NOT_FOUND
;
1498 DWORD info_length
, count
;
1499 OBJECT_ATTRIBUTES attr
;
1500 UNICODE_STRING keyW
;
1503 if (!name
|| !name
->Buffer
|| !name
->Length
|| !result_len
)
1504 return STATUS_INVALID_PARAMETER
;
1506 info_length
= FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION
, Data
) + length
;
1507 info
= RtlAllocateHeap( GetProcessHeap(), 0, info_length
);
1508 if (!info
) return STATUS_NO_MEMORY
;
1510 attr
.Length
= sizeof(attr
);
1511 attr
.RootDirectory
= 0;
1512 attr
.ObjectName
= &keyW
;
1513 attr
.Attributes
= 0;
1514 attr
.SecurityDescriptor
= NULL
;
1515 attr
.SecurityQualityOfService
= NULL
;
1516 RtlInitUnicodeString( &keyW
, LicenseInformationW
);
1518 /* @@ Wine registry key: HKLM\Software\Wine\LicenseInformation */
1519 if (!NtOpenKey( &hkey
, KEY_READ
, &attr
))
1521 status
= NtQueryValueKey( hkey
, name
, KeyValuePartialInformation
,
1522 info
, info_length
, &count
);
1523 if (!status
|| status
== STATUS_BUFFER_OVERFLOW
)
1526 *result_type
= info
->Type
;
1528 *result_len
= info
->DataLength
;
1530 if (status
== STATUS_BUFFER_OVERFLOW
)
1531 status
= STATUS_BUFFER_TOO_SMALL
;
1533 memcpy( data
, info
->Data
, info
->DataLength
);
1538 if (status
== STATUS_OBJECT_NAME_NOT_FOUND
)
1539 FIXME( "License key %s not found\n", debugstr_w(name
->Buffer
) );
1541 RtlFreeHeap( GetProcessHeap(), 0, info
);