4 * Copyright (C) 1999 Juergen Schmied
5 * Copyright (C) 2000 Alexandre Julliard
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 * HKEY_LOCAL_MACHINE \\REGISTRY\\MACHINE
23 * HKEY_USERS \\REGISTRY\\USER
24 * HKEY_CURRENT_CONFIG \\REGISTRY\\MACHINE\\SYSTEM\\CURRENTCONTROLSET\\HARDWARE PROFILES\\CURRENT
25 * HKEY_CLASSES \\REGISTRY\\MACHINE\\SOFTWARE\\CLASSES
29 #include "wine/port.h"
36 #include "wine/library.h"
38 #include "ntdll_misc.h"
39 #include "wine/debug.h"
41 WINE_DEFAULT_DEBUG_CHANNEL(reg);
43 /* maximum length of a key/value name in bytes (without terminating null) */
44 #define MAX_NAME_LENGTH ((MAX_PATH-1) * sizeof(WCHAR))
47 /******************************************************************************
48 * NtCreateKey [NTDLL.@]
49 * ZwCreateKey [NTDLL.@]
51 NTSTATUS WINAPI NtCreateKey( PHKEY retkey, ACCESS_MASK access, const OBJECT_ATTRIBUTES *attr,
52 ULONG TitleIndex, const UNICODE_STRING *class, ULONG options,
57 TRACE( "(%p,%s,%s,%lx,%lx,%p)\n", attr->RootDirectory, debugstr_us(attr->ObjectName),
58 debugstr_us(class), options, access, retkey );
60 if (attr->ObjectName->Length > MAX_NAME_LENGTH) return STATUS_BUFFER_OVERFLOW;
61 if (!retkey) return STATUS_INVALID_PARAMETER;
63 SERVER_START_REQ( create_key )
65 req->parent = attr->RootDirectory;
67 req->options = options;
69 req->namelen = attr->ObjectName->Length;
70 wine_server_add_data( req, attr->ObjectName->Buffer, attr->ObjectName->Length );
71 if (class) wine_server_add_data( req, class->Buffer, class->Length );
72 if (!(ret = wine_server_call( req )))
74 *retkey = reply->hkey;
75 if (dispos) *dispos = reply->created ? REG_CREATED_NEW_KEY : REG_OPENED_EXISTING_KEY;
79 TRACE("<- %p\n", *retkey);
83 /******************************************************************************
84 * RtlpNtCreateKey [NTDLL.@]
88 NTSTATUS WINAPI RtlpNtCreateKey( PHKEY retkey, ACCESS_MASK access, OBJECT_ATTRIBUTES *attr,
89 ULONG TitleIndex, const UNICODE_STRING *class, ULONG options,
93 attr->Attributes &= ~(OBJ_PERMANENT|OBJ_EXCLUSIVE);
95 return NtCreateKey(retkey, access, attr, 0, NULL, 0, dispos);
98 /******************************************************************************
100 * ZwOpenKey [NTDLL.@]
102 * OUT PHKEY retkey (returns 0 when failure)
103 * IN ACCESS_MASK access
104 * IN POBJECT_ATTRIBUTES attr
106 NTSTATUS WINAPI NtOpenKey( PHKEY retkey, ACCESS_MASK access, const OBJECT_ATTRIBUTES *attr )
109 DWORD len = attr->ObjectName->Length;
111 TRACE( "(%p,%s,%lx,%p)\n", attr->RootDirectory,
112 debugstr_us(attr->ObjectName), access, retkey );
114 if (len > MAX_NAME_LENGTH) return STATUS_BUFFER_OVERFLOW;
115 if (!retkey) return STATUS_INVALID_PARAMETER;
117 SERVER_START_REQ( open_key )
119 req->parent = attr->RootDirectory;
120 req->access = access;
121 wine_server_add_data( req, attr->ObjectName->Buffer, len );
122 ret = wine_server_call( req );
123 *retkey = reply->hkey;
126 TRACE("<- %p\n", *retkey);
130 /******************************************************************************
131 * RtlpNtOpenKey [NTDLL.@]
135 NTSTATUS WINAPI RtlpNtOpenKey( PHKEY retkey, ACCESS_MASK access, OBJECT_ATTRIBUTES *attr )
138 attr->Attributes &= ~(OBJ_PERMANENT|OBJ_EXCLUSIVE);
139 return NtOpenKey(retkey, access, attr);
142 /******************************************************************************
143 * NtDeleteKey [NTDLL.@]
144 * ZwDeleteKey [NTDLL.@]
146 NTSTATUS WINAPI NtDeleteKey( HKEY hkey )
150 TRACE( "(%p)\n", hkey );
152 SERVER_START_REQ( delete_key )
155 ret = wine_server_call( req );
161 /******************************************************************************
162 * RtlpNtMakeTemporaryKey [NTDLL.@]
166 NTSTATUS WINAPI RtlpNtMakeTemporaryKey( HKEY hkey )
168 return NtDeleteKey(hkey);
171 /******************************************************************************
172 * NtDeleteValueKey [NTDLL.@]
173 * ZwDeleteValueKey [NTDLL.@]
175 NTSTATUS WINAPI NtDeleteValueKey( HKEY hkey, const UNICODE_STRING *name )
179 TRACE( "(%p,%s)\n", hkey, debugstr_us(name) );
180 if (name->Length > MAX_NAME_LENGTH) return STATUS_BUFFER_OVERFLOW;
182 SERVER_START_REQ( delete_key_value )
185 wine_server_add_data( req, name->Buffer, name->Length );
186 ret = wine_server_call( req );
193 /******************************************************************************
196 * Implementation of NtQueryKey and NtEnumerateKey
198 static NTSTATUS enumerate_key( HKEY handle, int index, KEY_INFORMATION_CLASS info_class,
199 void *info, DWORD length, DWORD *result_len )
208 case KeyBasicInformation: data_ptr = ((KEY_BASIC_INFORMATION *)info)->Name; break;
209 case KeyFullInformation: data_ptr = ((KEY_FULL_INFORMATION *)info)->Class; break;
210 case KeyNodeInformation: data_ptr = ((KEY_NODE_INFORMATION *)info)->Name; break;
212 FIXME( "Information class %d not implemented\n", info_class );
213 return STATUS_INVALID_PARAMETER;
215 fixed_size = (char *)data_ptr - (char *)info;
217 SERVER_START_REQ( enum_key )
221 req->info_class = info_class;
222 if (length > fixed_size) wine_server_set_reply( req, data_ptr, length - fixed_size );
223 if (!(ret = wine_server_call( req )))
227 RtlSecondsSince1970ToTime( reply->modif, &modif );
231 case KeyBasicInformation:
233 KEY_BASIC_INFORMATION keyinfo;
234 fixed_size = (char *)keyinfo.Name - (char *)&keyinfo;
235 keyinfo.LastWriteTime = modif;
236 keyinfo.TitleIndex = 0;
237 keyinfo.NameLength = reply->namelen;
238 memcpy( info, &keyinfo, min( length, fixed_size ) );
241 case KeyFullInformation:
243 KEY_FULL_INFORMATION keyinfo;
244 fixed_size = (char *)keyinfo.Class - (char *)&keyinfo;
245 keyinfo.LastWriteTime = modif;
246 keyinfo.TitleIndex = 0;
247 keyinfo.ClassLength = wine_server_reply_size(reply);
248 keyinfo.ClassOffset = keyinfo.ClassLength ? fixed_size : -1;
249 keyinfo.SubKeys = reply->subkeys;
250 keyinfo.MaxNameLen = reply->max_subkey;
251 keyinfo.MaxClassLen = reply->max_class;
252 keyinfo.Values = reply->values;
253 keyinfo.MaxValueNameLen = reply->max_value;
254 keyinfo.MaxValueDataLen = reply->max_data;
255 memcpy( info, &keyinfo, min( length, fixed_size ) );
258 case KeyNodeInformation:
260 KEY_NODE_INFORMATION keyinfo;
261 fixed_size = (char *)keyinfo.Name - (char *)&keyinfo;
262 keyinfo.LastWriteTime = modif;
263 keyinfo.TitleIndex = 0;
264 keyinfo.ClassLength = max( 0, wine_server_reply_size(reply) - reply->namelen );
265 keyinfo.ClassOffset = keyinfo.ClassLength ? fixed_size + reply->namelen : -1;
266 keyinfo.NameLength = reply->namelen;
267 memcpy( info, &keyinfo, min( length, fixed_size ) );
271 *result_len = fixed_size + reply->total;
272 if (length < *result_len) ret = STATUS_BUFFER_OVERFLOW;
281 /******************************************************************************
282 * NtEnumerateKey [NTDLL.@]
283 * ZwEnumerateKey [NTDLL.@]
286 * the name copied into the buffer is NOT 0-terminated
288 NTSTATUS WINAPI NtEnumerateKey( HKEY handle, ULONG index, KEY_INFORMATION_CLASS info_class,
289 void *info, DWORD length, DWORD *result_len )
291 /* -1 means query key, so avoid it here */
292 if (index == (ULONG)-1) return STATUS_NO_MORE_ENTRIES;
293 return enumerate_key( handle, index, info_class, info, length, result_len );
297 /******************************************************************************
298 * RtlpNtEnumerateSubKey [NTDLL.@]
301 NTSTATUS WINAPI RtlpNtEnumerateSubKey( HKEY handle, UNICODE_STRING *out, ULONG index )
303 KEY_BASIC_INFORMATION *info;
304 DWORD dwLen, dwResultLen;
309 dwLen = out->Length + sizeof(KEY_BASIC_INFORMATION);
310 info = (KEY_BASIC_INFORMATION*)RtlAllocateHeap( GetProcessHeap(), 0, dwLen );
312 return STATUS_NO_MEMORY;
320 ret = NtEnumerateKey( handle, index, KeyBasicInformation, info, dwLen, &dwResultLen );
321 dwResultLen -= sizeof(KEY_BASIC_INFORMATION);
323 if (ret == STATUS_BUFFER_OVERFLOW)
324 out->Length = dwResultLen;
327 if (out->Length < info->NameLength)
329 out->Length = dwResultLen;
330 ret = STATUS_BUFFER_OVERFLOW;
334 out->Length = info->NameLength;
335 memcpy(out->Buffer, info->Name, info->NameLength);
340 RtlFreeHeap( GetProcessHeap(), 0, info );
344 /******************************************************************************
345 * NtQueryKey [NTDLL.@]
346 * ZwQueryKey [NTDLL.@]
348 NTSTATUS WINAPI NtQueryKey( HKEY handle, KEY_INFORMATION_CLASS info_class,
349 void *info, DWORD length, DWORD *result_len )
351 return enumerate_key( handle, -1, info_class, info, length, result_len );
355 /* fill the key value info structure for a specific info class */
356 static void copy_key_value_info( KEY_VALUE_INFORMATION_CLASS info_class, void *info,
357 DWORD length, int type, int name_len, int data_len )
361 case KeyValueBasicInformation:
363 KEY_VALUE_BASIC_INFORMATION keyinfo;
364 keyinfo.TitleIndex = 0;
366 keyinfo.NameLength = name_len;
367 length = min( length, (char *)keyinfo.Name - (char *)&keyinfo );
368 memcpy( info, &keyinfo, length );
371 case KeyValueFullInformation:
373 KEY_VALUE_FULL_INFORMATION keyinfo;
374 keyinfo.TitleIndex = 0;
376 keyinfo.DataOffset = (char *)keyinfo.Name - (char *)&keyinfo + name_len;
377 keyinfo.DataLength = data_len;
378 keyinfo.NameLength = name_len;
379 length = min( length, (char *)keyinfo.Name - (char *)&keyinfo );
380 memcpy( info, &keyinfo, length );
383 case KeyValuePartialInformation:
385 KEY_VALUE_PARTIAL_INFORMATION keyinfo;
386 keyinfo.TitleIndex = 0;
388 keyinfo.DataLength = data_len;
389 length = min( length, (char *)keyinfo.Data - (char *)&keyinfo );
390 memcpy( info, &keyinfo, length );
399 /******************************************************************************
400 * NtEnumerateValueKey [NTDLL.@]
401 * ZwEnumerateValueKey [NTDLL.@]
403 NTSTATUS WINAPI NtEnumerateValueKey( HKEY handle, ULONG index,
404 KEY_VALUE_INFORMATION_CLASS info_class,
405 void *info, DWORD length, DWORD *result_len )
411 TRACE( "(%p,%lu,%d,%p,%ld)\n", handle, index, info_class, info, length );
413 /* compute the length we want to retrieve */
416 case KeyValueBasicInformation: ptr = ((KEY_VALUE_BASIC_INFORMATION *)info)->Name; break;
417 case KeyValueFullInformation: ptr = ((KEY_VALUE_FULL_INFORMATION *)info)->Name; break;
418 case KeyValuePartialInformation: ptr = ((KEY_VALUE_PARTIAL_INFORMATION *)info)->Data; break;
420 FIXME( "Information class %d not implemented\n", info_class );
421 return STATUS_INVALID_PARAMETER;
423 fixed_size = (char *)ptr - (char *)info;
425 SERVER_START_REQ( enum_key_value )
429 req->info_class = info_class;
430 if (length > fixed_size) wine_server_set_reply( req, ptr, length - fixed_size );
431 if (!(ret = wine_server_call( req )))
433 copy_key_value_info( info_class, info, length, reply->type, reply->namelen,
434 wine_server_reply_size(reply) - reply->namelen );
435 *result_len = fixed_size + reply->total;
436 if (length < *result_len) ret = STATUS_BUFFER_OVERFLOW;
444 /******************************************************************************
445 * NtQueryValueKey [NTDLL.@]
446 * ZwQueryValueKey [NTDLL.@]
449 * the name in the KeyValueInformation is never set
451 NTSTATUS WINAPI NtQueryValueKey( HKEY handle, const UNICODE_STRING *name,
452 KEY_VALUE_INFORMATION_CLASS info_class,
453 void *info, DWORD length, DWORD *result_len )
457 unsigned int fixed_size = 0;
459 TRACE( "(%p,%s,%d,%p,%ld)\n", handle, debugstr_us(name), info_class, info, length );
461 if (name->Length > MAX_NAME_LENGTH) return STATUS_BUFFER_OVERFLOW;
463 /* compute the length we want to retrieve */
466 case KeyValueBasicInformation:
467 fixed_size = (char *)((KEY_VALUE_BASIC_INFORMATION *)info)->Name - (char *)info;
470 case KeyValueFullInformation:
471 data_ptr = (UCHAR *)((KEY_VALUE_FULL_INFORMATION *)info)->Name;
472 fixed_size = (char *)data_ptr - (char *)info;
474 case KeyValuePartialInformation:
475 data_ptr = ((KEY_VALUE_PARTIAL_INFORMATION *)info)->Data;
476 fixed_size = (char *)data_ptr - (char *)info;
479 FIXME( "Information class %d not implemented\n", info_class );
480 return STATUS_INVALID_PARAMETER;
483 SERVER_START_REQ( get_key_value )
486 wine_server_add_data( req, name->Buffer, name->Length );
487 if (length > fixed_size) wine_server_set_reply( req, data_ptr, length - fixed_size );
488 if (!(ret = wine_server_call( req )))
490 copy_key_value_info( info_class, info, length, reply->type,
491 0, wine_server_reply_size(reply) );
492 *result_len = fixed_size + reply->total;
493 if (length < *result_len) ret = STATUS_BUFFER_OVERFLOW;
500 /******************************************************************************
501 * RtlpNtQueryValueKey [NTDLL.@]
504 NTSTATUS WINAPI RtlpNtQueryValueKey( HKEY handle, ULONG *result_type, PBYTE dest,
507 KEY_VALUE_PARTIAL_INFORMATION *info;
511 DWORD dwLen = sizeof (KEY_VALUE_PARTIAL_INFORMATION) + result_len ? *result_len : 0;
513 info = (KEY_VALUE_PARTIAL_INFORMATION*)RtlAllocateHeap( GetProcessHeap(), 0, dwLen );
515 return STATUS_NO_MEMORY;
518 ret = NtQueryValueKey( handle, &name, KeyValuePartialInformation, info, dwLen, &dwResultLen );
520 if (!ret || ret == STATUS_BUFFER_OVERFLOW)
523 *result_len = info->DataLength;
526 *result_type = info->Type;
528 if (ret != STATUS_BUFFER_OVERFLOW)
529 memcpy( dest, info->Data, info->DataLength );
532 RtlFreeHeap( GetProcessHeap(), 0, info );
536 /******************************************************************************
537 * NtFlushKey [NTDLL.@]
538 * ZwFlushKey [NTDLL.@]
540 NTSTATUS WINAPI NtFlushKey(HKEY key)
544 TRACE("key=%p\n", key);
546 SERVER_START_REQ( flush_key )
549 ret = wine_server_call( req );
556 /******************************************************************************
557 * NtLoadKey [NTDLL.@]
558 * ZwLoadKey [NTDLL.@]
560 NTSTATUS WINAPI NtLoadKey( const OBJECT_ATTRIBUTES *attr, const OBJECT_ATTRIBUTES *file )
563 dump_ObjectAttributes(attr);
564 dump_ObjectAttributes(file);
565 return STATUS_SUCCESS;
568 /******************************************************************************
569 * NtNotifyChangeKey [NTDLL.@]
570 * ZwNotifyChangeKey [NTDLL.@]
572 NTSTATUS WINAPI NtNotifyChangeKey(
575 IN PIO_APC_ROUTINE ApcRoutine OPTIONAL,
576 IN PVOID ApcContext OPTIONAL,
577 OUT PIO_STATUS_BLOCK IoStatusBlock,
578 IN ULONG CompletionFilter,
579 IN BOOLEAN Asynchroneous,
580 OUT PVOID ChangeBuffer,
582 IN BOOLEAN WatchSubtree)
584 FIXME("(%p,%p,%p,%p,%p,0x%08lx, 0x%08x,%p,0x%08lx,0x%08x) stub!\n",
585 KeyHandle, Event, ApcRoutine, ApcContext, IoStatusBlock, CompletionFilter,
586 Asynchroneous, ChangeBuffer, Length, WatchSubtree);
587 return STATUS_SUCCESS;
590 /******************************************************************************
591 * NtQueryMultipleValueKey [NTDLL]
592 * ZwQueryMultipleValueKey
595 NTSTATUS WINAPI NtQueryMultipleValueKey(
597 PVALENTW ListOfValuesToQuery,
599 PVOID MultipleValueInformation,
603 FIXME("(%p,%p,0x%08lx,%p,0x%08lx,%p) stub!\n",
604 KeyHandle, ListOfValuesToQuery, NumberOfItems, MultipleValueInformation,
605 Length,ReturnLength);
606 return STATUS_SUCCESS;
609 /******************************************************************************
610 * NtReplaceKey [NTDLL.@]
611 * ZwReplaceKey [NTDLL.@]
613 NTSTATUS WINAPI NtReplaceKey(
614 IN POBJECT_ATTRIBUTES ObjectAttributes,
616 IN POBJECT_ATTRIBUTES ReplacedObjectAttributes)
618 FIXME("(%p),stub!\n", Key);
619 dump_ObjectAttributes(ObjectAttributes);
620 dump_ObjectAttributes(ReplacedObjectAttributes);
621 return STATUS_SUCCESS;
623 /******************************************************************************
624 * NtRestoreKey [NTDLL.@]
625 * ZwRestoreKey [NTDLL.@]
627 NTSTATUS WINAPI NtRestoreKey(
632 FIXME("(%p,%p,0x%08lx) stub\n",
633 KeyHandle, FileHandle, RestoreFlags);
634 return STATUS_SUCCESS;
636 /******************************************************************************
637 * NtSaveKey [NTDLL.@]
638 * ZwSaveKey [NTDLL.@]
640 NTSTATUS WINAPI NtSaveKey(
642 IN HANDLE FileHandle)
644 FIXME("(%p,%p) stub\n",
645 KeyHandle, FileHandle);
646 return STATUS_SUCCESS;
648 /******************************************************************************
649 * NtSetInformationKey [NTDLL.@]
650 * ZwSetInformationKey [NTDLL.@]
652 NTSTATUS WINAPI NtSetInformationKey(
654 IN const int KeyInformationClass,
655 IN PVOID KeyInformation,
656 IN ULONG KeyInformationLength)
658 FIXME("(%p,0x%08x,%p,0x%08lx) stub\n",
659 KeyHandle, KeyInformationClass, KeyInformation, KeyInformationLength);
660 return STATUS_SUCCESS;
664 /******************************************************************************
665 * NtSetValueKey [NTDLL.@]
666 * ZwSetValueKey [NTDLL.@]
669 * win95 does not care about count for REG_SZ and finds out the len by itself (js)
670 * NT does definitely care (aj)
672 NTSTATUS WINAPI NtSetValueKey( HKEY hkey, const UNICODE_STRING *name, ULONG TitleIndex,
673 ULONG type, const void *data, ULONG count )
677 TRACE( "(%p,%s,%ld,%p,%ld)\n", hkey, debugstr_us(name), type, data, count );
679 if (name->Length > MAX_NAME_LENGTH) return STATUS_BUFFER_OVERFLOW;
681 SERVER_START_REQ( set_key_value )
685 req->namelen = name->Length;
686 wine_server_add_data( req, name->Buffer, name->Length );
687 wine_server_add_data( req, data, count );
688 ret = wine_server_call( req );
694 /******************************************************************************
695 * RtlpNtSetValueKey [NTDLL.@]
698 NTSTATUS WINAPI RtlpNtSetValueKey( HKEY hkey, ULONG type, const void *data,
704 return NtSetValueKey( hkey, &name, 0, type, data, count );
707 /******************************************************************************
708 * NtUnloadKey [NTDLL.@]
709 * ZwUnloadKey [NTDLL.@]
711 NTSTATUS WINAPI NtUnloadKey(
716 return STATUS_SUCCESS;
719 /******************************************************************************
720 * RtlFormatCurrentUserKeyPath [NTDLL.@]
722 * NOTE: under NT the user name part of the path is an SID.
724 NTSTATUS WINAPI RtlFormatCurrentUserKeyPath( IN OUT PUNICODE_STRING KeyPath)
726 static const WCHAR pathW[] = {'\\','R','e','g','i','s','t','r','y','\\','U','s','e','r','\\'};
727 const char *user = wine_get_user_name();
728 int len = ntdll_umbstowcs( 0, user, strlen(user)+1, NULL, 0 );
730 KeyPath->MaximumLength = sizeof(pathW) + len * sizeof(WCHAR);
731 KeyPath->Length = KeyPath->MaximumLength - sizeof(WCHAR);
732 if (!(KeyPath->Buffer = RtlAllocateHeap( GetProcessHeap(), 0, KeyPath->MaximumLength )))
733 return STATUS_NO_MEMORY;
734 memcpy( KeyPath->Buffer, pathW, sizeof(pathW) );
735 ntdll_umbstowcs( 0, user, strlen(user)+1, KeyPath->Buffer + sizeof(pathW)/sizeof(WCHAR), len );
736 return STATUS_SUCCESS;
739 /******************************************************************************
740 * RtlOpenCurrentUser [NTDLL.@]
742 * if we return just HKEY_CURRENT_USER the advapi tries to find a remote
743 * registry (odd handle) and fails
746 DWORD WINAPI RtlOpenCurrentUser(
747 IN ACCESS_MASK DesiredAccess, /* [in] */
748 OUT PHKEY KeyHandle) /* [out] handle of HKEY_CURRENT_USER */
750 OBJECT_ATTRIBUTES ObjectAttributes;
751 UNICODE_STRING ObjectName;
754 TRACE("(0x%08lx, %p) stub\n",DesiredAccess, KeyHandle);
756 RtlFormatCurrentUserKeyPath(&ObjectName);
757 InitializeObjectAttributes(&ObjectAttributes,&ObjectName,OBJ_CASE_INSENSITIVE,0, NULL);
758 ret = NtCreateKey(KeyHandle, DesiredAccess, &ObjectAttributes, 0, NULL, 0, NULL);
759 RtlFreeUnicodeString(&ObjectName);