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"
19 #include "wine/server.h"
21 #include "ntdll_misc.h"
23 DEFAULT_DEBUG_CHANNEL(reg
);
25 /* maximum length of a key/value name in bytes (without terminating null) */
26 #define MAX_NAME_LENGTH ((MAX_PATH-1) * sizeof(WCHAR))
29 /******************************************************************************
30 * NtCreateKey [NTDLL.@]
31 * ZwCreateKey [NTDLL.@]
33 NTSTATUS WINAPI
NtCreateKey( PHANDLE retkey
, ACCESS_MASK access
, const OBJECT_ATTRIBUTES
*attr
,
34 ULONG TitleIndex
, const UNICODE_STRING
*class, ULONG options
,
38 DWORD len
= attr
->ObjectName
->Length
;
40 TRACE( "(0x%x,%s,%s,%lx,%lx,%p)\n", attr
->RootDirectory
, debugstr_us(attr
->ObjectName
),
41 debugstr_us(class), options
, access
, retkey
);
43 if (len
> MAX_NAME_LENGTH
) return STATUS_BUFFER_OVERFLOW
;
44 len
+= sizeof(WCHAR
); /* for storing name length */
48 if (len
> REQUEST_MAX_VAR_SIZE
) return STATUS_BUFFER_OVERFLOW
;
50 if (!retkey
) return STATUS_INVALID_PARAMETER
;
52 SERVER_START_VAR_REQ( create_key
, len
)
54 WCHAR
*data
= server_data_ptr(req
);
56 req
->parent
= attr
->RootDirectory
;
58 req
->options
= options
;
61 *data
++ = attr
->ObjectName
->Length
;
62 memcpy( data
, attr
->ObjectName
->Buffer
, attr
->ObjectName
->Length
);
63 if (class) memcpy( (char *)data
+ attr
->ObjectName
->Length
, class->Buffer
, class->Length
);
64 if (!(ret
= SERVER_CALL()))
67 if (dispos
) *dispos
= req
->created
? REG_CREATED_NEW_KEY
: REG_OPENED_EXISTING_KEY
;
71 TRACE("<- 0x%04x\n", *retkey
);
76 /******************************************************************************
80 * OUT PHANDLE retkey (returns 0 when failure)
81 * IN ACCESS_MASK access
82 * IN POBJECT_ATTRIBUTES attr
84 NTSTATUS WINAPI
NtOpenKey( PHANDLE retkey
, ACCESS_MASK access
, const OBJECT_ATTRIBUTES
*attr
)
87 DWORD len
= attr
->ObjectName
->Length
;
89 TRACE( "(0x%x,%s,%lx,%p)\n", attr
->RootDirectory
,
90 debugstr_us(attr
->ObjectName
), access
, retkey
);
92 if (len
> MAX_NAME_LENGTH
) return STATUS_BUFFER_OVERFLOW
;
93 if (!retkey
) return STATUS_INVALID_PARAMETER
;
95 SERVER_START_VAR_REQ( open_key
, len
)
97 req
->parent
= attr
->RootDirectory
;
99 memcpy( server_data_ptr(req
), attr
->ObjectName
->Buffer
, len
);
104 TRACE("<- 0x%04x\n", *retkey
);
109 /******************************************************************************
110 * NtDeleteKey [NTDLL.@]
111 * ZwDeleteKey [NTDLL.@]
113 NTSTATUS WINAPI
NtDeleteKey( HANDLE hkey
)
117 TRACE( "(%x)\n", hkey
);
119 SERVER_START_REQ( delete_key
)
129 /******************************************************************************
130 * NtDeleteValueKey [NTDLL.@]
131 * ZwDeleteValueKey [NTDLL.@]
133 NTSTATUS WINAPI
NtDeleteValueKey( HANDLE hkey
, const UNICODE_STRING
*name
)
137 TRACE( "(0x%x,%s)\n", hkey
, debugstr_us(name
) );
138 if (name
->Length
> MAX_NAME_LENGTH
) return STATUS_BUFFER_OVERFLOW
;
140 SERVER_START_VAR_REQ( delete_key_value
, name
->Length
)
143 memcpy( server_data_ptr(req
), name
->Buffer
, name
->Length
);
151 /******************************************************************************
154 * Helper function for NtQueryKey and NtEnumerateKey
156 static NTSTATUS
fill_key_info( KEY_INFORMATION_CLASS info_class
, void *info
, DWORD length
,
157 DWORD
*result_len
, const struct enum_key_request
*req
)
159 WCHAR
*name_ptr
= server_data_ptr(req
);
160 int name_size
= *name_ptr
++;
161 WCHAR
*class_ptr
= (WCHAR
*)((char *)name_ptr
+ name_size
);
162 int class_size
= server_data_size(req
) - sizeof(WCHAR
) - name_size
;
166 RtlSecondsSince1970ToTime( req
->modif
, &modif
);
170 case KeyBasicInformation
:
172 KEY_BASIC_INFORMATION keyinfo
;
173 fixed_size
= sizeof(keyinfo
) - sizeof(keyinfo
.Name
);
174 keyinfo
.LastWriteTime
= modif
;
175 keyinfo
.TitleIndex
= 0;
176 keyinfo
.NameLength
= name_size
;
177 memcpy( info
, &keyinfo
, min( length
, fixed_size
) );
181 case KeyFullInformation
:
183 KEY_FULL_INFORMATION keyinfo
;
184 fixed_size
= sizeof(keyinfo
) - sizeof(keyinfo
.Class
);
185 keyinfo
.LastWriteTime
= modif
;
186 keyinfo
.TitleIndex
= 0;
187 keyinfo
.ClassLength
= class_size
;
188 keyinfo
.ClassOffset
= keyinfo
.ClassLength
? fixed_size
: -1;
189 keyinfo
.SubKeys
= req
->subkeys
;
190 keyinfo
.MaxNameLen
= req
->max_subkey
;
191 keyinfo
.MaxClassLen
= req
->max_class
;
192 keyinfo
.Values
= req
->values
;
193 keyinfo
.MaxValueNameLen
= req
->max_value
;
194 keyinfo
.MaxValueDataLen
= req
->max_data
;
195 memcpy( info
, &keyinfo
, min( length
, fixed_size
) );
199 case KeyNodeInformation
:
201 KEY_NODE_INFORMATION keyinfo
;
202 fixed_size
= sizeof(keyinfo
) - sizeof(keyinfo
.Name
);
203 keyinfo
.LastWriteTime
= modif
;
204 keyinfo
.TitleIndex
= 0;
205 keyinfo
.ClassLength
= class_size
;
206 keyinfo
.ClassOffset
= fixed_size
+ name_size
;
207 if (!keyinfo
.ClassLength
|| keyinfo
.ClassOffset
> length
) keyinfo
.ClassOffset
= -1;
208 keyinfo
.NameLength
= name_size
;
209 memcpy( info
, &keyinfo
, min( length
, fixed_size
) );
213 FIXME("Information class not implemented\n");
214 return STATUS_INVALID_PARAMETER
;
217 *result_len
= fixed_size
+ name_size
+ class_size
;
218 if (length
<= fixed_size
) return STATUS_BUFFER_OVERFLOW
;
219 length
-= fixed_size
;
224 memcpy( (char *)info
+ fixed_size
, name_ptr
, min(length
,name_size
) );
225 if (length
< name_size
) return STATUS_BUFFER_OVERFLOW
;
232 memcpy( (char *)info
+ fixed_size
+ name_size
, class_ptr
, min(length
,class_size
) );
233 if (length
< class_size
) return STATUS_BUFFER_OVERFLOW
;
235 return STATUS_SUCCESS
;
240 /******************************************************************************
241 * NtEnumerateKey [NTDLL.@]
242 * ZwEnumerateKey [NTDLL.@]
245 * the name copied into the buffer is NOT 0-terminated
247 NTSTATUS WINAPI
NtEnumerateKey( HANDLE handle
, ULONG index
, KEY_INFORMATION_CLASS info_class
,
248 void *info
, DWORD length
, DWORD
*result_len
)
252 /* -1 means query key, so avoid it here */
253 if (index
== (ULONG
)-1) return STATUS_NO_MORE_ENTRIES
;
255 SERVER_START_VAR_REQ( enum_key
, REQUEST_MAX_VAR_SIZE
)
259 req
->full
= (info_class
== KeyFullInformation
);
260 if (!(ret
= SERVER_CALL()))
262 ret
= fill_key_info( info_class
, info
, length
, result_len
, req
);
270 /******************************************************************************
271 * NtQueryKey [NTDLL.@]
272 * ZwQueryKey [NTDLL.@]
274 NTSTATUS WINAPI
NtQueryKey( HANDLE handle
, KEY_INFORMATION_CLASS info_class
,
275 void *info
, DWORD length
, DWORD
*result_len
)
279 SERVER_START_VAR_REQ( enum_key
, REQUEST_MAX_VAR_SIZE
)
283 req
->full
= (info_class
== KeyFullInformation
);
284 if (!(ret
= SERVER_CALL()))
286 ret
= fill_key_info( info_class
, info
, length
, result_len
, req
);
294 /* fill the key value info structure for a specific info class */
295 static void copy_key_value_info( KEY_VALUE_INFORMATION_CLASS info_class
, void *info
,
296 DWORD length
, int type
, int name_len
, int data_len
)
300 case KeyValueBasicInformation
:
302 KEY_VALUE_BASIC_INFORMATION keyinfo
;
303 keyinfo
.TitleIndex
= 0;
305 keyinfo
.NameLength
= name_len
;
306 length
= min( length
, sizeof(keyinfo
) - sizeof(keyinfo
.Name
) );
307 memcpy( info
, &keyinfo
, length
);
310 case KeyValueFullInformation
:
312 KEY_VALUE_FULL_INFORMATION keyinfo
;
313 keyinfo
.TitleIndex
= 0;
315 keyinfo
.DataOffset
= sizeof(keyinfo
) - sizeof(keyinfo
.Name
) + name_len
;
316 keyinfo
.DataLength
= data_len
;
317 keyinfo
.NameLength
= name_len
;
318 length
= min( length
, sizeof(keyinfo
) - sizeof(keyinfo
.Name
) );
319 memcpy( info
, &keyinfo
, length
);
322 case KeyValuePartialInformation
:
324 KEY_VALUE_PARTIAL_INFORMATION keyinfo
;
325 keyinfo
.TitleIndex
= 0;
327 keyinfo
.DataLength
= data_len
;
328 length
= min( length
, sizeof(keyinfo
) - sizeof(keyinfo
.Data
) );
329 memcpy( info
, &keyinfo
, length
);
338 /******************************************************************************
339 * NtEnumerateValueKey [NTDLL.@]
340 * ZwEnumerateValueKey [NTDLL.@]
342 NTSTATUS WINAPI
NtEnumerateValueKey( HANDLE handle
, ULONG index
,
343 KEY_VALUE_INFORMATION_CLASS info_class
,
344 void *info
, DWORD length
, DWORD
*result_len
)
347 char *data_ptr
, *name_ptr
;
348 int fixed_size
= 0, name_len
= 0, data_len
= 0, offset
= 0, type
= 0, total_len
= 0;
350 TRACE( "(0x%x,%lu,%d,%p,%ld)\n", handle
, index
, info_class
, info
, length
);
352 /* compute the length we want to retrieve */
355 case KeyValueBasicInformation
:
356 fixed_size
= sizeof(KEY_VALUE_BASIC_INFORMATION
) - sizeof(WCHAR
);
357 name_ptr
= (char *)info
+ fixed_size
;
360 case KeyValueFullInformation
:
361 fixed_size
= sizeof(KEY_VALUE_FULL_INFORMATION
) - sizeof(WCHAR
);
362 name_ptr
= data_ptr
= (char *)info
+ fixed_size
;
364 case KeyValuePartialInformation
:
365 fixed_size
= sizeof(KEY_VALUE_PARTIAL_INFORMATION
) - sizeof(UCHAR
);
367 data_ptr
= (char *)info
+ fixed_size
;
370 FIXME( "Information class %d not implemented\n", info_class
);
371 return STATUS_INVALID_PARAMETER
;
373 if (length
> fixed_size
) data_len
= length
- fixed_size
;
377 size_t reqlen
= data_len
+ sizeof(WCHAR
);
378 if (name_ptr
&& !offset
) reqlen
+= MAX_PATH
*sizeof(WCHAR
);
379 reqlen
= min( reqlen
, REQUEST_MAX_VAR_SIZE
);
381 SERVER_START_VAR_REQ( enum_key_value
, reqlen
)
385 req
->offset
= offset
;
387 if (!(ret
= SERVER_CALL()))
389 size_t size
= server_data_size(req
) - sizeof(WCHAR
);
390 WCHAR
*name
= server_data_ptr(req
);
391 if (!offset
) /* name is only present on the first request */
397 if (name_len
> data_len
) /* overflow */
399 memcpy( name_ptr
, name
, data_len
);
401 ret
= STATUS_BUFFER_OVERFLOW
;
405 memcpy( name_ptr
, name
, name_len
);
406 data_len
-= name_len
;
407 if (data_ptr
) data_ptr
+= name_len
;
410 name
+= name_len
/ sizeof(WCHAR
);
412 else name
++; /* skip 0 length */
416 size
= min( size
, data_len
);
417 memcpy( data_ptr
+ offset
, name
, size
);
422 total_len
= req
->len
;
427 } while (data_len
&& data_ptr
&& offset
< total_len
);
429 *result_len
= total_len
+ fixed_size
+ (name_ptr
? name_len
: 0);
431 if (data_ptr
&& offset
< total_len
) ret
= STATUS_BUFFER_OVERFLOW
;
432 if (length
< fixed_size
) ret
= STATUS_BUFFER_OVERFLOW
;
434 copy_key_value_info( info_class
, info
, length
, type
, name_len
, total_len
);
440 /******************************************************************************
441 * NtQueryValueKey [NTDLL.@]
442 * ZwQueryValueKey [NTDLL.@]
445 * the name in the KeyValueInformation is never set
447 NTSTATUS WINAPI
NtQueryValueKey( HANDLE handle
, const UNICODE_STRING
*name
,
448 KEY_VALUE_INFORMATION_CLASS info_class
,
449 void *info
, DWORD length
, DWORD
*result_len
)
453 int fixed_size
= 0, data_len
= 0, offset
= 0, type
= 0, total_len
= 0;
455 TRACE( "(0x%x,%s,%d,%p,%ld)\n", handle
, debugstr_us(name
), info_class
, info
, length
);
457 if (name
->Length
> MAX_NAME_LENGTH
) return STATUS_BUFFER_OVERFLOW
;
459 /* compute the length we want to retrieve */
462 case KeyValueBasicInformation
:
463 fixed_size
= sizeof(KEY_VALUE_BASIC_INFORMATION
) - sizeof(WCHAR
);
466 case KeyValueFullInformation
:
467 fixed_size
= sizeof(KEY_VALUE_FULL_INFORMATION
) - sizeof(WCHAR
);
468 data_ptr
= (char *)info
+ fixed_size
;
470 case KeyValuePartialInformation
:
471 fixed_size
= sizeof(KEY_VALUE_PARTIAL_INFORMATION
) - sizeof(UCHAR
);
472 data_ptr
= (char *)info
+ fixed_size
;
475 FIXME( "Information class %d not implemented\n", info_class
);
476 return STATUS_INVALID_PARAMETER
;
478 if (data_ptr
&& length
> fixed_size
) data_len
= length
- fixed_size
;
482 size_t reqlen
= min( data_len
, REQUEST_MAX_VAR_SIZE
);
483 reqlen
= max( reqlen
, name
->Length
+ sizeof(WCHAR
) );
485 SERVER_START_VAR_REQ( get_key_value
, reqlen
)
487 WCHAR
*nameptr
= server_data_ptr(req
);
490 req
->offset
= offset
;
491 *nameptr
++ = name
->Length
;
492 memcpy( nameptr
, name
->Buffer
, name
->Length
);
494 if (!(ret
= SERVER_CALL()))
496 size_t size
= min( server_data_size(req
), data_len
);
498 total_len
= req
->len
;
501 memcpy( data_ptr
+ offset
, server_data_ptr(req
), size
);
509 } while (data_len
&& offset
< total_len
);
511 *result_len
= total_len
+ fixed_size
;
513 if (offset
< total_len
) ret
= STATUS_BUFFER_OVERFLOW
;
514 if (length
< fixed_size
) ret
= STATUS_BUFFER_OVERFLOW
;
516 copy_key_value_info( info_class
, info
, length
, type
, 0, total_len
);
521 /******************************************************************************
522 * NtFlushKey [NTDLL.@]
523 * ZwFlushKey [NTDLL.@]
525 NTSTATUS WINAPI
NtFlushKey(HANDLE KeyHandle
)
527 FIXME("(0x%08x) stub!\n",
532 /******************************************************************************
533 * NtLoadKey [NTDLL.@]
534 * ZwLoadKey [NTDLL.@]
536 NTSTATUS WINAPI
NtLoadKey( const OBJECT_ATTRIBUTES
*attr
, const OBJECT_ATTRIBUTES
*file
)
539 dump_ObjectAttributes(attr
);
540 dump_ObjectAttributes(file
);
541 return STATUS_SUCCESS
;
544 /******************************************************************************
545 * NtNotifyChangeKey [NTDLL.@]
546 * ZwNotifyChangeKey [NTDLL.@]
548 NTSTATUS WINAPI
NtNotifyChangeKey(
551 IN PIO_APC_ROUTINE ApcRoutine OPTIONAL
,
552 IN PVOID ApcContext OPTIONAL
,
553 OUT PIO_STATUS_BLOCK IoStatusBlock
,
554 IN ULONG CompletionFilter
,
555 IN BOOLEAN Asynchroneous
,
556 OUT PVOID ChangeBuffer
,
558 IN BOOLEAN WatchSubtree
)
560 FIXME("(0x%08x,0x%08x,%p,%p,%p,0x%08lx, 0x%08x,%p,0x%08lx,0x%08x) stub!\n",
561 KeyHandle
, Event
, ApcRoutine
, ApcContext
, IoStatusBlock
, CompletionFilter
,
562 Asynchroneous
, ChangeBuffer
, Length
, WatchSubtree
);
563 return STATUS_SUCCESS
;
566 /******************************************************************************
567 * NtQueryMultipleValueKey [NTDLL]
568 * ZwQueryMultipleValueKey
571 NTSTATUS WINAPI
NtQueryMultipleValueKey(
573 PVALENTW ListOfValuesToQuery
,
575 PVOID MultipleValueInformation
,
579 FIXME("(0x%08x,%p,0x%08lx,%p,0x%08lx,%p) stub!\n",
580 KeyHandle
, ListOfValuesToQuery
, NumberOfItems
, MultipleValueInformation
,
581 Length
,ReturnLength
);
582 return STATUS_SUCCESS
;
585 /******************************************************************************
586 * NtReplaceKey [NTDLL.@]
587 * ZwReplaceKey [NTDLL.@]
589 NTSTATUS WINAPI
NtReplaceKey(
590 IN POBJECT_ATTRIBUTES ObjectAttributes
,
592 IN POBJECT_ATTRIBUTES ReplacedObjectAttributes
)
594 FIXME("(0x%08x),stub!\n", Key
);
595 dump_ObjectAttributes(ObjectAttributes
);
596 dump_ObjectAttributes(ReplacedObjectAttributes
);
597 return STATUS_SUCCESS
;
599 /******************************************************************************
600 * NtRestoreKey [NTDLL.@]
601 * ZwRestoreKey [NTDLL.@]
603 NTSTATUS WINAPI
NtRestoreKey(
608 FIXME("(0x%08x,0x%08x,0x%08lx) stub\n",
609 KeyHandle
, FileHandle
, RestoreFlags
);
610 return STATUS_SUCCESS
;
612 /******************************************************************************
613 * NtSaveKey [NTDLL.@]
614 * ZwSaveKey [NTDLL.@]
616 NTSTATUS WINAPI
NtSaveKey(
618 IN HANDLE FileHandle
)
620 FIXME("(0x%08x,0x%08x) stub\n",
621 KeyHandle
, FileHandle
);
622 return STATUS_SUCCESS
;
624 /******************************************************************************
625 * NtSetInformationKey [NTDLL.@]
626 * ZwSetInformationKey [NTDLL.@]
628 NTSTATUS WINAPI
NtSetInformationKey(
630 IN
const int KeyInformationClass
,
631 IN PVOID KeyInformation
,
632 IN ULONG KeyInformationLength
)
634 FIXME("(0x%08x,0x%08x,%p,0x%08lx) stub\n",
635 KeyHandle
, KeyInformationClass
, KeyInformation
, KeyInformationLength
);
636 return STATUS_SUCCESS
;
640 /******************************************************************************
641 * NtSetValueKey [NTDLL.@]
642 * ZwSetValueKey [NTDLL.@]
645 * win95 does not care about count for REG_SZ and finds out the len by itself (js)
646 * NT does definitely care (aj)
648 NTSTATUS WINAPI
NtSetValueKey( HANDLE hkey
, const UNICODE_STRING
*name
, ULONG TitleIndex
,
649 ULONG type
, const void *data
, ULONG count
)
654 TRACE( "(0x%x,%s,%ld,%p,%ld)\n", hkey
, debugstr_us(name
), type
, data
, count
);
656 if (name
->Length
> MAX_NAME_LENGTH
) return STATUS_BUFFER_OVERFLOW
;
658 namelen
= name
->Length
+ sizeof(WCHAR
); /* for storing length */
663 ULONG len
= count
- pos
;
664 if (len
> REQUEST_MAX_VAR_SIZE
- namelen
) len
= REQUEST_MAX_VAR_SIZE
- namelen
;
666 SERVER_START_VAR_REQ( set_key_value
, namelen
+ len
)
668 WCHAR
*name_ptr
= server_data_ptr(req
);
674 *name_ptr
++ = name
->Length
;
675 memcpy( name_ptr
, name
->Buffer
, name
->Length
);
676 memcpy( (char *)name_ptr
+ name
->Length
, (char *)data
+ pos
, len
);
681 } while (!ret
&& pos
< count
);
685 /******************************************************************************
686 * NtUnloadKey [NTDLL.@]
687 * ZwUnloadKey [NTDLL.@]
689 NTSTATUS WINAPI
NtUnloadKey(
692 FIXME("(0x%08x) stub\n",
694 return STATUS_SUCCESS
;
697 /******************************************************************************
698 * RtlFormatCurrentUserKeyPath [NTDLL.@]
700 NTSTATUS WINAPI
RtlFormatCurrentUserKeyPath(
701 IN OUT PUNICODE_STRING KeyPath
)
703 /* LPSTR Path = "\\REGISTRY\\USER\\S-1-5-21-0000000000-000000000-0000000000-500";*/
704 LPSTR Path
= "\\REGISTRY\\USER\\.DEFAULT";
705 ANSI_STRING AnsiPath
;
707 FIXME("(%p) stub\n",KeyPath
);
708 RtlInitAnsiString(&AnsiPath
, Path
);
709 return RtlAnsiStringToUnicodeString(KeyPath
, &AnsiPath
, TRUE
);
712 /******************************************************************************
713 * RtlOpenCurrentUser [NTDLL.@]
715 * if we return just HKEY_CURRENT_USER the advapi try's to find a remote
716 * registry (odd handle) and fails
719 DWORD WINAPI
RtlOpenCurrentUser(
720 IN ACCESS_MASK DesiredAccess
, /* [in] */
721 OUT PHANDLE KeyHandle
) /* [out] handle of HKEY_CURRENT_USER */
723 OBJECT_ATTRIBUTES ObjectAttributes
;
724 UNICODE_STRING ObjectName
;
727 TRACE("(0x%08lx, %p) stub\n",DesiredAccess
, KeyHandle
);
729 RtlFormatCurrentUserKeyPath(&ObjectName
);
730 InitializeObjectAttributes(&ObjectAttributes
,&ObjectName
,OBJ_CASE_INSENSITIVE
,0, NULL
);
731 ret
= NtOpenKey(KeyHandle
, DesiredAccess
, &ObjectAttributes
);
732 RtlFreeUnicodeString(&ObjectName
);