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 /* maximum length of a key/value name in bytes (without terminating null) */
26 #define MAX_NAME_LENGTH ((MAX_PATH-1) * sizeof(WCHAR))
29 /******************************************************************************
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 /******************************************************************************
77 * NtOpenKey [NTDLL.129]
79 * OUT PHANDLE retkey (returns 0 when failure)
80 * IN ACCESS_MASK access
81 * IN POBJECT_ATTRIBUTES attr
83 NTSTATUS WINAPI
NtOpenKey( PHANDLE retkey
, ACCESS_MASK access
, const OBJECT_ATTRIBUTES
*attr
)
86 DWORD len
= attr
->ObjectName
->Length
;
88 TRACE( "(0x%x,%s,%lx,%p)\n", attr
->RootDirectory
,
89 debugstr_us(attr
->ObjectName
), access
, retkey
);
91 if (len
> MAX_NAME_LENGTH
) return STATUS_BUFFER_OVERFLOW
;
92 if (!retkey
) return STATUS_INVALID_PARAMETER
;
94 SERVER_START_VAR_REQ( open_key
, len
)
96 req
->parent
= attr
->RootDirectory
;
98 memcpy( server_data_ptr(req
), attr
->ObjectName
->Buffer
, len
);
103 TRACE("<- 0x%04x\n", *retkey
);
108 /******************************************************************************
109 * NtDeleteKey [NTDLL]
112 NTSTATUS WINAPI
NtDeleteKey( HANDLE hkey
)
116 TRACE( "(%x)\n", hkey
);
118 SERVER_START_REQ( delete_key
)
128 /******************************************************************************
129 * NtDeleteValueKey [NTDLL]
132 NTSTATUS WINAPI
NtDeleteValueKey( HANDLE hkey
, const UNICODE_STRING
*name
)
136 TRACE( "(0x%x,%s)\n", hkey
, debugstr_us(name
) );
137 if (name
->Length
> MAX_NAME_LENGTH
) return STATUS_BUFFER_OVERFLOW
;
139 SERVER_START_VAR_REQ( delete_key_value
, name
->Length
)
142 memcpy( server_data_ptr(req
), name
->Buffer
, name
->Length
);
150 /******************************************************************************
153 * Helper function for NtQueryKey and NtEnumerateKey
155 static NTSTATUS
fill_key_info( KEY_INFORMATION_CLASS info_class
, void *info
, DWORD length
,
156 DWORD
*result_len
, const struct enum_key_request
*req
)
158 WCHAR
*name_ptr
= server_data_ptr(req
);
159 int name_size
= *name_ptr
++;
160 WCHAR
*class_ptr
= (WCHAR
*)((char *)name_ptr
+ name_size
);
161 int class_size
= server_data_size(req
) - sizeof(WCHAR
) - name_size
;
165 RtlSecondsSince1970ToTime( req
->modif
, &modif
);
169 case KeyBasicInformation
:
171 KEY_BASIC_INFORMATION keyinfo
;
172 fixed_size
= sizeof(keyinfo
) - sizeof(keyinfo
.Name
);
173 keyinfo
.LastWriteTime
= modif
;
174 keyinfo
.TitleIndex
= 0;
175 keyinfo
.NameLength
= name_size
;
176 memcpy( info
, &keyinfo
, min( length
, fixed_size
) );
180 case KeyFullInformation
:
182 KEY_FULL_INFORMATION keyinfo
;
183 fixed_size
= sizeof(keyinfo
) - sizeof(keyinfo
.Class
);
184 keyinfo
.LastWriteTime
= modif
;
185 keyinfo
.TitleIndex
= 0;
186 keyinfo
.ClassLength
= class_size
;
187 keyinfo
.ClassOffset
= keyinfo
.ClassLength
? fixed_size
: -1;
188 keyinfo
.SubKeys
= req
->subkeys
;
189 keyinfo
.MaxNameLen
= req
->max_subkey
;
190 keyinfo
.MaxClassLen
= req
->max_class
;
191 keyinfo
.Values
= req
->values
;
192 keyinfo
.MaxValueNameLen
= req
->max_value
;
193 keyinfo
.MaxValueDataLen
= req
->max_data
;
194 memcpy( info
, &keyinfo
, min( length
, fixed_size
) );
198 case KeyNodeInformation
:
200 KEY_NODE_INFORMATION keyinfo
;
201 fixed_size
= sizeof(keyinfo
) - sizeof(keyinfo
.Name
);
202 keyinfo
.LastWriteTime
= modif
;
203 keyinfo
.TitleIndex
= 0;
204 keyinfo
.ClassLength
= class_size
;
205 keyinfo
.ClassOffset
= fixed_size
+ name_size
;
206 if (!keyinfo
.ClassLength
|| keyinfo
.ClassOffset
> length
) keyinfo
.ClassOffset
= -1;
207 keyinfo
.NameLength
= name_size
;
208 memcpy( info
, &keyinfo
, min( length
, fixed_size
) );
212 FIXME("Information class not implemented\n");
213 return STATUS_INVALID_PARAMETER
;
216 *result_len
= fixed_size
+ name_size
+ class_size
;
217 if (length
<= fixed_size
) return STATUS_BUFFER_OVERFLOW
;
218 length
-= fixed_size
;
223 memcpy( (char *)info
+ fixed_size
, name_ptr
, min(length
,name_size
) );
224 if (length
< name_size
) return STATUS_BUFFER_OVERFLOW
;
231 memcpy( (char *)info
+ fixed_size
+ name_size
, class_ptr
, min(length
,class_size
) );
232 if (length
< class_size
) return STATUS_BUFFER_OVERFLOW
;
234 return STATUS_SUCCESS
;
239 /******************************************************************************
240 * NtEnumerateKey [NTDLL]
244 * the name copied into the buffer is NOT 0-terminated
246 NTSTATUS WINAPI
NtEnumerateKey( HANDLE handle
, ULONG index
, KEY_INFORMATION_CLASS info_class
,
247 void *info
, DWORD length
, DWORD
*result_len
)
251 /* -1 means query key, so avoid it here */
252 if (index
== (ULONG
)-1) return STATUS_NO_MORE_ENTRIES
;
254 SERVER_START_VAR_REQ( enum_key
, REQUEST_MAX_VAR_SIZE
)
258 req
->full
= (info_class
== KeyFullInformation
);
259 if (!(ret
= SERVER_CALL()))
261 ret
= fill_key_info( info_class
, info
, length
, result_len
, req
);
269 /******************************************************************************
273 NTSTATUS WINAPI
NtQueryKey( HANDLE handle
, KEY_INFORMATION_CLASS info_class
,
274 void *info
, DWORD length
, DWORD
*result_len
)
278 SERVER_START_VAR_REQ( enum_key
, REQUEST_MAX_VAR_SIZE
)
282 req
->full
= (info_class
== KeyFullInformation
);
283 if (!(ret
= SERVER_CALL()))
285 ret
= fill_key_info( info_class
, info
, length
, result_len
, req
);
293 /* fill the key value info structure for a specific info class */
294 static void copy_key_value_info( KEY_VALUE_INFORMATION_CLASS info_class
, void *info
,
295 DWORD length
, int type
, int name_len
, int data_len
)
299 case KeyValueBasicInformation
:
301 KEY_VALUE_BASIC_INFORMATION keyinfo
;
302 keyinfo
.TitleIndex
= 0;
304 keyinfo
.NameLength
= name_len
;
305 length
= min( length
, sizeof(keyinfo
) - sizeof(keyinfo
.Name
) );
306 memcpy( info
, &keyinfo
, length
);
309 case KeyValueFullInformation
:
311 KEY_VALUE_FULL_INFORMATION keyinfo
;
312 keyinfo
.TitleIndex
= 0;
314 keyinfo
.DataOffset
= sizeof(keyinfo
) - sizeof(keyinfo
.Name
) + name_len
;
315 keyinfo
.DataLength
= data_len
;
316 keyinfo
.NameLength
= name_len
;
317 length
= min( length
, sizeof(keyinfo
) - sizeof(keyinfo
.Name
) );
318 memcpy( info
, &keyinfo
, length
);
321 case KeyValuePartialInformation
:
323 KEY_VALUE_PARTIAL_INFORMATION keyinfo
;
324 keyinfo
.TitleIndex
= 0;
326 keyinfo
.DataLength
= data_len
;
327 length
= min( length
, sizeof(keyinfo
) - sizeof(keyinfo
.Data
) );
328 memcpy( info
, &keyinfo
, length
);
337 /******************************************************************************
338 * NtEnumerateValueKey [NTDLL]
339 * ZwEnumerateValueKey
341 NTSTATUS WINAPI
NtEnumerateValueKey( HANDLE handle
, ULONG index
,
342 KEY_VALUE_INFORMATION_CLASS info_class
,
343 void *info
, DWORD length
, DWORD
*result_len
)
346 char *data_ptr
, *name_ptr
;
347 int fixed_size
= 0, name_len
= 0, data_len
= 0, offset
= 0, type
= 0, total_len
= 0;
349 TRACE( "(0x%x,%lu,%d,%p,%ld)\n", handle
, index
, info_class
, info
, length
);
351 /* compute the length we want to retrieve */
354 case KeyValueBasicInformation
:
355 fixed_size
= sizeof(KEY_VALUE_BASIC_INFORMATION
) - sizeof(WCHAR
);
356 name_ptr
= (char *)info
+ fixed_size
;
359 case KeyValueFullInformation
:
360 fixed_size
= sizeof(KEY_VALUE_FULL_INFORMATION
) - sizeof(WCHAR
);
361 name_ptr
= data_ptr
= (char *)info
+ fixed_size
;
363 case KeyValuePartialInformation
:
364 fixed_size
= sizeof(KEY_VALUE_PARTIAL_INFORMATION
) - sizeof(UCHAR
);
366 data_ptr
= (char *)info
+ fixed_size
;
369 FIXME( "Information class %d not implemented\n", info_class
);
370 return STATUS_INVALID_PARAMETER
;
372 if (length
> fixed_size
) data_len
= length
- fixed_size
;
376 size_t reqlen
= data_len
+ sizeof(WCHAR
);
377 if (name_ptr
&& !offset
) reqlen
+= MAX_PATH
*sizeof(WCHAR
);
378 reqlen
= min( reqlen
, REQUEST_MAX_VAR_SIZE
);
380 SERVER_START_VAR_REQ( enum_key_value
, reqlen
)
384 req
->offset
= offset
;
386 if (!(ret
= SERVER_CALL()))
388 size_t size
= server_data_size(req
) - sizeof(WCHAR
);
389 WCHAR
*name
= server_data_ptr(req
);
390 if (!offset
) /* name is only present on the first request */
396 if (name_len
> data_len
) /* overflow */
398 memcpy( name_ptr
, name
, data_len
);
400 ret
= STATUS_BUFFER_OVERFLOW
;
404 memcpy( name_ptr
, name
, name_len
);
405 data_len
-= name_len
;
406 if (data_ptr
) data_ptr
+= name_len
;
409 name
+= name_len
/ sizeof(WCHAR
);
411 else name
++; /* skip 0 length */
415 size
= min( size
, data_len
);
416 memcpy( data_ptr
+ offset
, name
, size
);
421 total_len
= req
->len
;
426 } while (data_len
&& data_ptr
&& offset
< total_len
);
428 *result_len
= total_len
+ fixed_size
+ (name_ptr
? name_len
: 0);
430 if (data_ptr
&& offset
< total_len
) ret
= STATUS_BUFFER_OVERFLOW
;
431 if (length
< fixed_size
) ret
= STATUS_BUFFER_OVERFLOW
;
433 copy_key_value_info( info_class
, info
, length
, type
, name_len
, total_len
);
439 /******************************************************************************
440 * NtQueryValueKey [NTDLL]
444 * the name in the KeyValueInformation is never set
446 NTSTATUS WINAPI
NtQueryValueKey( HANDLE handle
, const UNICODE_STRING
*name
,
447 KEY_VALUE_INFORMATION_CLASS info_class
,
448 void *info
, DWORD length
, DWORD
*result_len
)
452 int fixed_size
= 0, data_len
= 0, offset
= 0, type
= 0, total_len
= 0;
454 TRACE( "(0x%x,%s,%d,%p,%ld)\n", handle
, debugstr_us(name
), info_class
, info
, length
);
456 if (name
->Length
> MAX_NAME_LENGTH
) return STATUS_BUFFER_OVERFLOW
;
458 /* compute the length we want to retrieve */
461 case KeyValueBasicInformation
:
462 fixed_size
= sizeof(KEY_VALUE_BASIC_INFORMATION
) - sizeof(WCHAR
);
465 case KeyValueFullInformation
:
466 fixed_size
= sizeof(KEY_VALUE_FULL_INFORMATION
) - sizeof(WCHAR
);
467 data_ptr
= (char *)info
+ fixed_size
;
469 case KeyValuePartialInformation
:
470 fixed_size
= sizeof(KEY_VALUE_PARTIAL_INFORMATION
) - sizeof(UCHAR
);
471 data_ptr
= (char *)info
+ fixed_size
;
474 FIXME( "Information class %d not implemented\n", info_class
);
475 return STATUS_INVALID_PARAMETER
;
477 if (data_ptr
&& length
> fixed_size
) data_len
= length
- fixed_size
;
481 size_t reqlen
= min( data_len
, REQUEST_MAX_VAR_SIZE
);
482 reqlen
= max( reqlen
, name
->Length
+ sizeof(WCHAR
) );
484 SERVER_START_VAR_REQ( get_key_value
, reqlen
)
486 WCHAR
*nameptr
= server_data_ptr(req
);
489 req
->offset
= offset
;
490 *nameptr
++ = name
->Length
;
491 memcpy( nameptr
, name
->Buffer
, name
->Length
);
493 if (!(ret
= SERVER_CALL()))
495 size_t size
= min( server_data_size(req
), data_len
);
497 total_len
= req
->len
;
500 memcpy( data_ptr
+ offset
, server_data_ptr(req
), size
);
508 } while (data_len
&& offset
< total_len
);
510 *result_len
= total_len
+ fixed_size
;
512 if (offset
< total_len
) ret
= STATUS_BUFFER_OVERFLOW
;
513 if (length
< fixed_size
) ret
= STATUS_BUFFER_OVERFLOW
;
515 copy_key_value_info( info_class
, info
, length
, type
, 0, total_len
);
520 /******************************************************************************
524 NTSTATUS WINAPI
NtFlushKey(HANDLE KeyHandle
)
526 FIXME("(0x%08x) stub!\n",
531 /******************************************************************************
535 NTSTATUS WINAPI
NtLoadKey( const OBJECT_ATTRIBUTES
*attr
, const OBJECT_ATTRIBUTES
*file
)
538 dump_ObjectAttributes(attr
);
539 dump_ObjectAttributes(file
);
540 return STATUS_SUCCESS
;
543 /******************************************************************************
544 * NtNotifyChangeKey [NTDLL]
547 NTSTATUS WINAPI
NtNotifyChangeKey(
550 IN PIO_APC_ROUTINE ApcRoutine OPTIONAL
,
551 IN PVOID ApcContext OPTIONAL
,
552 OUT PIO_STATUS_BLOCK IoStatusBlock
,
553 IN ULONG CompletionFilter
,
554 IN BOOLEAN Asynchroneous
,
555 OUT PVOID ChangeBuffer
,
557 IN BOOLEAN WatchSubtree
)
559 FIXME("(0x%08x,0x%08x,%p,%p,%p,0x%08lx, 0x%08x,%p,0x%08lx,0x%08x) stub!\n",
560 KeyHandle
, Event
, ApcRoutine
, ApcContext
, IoStatusBlock
, CompletionFilter
,
561 Asynchroneous
, ChangeBuffer
, Length
, WatchSubtree
);
562 return STATUS_SUCCESS
;
565 /******************************************************************************
566 * NtQueryMultipleValueKey [NTDLL]
567 * ZwQueryMultipleValueKey
570 NTSTATUS WINAPI
NtQueryMultipleValueKey(
572 PVALENTW ListOfValuesToQuery
,
574 PVOID MultipleValueInformation
,
578 FIXME("(0x%08x,%p,0x%08lx,%p,0x%08lx,%p) stub!\n",
579 KeyHandle
, ListOfValuesToQuery
, NumberOfItems
, MultipleValueInformation
,
580 Length
,ReturnLength
);
581 return STATUS_SUCCESS
;
584 /******************************************************************************
585 * NtReplaceKey [NTDLL]
588 NTSTATUS WINAPI
NtReplaceKey(
589 IN POBJECT_ATTRIBUTES ObjectAttributes
,
591 IN POBJECT_ATTRIBUTES ReplacedObjectAttributes
)
593 FIXME("(0x%08x),stub!\n", Key
);
594 dump_ObjectAttributes(ObjectAttributes
);
595 dump_ObjectAttributes(ReplacedObjectAttributes
);
596 return STATUS_SUCCESS
;
598 /******************************************************************************
599 * NtRestoreKey [NTDLL]
602 NTSTATUS WINAPI
NtRestoreKey(
607 FIXME("(0x%08x,0x%08x,0x%08lx) stub\n",
608 KeyHandle
, FileHandle
, RestoreFlags
);
609 return STATUS_SUCCESS
;
611 /******************************************************************************
615 NTSTATUS WINAPI
NtSaveKey(
617 IN HANDLE FileHandle
)
619 FIXME("(0x%08x,0x%08x) stub\n",
620 KeyHandle
, FileHandle
);
621 return STATUS_SUCCESS
;
623 /******************************************************************************
624 * NtSetInformationKey [NTDLL]
625 * ZwSetInformationKey
627 NTSTATUS WINAPI
NtSetInformationKey(
629 IN
const int KeyInformationClass
,
630 IN PVOID KeyInformation
,
631 IN ULONG KeyInformationLength
)
633 FIXME("(0x%08x,0x%08x,%p,0x%08lx) stub\n",
634 KeyHandle
, KeyInformationClass
, KeyInformation
, KeyInformationLength
);
635 return STATUS_SUCCESS
;
639 /******************************************************************************
640 * NtSetValueKey [NTDLL]
644 * win95 does not care about count for REG_SZ and finds out the len by itself (js)
645 * NT does definitely care (aj)
647 NTSTATUS WINAPI
NtSetValueKey( HANDLE hkey
, const UNICODE_STRING
*name
, ULONG TitleIndex
,
648 ULONG type
, const void *data
, ULONG count
)
653 TRACE( "(0x%x,%s,%ld,%p,%ld)\n", hkey
, debugstr_us(name
), type
, data
, count
);
655 if (name
->Length
> MAX_NAME_LENGTH
) return STATUS_BUFFER_OVERFLOW
;
657 namelen
= name
->Length
+ sizeof(WCHAR
); /* for storing length */
662 ULONG len
= count
- pos
;
663 if (len
> REQUEST_MAX_VAR_SIZE
- namelen
) len
= REQUEST_MAX_VAR_SIZE
- namelen
;
665 SERVER_START_VAR_REQ( set_key_value
, namelen
+ len
)
667 WCHAR
*name_ptr
= server_data_ptr(req
);
673 *name_ptr
++ = name
->Length
;
674 memcpy( name_ptr
, name
->Buffer
, name
->Length
);
675 memcpy( (char *)name_ptr
+ name
->Length
, (char *)data
+ pos
, len
);
680 } while (!ret
&& pos
< count
);
684 /******************************************************************************
685 * NtUnloadKey [NTDLL]
688 NTSTATUS WINAPI
NtUnloadKey(
691 FIXME("(0x%08x) stub\n",
693 return STATUS_SUCCESS
;
696 /******************************************************************************
697 * RtlFormatCurrentUserKeyPath [NTDLL.371]
699 NTSTATUS WINAPI
RtlFormatCurrentUserKeyPath(
700 IN OUT PUNICODE_STRING KeyPath
)
702 /* LPSTR Path = "\\REGISTRY\\USER\\S-1-5-21-0000000000-000000000-0000000000-500";*/
703 LPSTR Path
= "\\REGISTRY\\USER\\.DEFAULT";
704 ANSI_STRING AnsiPath
;
706 FIXME("(%p) stub\n",KeyPath
);
707 RtlInitAnsiString(&AnsiPath
, Path
);
708 return RtlAnsiStringToUnicodeString(KeyPath
, &AnsiPath
, TRUE
);
711 /******************************************************************************
712 * RtlOpenCurrentUser [NTDLL]
714 * if we return just HKEY_CURRENT_USER the advapi try's to find a remote
715 * registry (odd handle) and fails
718 DWORD WINAPI
RtlOpenCurrentUser(
719 IN ACCESS_MASK DesiredAccess
, /* [in] */
720 OUT PHANDLE KeyHandle
) /* [out] handle of HKEY_CURRENT_USER */
722 OBJECT_ATTRIBUTES ObjectAttributes
;
723 UNICODE_STRING ObjectName
;
726 TRACE("(0x%08lx, %p) stub\n",DesiredAccess
, KeyHandle
);
728 RtlFormatCurrentUserKeyPath(&ObjectName
);
729 InitializeObjectAttributes(&ObjectAttributes
,&ObjectName
,OBJ_CASE_INSENSITIVE
,0, NULL
);
730 ret
= NtOpenKey(KeyHandle
, DesiredAccess
, &ObjectAttributes
);
731 RtlFreeUnicodeString(&ObjectName
);