4 * Copyright (C) 1999 Juergen Schmied
5 * Copyright (C) 2000 Alexandre Julliard
8 * HKEY_LOCAL_MACHINE \\REGISTRY\\MACHINE
9 * HKEY_USERS \\REGISTRY\\USER
10 * HKEY_CURRENT_CONFIG \\REGISTRY\\MACHINE\\SYSTEM\\CURRENTCONTROLSET\\HARDWARE PROFILES\\CURRENT
11 * HKEY_CLASSES \\REGISTRY\\MACHINE\\SOFTWARE\\CLASSES
15 #include "debugtools.h"
18 #include "wine/unicode.h"
21 #include "ntdll_misc.h"
23 DEFAULT_DEBUG_CHANNEL(reg
);
25 static const WCHAR root_name
[] = { '\\','R','e','g','i','s','t','r','y','\\',0 };
26 static const UNICODE_STRING root_path
=
28 sizeof(root_name
)-sizeof(WCHAR
), /* Length */
29 sizeof(root_name
), /* MaximumLength */
30 (LPWSTR
)root_name
/* Buffer */
33 /* maximum length of a key/value name in bytes (without terminating null) */
34 #define MAX_NAME_LENGTH ((MAX_PATH-1) * sizeof(WCHAR))
37 /* copy a key name into the request buffer */
38 static inline NTSTATUS
copy_nameU( LPWSTR Dest
, const UNICODE_STRING
*name
, UINT max
)
40 if (name
->Length
>= max
) return STATUS_BUFFER_OVERFLOW
;
41 if (name
->Length
) memcpy( Dest
, name
->Buffer
, name
->Length
);
42 Dest
[name
->Length
/ sizeof(WCHAR
)] = 0;
43 return STATUS_SUCCESS
;
47 /******************************************************************************
51 NTSTATUS WINAPI
NtCreateKey( PHANDLE retkey
, ACCESS_MASK access
, const OBJECT_ATTRIBUTES
*attr
,
52 ULONG TitleIndex
, const UNICODE_STRING
*class, ULONG options
,
56 DWORD len
= attr
->ObjectName
->Length
;
58 TRACE( "(0x%x,%s,%s,%lx,%lx,%p)\n", attr
->RootDirectory
, debugstr_us(attr
->ObjectName
),
59 debugstr_us(class), options
, access
, retkey
);
61 if (len
> MAX_NAME_LENGTH
) return STATUS_BUFFER_OVERFLOW
;
62 len
+= sizeof(WCHAR
); /* for storing name length */
66 if (len
> REQUEST_MAX_VAR_SIZE
) return STATUS_BUFFER_OVERFLOW
;
68 if (!retkey
) return STATUS_INVALID_PARAMETER
;
70 SERVER_START_VAR_REQ( create_key
, len
)
72 WCHAR
*data
= server_data_ptr(req
);
74 req
->parent
= attr
->RootDirectory
;
76 req
->options
= options
;
79 *data
++ = attr
->ObjectName
->Length
;
80 memcpy( data
, attr
->ObjectName
->Buffer
, attr
->ObjectName
->Length
);
81 if (class) memcpy( (char *)data
+ attr
->ObjectName
->Length
, class->Buffer
, class->Length
);
82 if (!(ret
= SERVER_CALL()))
85 if (dispos
) *dispos
= req
->created
? REG_CREATED_NEW_KEY
: REG_OPENED_EXISTING_KEY
;
89 TRACE("<- 0x%04x\n", *retkey
);
94 /******************************************************************************
95 * NtOpenKey [NTDLL.129]
97 * OUT PHANDLE retkey (returns 0 when failure)
98 * IN ACCESS_MASK access
99 * IN POBJECT_ATTRIBUTES attr
101 NTSTATUS WINAPI
NtOpenKey( PHANDLE retkey
, ACCESS_MASK access
, const OBJECT_ATTRIBUTES
*attr
)
104 DWORD len
= attr
->ObjectName
->Length
;
106 TRACE( "(0x%x,%s,%lx,%p)\n", attr
->RootDirectory
,
107 debugstr_us(attr
->ObjectName
), access
, retkey
);
109 if (len
> MAX_NAME_LENGTH
) return STATUS_BUFFER_OVERFLOW
;
110 if (!retkey
) return STATUS_INVALID_PARAMETER
;
112 SERVER_START_VAR_REQ( open_key
, len
)
114 req
->parent
= attr
->RootDirectory
;
115 req
->access
= access
;
116 memcpy( server_data_ptr(req
), attr
->ObjectName
->Buffer
, len
);
121 TRACE("<- 0x%04x\n", *retkey
);
126 /******************************************************************************
127 * NtDeleteKey [NTDLL]
130 NTSTATUS WINAPI
NtDeleteKey( HANDLE hkey
)
134 TRACE( "(%x)\n", hkey
);
136 SERVER_START_REQ( delete_key
)
146 /******************************************************************************
147 * NtDeleteValueKey [NTDLL]
150 NTSTATUS WINAPI
NtDeleteValueKey( HANDLE hkey
, const UNICODE_STRING
*name
)
154 TRACE( "(0x%x,%s)\n", hkey
, debugstr_us(name
) );
155 if (name
->Length
> MAX_NAME_LENGTH
) return STATUS_BUFFER_OVERFLOW
;
157 SERVER_START_VAR_REQ( delete_key_value
, name
->Length
)
160 memcpy( server_data_ptr(req
), name
->Buffer
, name
->Length
);
168 /******************************************************************************
171 * Helper function for NtQueryKey and NtEnumerateKey
173 static NTSTATUS
fill_key_info( KEY_INFORMATION_CLASS info_class
, void *info
, DWORD length
,
174 DWORD
*result_len
, const struct enum_key_request
*req
)
176 WCHAR
*name_ptr
= server_data_ptr(req
);
177 int name_size
= *name_ptr
++;
178 WCHAR
*class_ptr
= (WCHAR
*)((char *)name_ptr
+ name_size
);
179 int class_size
= server_data_size(req
) - sizeof(WCHAR
) - name_size
;
183 RtlSecondsSince1970ToTime( req
->modif
, &modif
);
187 case KeyBasicInformation
:
189 KEY_BASIC_INFORMATION keyinfo
;
190 fixed_size
= sizeof(keyinfo
) - sizeof(keyinfo
.Name
);
191 keyinfo
.LastWriteTime
= modif
;
192 keyinfo
.TitleIndex
= 0;
193 keyinfo
.NameLength
= name_size
;
194 memcpy( info
, &keyinfo
, min( length
, fixed_size
) );
198 case KeyFullInformation
:
200 KEY_FULL_INFORMATION keyinfo
;
201 fixed_size
= sizeof(keyinfo
) - sizeof(keyinfo
.Class
);
202 keyinfo
.LastWriteTime
= modif
;
203 keyinfo
.TitleIndex
= 0;
204 keyinfo
.ClassLength
= class_size
;
205 keyinfo
.ClassOffset
= keyinfo
.ClassLength
? fixed_size
: -1;
206 keyinfo
.SubKeys
= req
->subkeys
;
207 keyinfo
.MaxNameLen
= req
->max_subkey
;
208 keyinfo
.MaxClassLen
= req
->max_class
;
209 keyinfo
.Values
= req
->values
;
210 keyinfo
.MaxValueNameLen
= req
->max_value
;
211 keyinfo
.MaxValueDataLen
= req
->max_data
;
212 memcpy( info
, &keyinfo
, min( length
, fixed_size
) );
216 case KeyNodeInformation
:
218 KEY_NODE_INFORMATION keyinfo
;
219 fixed_size
= sizeof(keyinfo
) - sizeof(keyinfo
.Name
);
220 keyinfo
.LastWriteTime
= modif
;
221 keyinfo
.TitleIndex
= 0;
222 keyinfo
.ClassLength
= class_size
;
223 keyinfo
.ClassOffset
= fixed_size
+ name_size
;
224 if (!keyinfo
.ClassLength
|| keyinfo
.ClassOffset
> length
) keyinfo
.ClassOffset
= -1;
225 keyinfo
.NameLength
= name_size
;
226 memcpy( info
, &keyinfo
, min( length
, fixed_size
) );
230 FIXME("Information class not implemented\n");
231 return STATUS_INVALID_PARAMETER
;
234 *result_len
= fixed_size
+ name_size
+ class_size
;
235 if (length
<= fixed_size
) return STATUS_BUFFER_OVERFLOW
;
236 length
-= fixed_size
;
241 memcpy( (char *)info
+ fixed_size
, name_ptr
, min(length
,name_size
) );
242 if (length
< name_size
) return STATUS_BUFFER_OVERFLOW
;
249 memcpy( (char *)info
+ fixed_size
+ name_size
, class_ptr
, min(length
,class_size
) );
250 if (length
< class_size
) return STATUS_BUFFER_OVERFLOW
;
252 return STATUS_SUCCESS
;
257 /******************************************************************************
258 * NtEnumerateKey [NTDLL]
262 * the name copied into the buffer is NOT 0-terminated
264 NTSTATUS WINAPI
NtEnumerateKey( HANDLE handle
, ULONG index
, KEY_INFORMATION_CLASS info_class
,
265 void *info
, DWORD length
, DWORD
*result_len
)
269 /* -1 means query key, so avoid it here */
270 if (index
== (ULONG
)-1) return STATUS_NO_MORE_ENTRIES
;
272 SERVER_START_VAR_REQ( enum_key
, REQUEST_MAX_VAR_SIZE
)
276 req
->full
= (info_class
== KeyFullInformation
);
277 if (!(ret
= SERVER_CALL()))
279 ret
= fill_key_info( info_class
, info
, length
, result_len
, req
);
287 /******************************************************************************
291 NTSTATUS WINAPI
NtQueryKey( HANDLE handle
, KEY_INFORMATION_CLASS info_class
,
292 void *info
, DWORD length
, DWORD
*result_len
)
296 SERVER_START_VAR_REQ( enum_key
, REQUEST_MAX_VAR_SIZE
)
300 req
->full
= (info_class
== KeyFullInformation
);
301 if (!(ret
= SERVER_CALL()))
303 ret
= fill_key_info( info_class
, info
, length
, result_len
, req
);
311 /* fill the key value info structure for a specific info class */
312 static void copy_key_value_info( KEY_VALUE_INFORMATION_CLASS info_class
, void *info
,
313 DWORD length
, int type
, int name_len
, int data_len
)
317 case KeyValueBasicInformation
:
319 KEY_VALUE_BASIC_INFORMATION keyinfo
;
320 keyinfo
.TitleIndex
= 0;
322 keyinfo
.NameLength
= name_len
;
323 length
= min( length
, sizeof(keyinfo
) - sizeof(keyinfo
.Name
) );
324 memcpy( info
, &keyinfo
, length
);
327 case KeyValueFullInformation
:
329 KEY_VALUE_FULL_INFORMATION keyinfo
;
330 keyinfo
.TitleIndex
= 0;
332 keyinfo
.DataOffset
= sizeof(keyinfo
) - sizeof(keyinfo
.Name
) + name_len
;
333 keyinfo
.DataLength
= data_len
;
334 keyinfo
.NameLength
= name_len
;
335 length
= min( length
, sizeof(keyinfo
) - sizeof(keyinfo
.Name
) );
336 memcpy( info
, &keyinfo
, length
);
339 case KeyValuePartialInformation
:
341 KEY_VALUE_PARTIAL_INFORMATION keyinfo
;
342 keyinfo
.TitleIndex
= 0;
344 keyinfo
.DataLength
= data_len
;
345 length
= min( length
, sizeof(keyinfo
) - sizeof(keyinfo
.Data
) );
346 memcpy( info
, &keyinfo
, length
);
355 /******************************************************************************
356 * NtEnumerateValueKey [NTDLL]
357 * ZwEnumerateValueKey
359 NTSTATUS WINAPI
NtEnumerateValueKey( HANDLE handle
, ULONG index
,
360 KEY_VALUE_INFORMATION_CLASS info_class
,
361 void *info
, DWORD length
, DWORD
*result_len
)
364 char *data_ptr
, *name_ptr
;
365 int fixed_size
= 0, name_len
= 0, data_len
= 0, offset
= 0, type
= 0, total_len
= 0;
367 TRACE( "(0x%x,%lu,%d,%p,%ld)\n", handle
, index
, info_class
, info
, length
);
369 /* compute the length we want to retrieve */
372 case KeyValueBasicInformation
:
373 fixed_size
= sizeof(KEY_VALUE_BASIC_INFORMATION
) - sizeof(WCHAR
);
374 name_ptr
= (char *)info
+ fixed_size
;
377 case KeyValueFullInformation
:
378 fixed_size
= sizeof(KEY_VALUE_FULL_INFORMATION
) - sizeof(WCHAR
);
379 name_ptr
= data_ptr
= (char *)info
+ fixed_size
;
381 case KeyValuePartialInformation
:
382 fixed_size
= sizeof(KEY_VALUE_PARTIAL_INFORMATION
) - sizeof(UCHAR
);
384 data_ptr
= (char *)info
+ fixed_size
;
387 FIXME( "Information class %d not implemented\n", info_class
);
388 return STATUS_INVALID_PARAMETER
;
390 if (length
> fixed_size
) data_len
= length
- fixed_size
;
394 size_t reqlen
= data_len
+ sizeof(WCHAR
);
395 if (name_ptr
&& !offset
) reqlen
+= MAX_PATH
*sizeof(WCHAR
);
396 reqlen
= min( reqlen
, REQUEST_MAX_VAR_SIZE
);
398 SERVER_START_VAR_REQ( enum_key_value
, reqlen
)
402 req
->offset
= offset
;
404 if (!(ret
= SERVER_CALL()))
406 size_t size
= server_data_size(req
) - sizeof(WCHAR
);
407 WCHAR
*name
= server_data_ptr(req
);
408 if (!offset
) /* name is only present on the first request */
414 if (name_len
> data_len
) /* overflow */
416 memcpy( name_ptr
, name
, data_len
);
418 ret
= STATUS_BUFFER_OVERFLOW
;
422 memcpy( name_ptr
, name
, name_len
);
423 data_len
-= name_len
;
424 if (data_ptr
) data_ptr
+= name_len
;
427 name
+= name_len
/ sizeof(WCHAR
);
429 else name
++; /* skip 0 length */
433 size
= min( size
, data_len
);
434 memcpy( data_ptr
+ offset
, name
, size
);
439 total_len
= req
->len
;
444 } while (data_len
&& data_ptr
&& offset
< total_len
);
446 *result_len
= total_len
+ fixed_size
+ (name_ptr
? name_len
: 0);
448 if (data_ptr
&& offset
< total_len
) ret
= STATUS_BUFFER_OVERFLOW
;
449 if (length
< fixed_size
) ret
= STATUS_BUFFER_OVERFLOW
;
451 copy_key_value_info( info_class
, info
, length
, type
, name_len
, total_len
);
457 /******************************************************************************
458 * NtQueryValueKey [NTDLL]
462 * the name in the KeyValueInformation is never set
464 NTSTATUS WINAPI
NtQueryValueKey( HANDLE handle
, const UNICODE_STRING
*name
,
465 KEY_VALUE_INFORMATION_CLASS info_class
,
466 void *info
, DWORD length
, DWORD
*result_len
)
470 int fixed_size
= 0, data_len
= 0, offset
= 0, type
= 0, total_len
= 0;
472 TRACE( "(0x%x,%s,%d,%p,%ld)\n", handle
, debugstr_us(name
), info_class
, info
, length
);
474 if (name
->Length
> MAX_NAME_LENGTH
) return STATUS_BUFFER_OVERFLOW
;
476 /* compute the length we want to retrieve */
479 case KeyValueBasicInformation
:
480 fixed_size
= sizeof(KEY_VALUE_BASIC_INFORMATION
) - sizeof(WCHAR
);
483 case KeyValueFullInformation
:
484 fixed_size
= sizeof(KEY_VALUE_FULL_INFORMATION
) - sizeof(WCHAR
);
485 data_ptr
= (char *)info
+ fixed_size
;
487 case KeyValuePartialInformation
:
488 fixed_size
= sizeof(KEY_VALUE_PARTIAL_INFORMATION
) - sizeof(UCHAR
);
489 data_ptr
= (char *)info
+ fixed_size
;
492 FIXME( "Information class %d not implemented\n", info_class
);
493 return STATUS_INVALID_PARAMETER
;
495 if (data_ptr
&& length
> fixed_size
) data_len
= length
- fixed_size
;
499 size_t reqlen
= min( data_len
, REQUEST_MAX_VAR_SIZE
);
500 reqlen
= max( reqlen
, name
->Length
+ sizeof(WCHAR
) );
502 SERVER_START_VAR_REQ( get_key_value
, reqlen
)
504 WCHAR
*nameptr
= server_data_ptr(req
);
507 req
->offset
= offset
;
508 *nameptr
++ = name
->Length
;
509 memcpy( nameptr
, name
->Buffer
, name
->Length
);
511 if (!(ret
= SERVER_CALL()))
513 size_t size
= min( server_data_size(req
), data_len
);
515 total_len
= req
->len
;
518 memcpy( data_ptr
+ offset
, server_data_ptr(req
), size
);
526 } while (data_len
&& offset
< total_len
);
528 *result_len
= total_len
+ fixed_size
;
530 if (offset
< total_len
) ret
= STATUS_BUFFER_OVERFLOW
;
531 if (length
< fixed_size
) ret
= STATUS_BUFFER_OVERFLOW
;
533 copy_key_value_info( info_class
, info
, length
, type
, 0, total_len
);
538 /******************************************************************************
542 NTSTATUS WINAPI
NtFlushKey(HANDLE KeyHandle
)
544 FIXME("(0x%08x) stub!\n",
549 /******************************************************************************
553 NTSTATUS WINAPI
NtLoadKey( const OBJECT_ATTRIBUTES
*attr
, const OBJECT_ATTRIBUTES
*file
)
556 dump_ObjectAttributes(attr
);
557 dump_ObjectAttributes(file
);
558 return STATUS_SUCCESS
;
561 /******************************************************************************
562 * NtNotifyChangeKey [NTDLL]
565 NTSTATUS WINAPI
NtNotifyChangeKey(
568 IN PIO_APC_ROUTINE ApcRoutine OPTIONAL
,
569 IN PVOID ApcContext OPTIONAL
,
570 OUT PIO_STATUS_BLOCK IoStatusBlock
,
571 IN ULONG CompletionFilter
,
572 IN BOOLEAN Asynchroneous
,
573 OUT PVOID ChangeBuffer
,
575 IN BOOLEAN WatchSubtree
)
577 FIXME("(0x%08x,0x%08x,%p,%p,%p,0x%08lx, 0x%08x,%p,0x%08lx,0x%08x) stub!\n",
578 KeyHandle
, Event
, ApcRoutine
, ApcContext
, IoStatusBlock
, CompletionFilter
,
579 Asynchroneous
, ChangeBuffer
, Length
, WatchSubtree
);
580 return STATUS_SUCCESS
;
583 /******************************************************************************
584 * NtQueryMultipleValueKey [NTDLL]
585 * ZwQueryMultipleValueKey
588 NTSTATUS WINAPI
NtQueryMultipleValueKey(
590 PVALENTW ListOfValuesToQuery
,
592 PVOID MultipleValueInformation
,
596 FIXME("(0x%08x,%p,0x%08lx,%p,0x%08lx,%p) stub!\n",
597 KeyHandle
, ListOfValuesToQuery
, NumberOfItems
, MultipleValueInformation
,
598 Length
,ReturnLength
);
599 return STATUS_SUCCESS
;
602 /******************************************************************************
603 * NtReplaceKey [NTDLL]
606 NTSTATUS WINAPI
NtReplaceKey(
607 IN POBJECT_ATTRIBUTES ObjectAttributes
,
609 IN POBJECT_ATTRIBUTES ReplacedObjectAttributes
)
611 FIXME("(0x%08x),stub!\n", Key
);
612 dump_ObjectAttributes(ObjectAttributes
);
613 dump_ObjectAttributes(ReplacedObjectAttributes
);
614 return STATUS_SUCCESS
;
616 /******************************************************************************
617 * NtRestoreKey [NTDLL]
620 NTSTATUS WINAPI
NtRestoreKey(
625 FIXME("(0x%08x,0x%08x,0x%08lx) stub\n",
626 KeyHandle
, FileHandle
, RestoreFlags
);
627 return STATUS_SUCCESS
;
629 /******************************************************************************
633 NTSTATUS WINAPI
NtSaveKey(
635 IN HANDLE FileHandle
)
637 FIXME("(0x%08x,0x%08x) stub\n",
638 KeyHandle
, FileHandle
);
639 return STATUS_SUCCESS
;
641 /******************************************************************************
642 * NtSetInformationKey [NTDLL]
643 * ZwSetInformationKey
645 NTSTATUS WINAPI
NtSetInformationKey(
647 IN
const int KeyInformationClass
,
648 IN PVOID KeyInformation
,
649 IN ULONG KeyInformationLength
)
651 FIXME("(0x%08x,0x%08x,%p,0x%08lx) stub\n",
652 KeyHandle
, KeyInformationClass
, KeyInformation
, KeyInformationLength
);
653 return STATUS_SUCCESS
;
657 /******************************************************************************
658 * NtSetValueKey [NTDLL]
662 * win95 does not care about count for REG_SZ and finds out the len by itself (js)
663 * NT does definitely care (aj)
665 NTSTATUS WINAPI
NtSetValueKey( HANDLE hkey
, const UNICODE_STRING
*name
, ULONG TitleIndex
,
666 ULONG type
, const void *data
, ULONG count
)
671 TRACE( "(0x%x,%s,%ld,%p,%ld)\n", hkey
, debugstr_us(name
), type
, data
, count
);
673 if (name
->Length
> MAX_NAME_LENGTH
) return STATUS_BUFFER_OVERFLOW
;
675 namelen
= name
->Length
+ sizeof(WCHAR
); /* for storing length */
680 ULONG len
= count
- pos
;
681 if (len
> REQUEST_MAX_VAR_SIZE
- namelen
) len
= REQUEST_MAX_VAR_SIZE
- namelen
;
683 SERVER_START_VAR_REQ( set_key_value
, namelen
+ len
)
685 WCHAR
*name_ptr
= server_data_ptr(req
);
691 *name_ptr
++ = name
->Length
;
692 memcpy( name_ptr
, name
->Buffer
, name
->Length
);
693 memcpy( (char *)name_ptr
+ name
->Length
, (char *)data
+ pos
, len
);
698 } while (!ret
&& pos
< count
);
702 /******************************************************************************
703 * NtUnloadKey [NTDLL]
706 NTSTATUS WINAPI
NtUnloadKey(
709 FIXME("(0x%08x) stub\n",
711 return STATUS_SUCCESS
;
714 /******************************************************************************
715 * RtlFormatCurrentUserKeyPath [NTDLL.371]
717 NTSTATUS WINAPI
RtlFormatCurrentUserKeyPath(
718 IN OUT PUNICODE_STRING KeyPath
)
720 /* LPSTR Path = "\\REGISTRY\\USER\\S-1-5-21-0000000000-000000000-0000000000-500";*/
721 LPSTR Path
= "\\REGISTRY\\USER\\.DEFAULT";
722 ANSI_STRING AnsiPath
;
724 FIXME("(%p) stub\n",KeyPath
);
725 RtlInitAnsiString(&AnsiPath
, Path
);
726 return RtlAnsiStringToUnicodeString(KeyPath
, &AnsiPath
, TRUE
);
729 /******************************************************************************
730 * RtlOpenCurrentUser [NTDLL]
732 * if we return just HKEY_CURRENT_USER the advapi try's to find a remote
733 * registry (odd handle) and fails
736 DWORD WINAPI
RtlOpenCurrentUser(
737 IN ACCESS_MASK DesiredAccess
, /* [in] */
738 OUT PHANDLE KeyHandle
) /* [out] handle of HKEY_CURRENT_USER */
740 OBJECT_ATTRIBUTES ObjectAttributes
;
741 UNICODE_STRING ObjectName
;
744 TRACE("(0x%08lx, %p) stub\n",DesiredAccess
, KeyHandle
);
746 RtlFormatCurrentUserKeyPath(&ObjectName
);
747 InitializeObjectAttributes(&ObjectAttributes
,&ObjectName
,OBJ_CASE_INSENSITIVE
,0, NULL
);
748 ret
= NtOpenKey(KeyHandle
, DesiredAccess
, &ObjectAttributes
);
749 RtlFreeUnicodeString(&ObjectName
);