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"
35 #include "wine/unicode.h"
36 #include "wine/library.h"
37 #include "wine/server.h"
39 #include "ntdll_misc.h"
40 #include "wine/debug.h"
42 WINE_DEFAULT_DEBUG_CHANNEL(reg);
44 /* maximum length of a key/value name in bytes (without terminating null) */
45 #define MAX_NAME_LENGTH ((MAX_PATH-1) * sizeof(WCHAR))
48 /******************************************************************************
49 * NtCreateKey [NTDLL.@]
50 * ZwCreateKey [NTDLL.@]
52 NTSTATUS WINAPI NtCreateKey( PHKEY retkey, ACCESS_MASK access, const OBJECT_ATTRIBUTES *attr,
53 ULONG TitleIndex, const UNICODE_STRING *class, ULONG options,
58 TRACE( "(%p,%s,%s,%lx,%lx,%p)\n", attr->RootDirectory, debugstr_us(attr->ObjectName),
59 debugstr_us(class), options, access, retkey );
61 if (attr->ObjectName->Length > MAX_NAME_LENGTH) return STATUS_BUFFER_OVERFLOW;
62 if (!retkey) return STATUS_INVALID_PARAMETER;
64 SERVER_START_REQ( create_key )
66 req->parent = attr->RootDirectory;
68 req->options = options;
70 req->namelen = attr->ObjectName->Length;
71 wine_server_add_data( req, attr->ObjectName->Buffer, attr->ObjectName->Length );
72 if (class) wine_server_add_data( req, class->Buffer, class->Length );
73 if (!(ret = wine_server_call( req )))
75 *retkey = reply->hkey;
76 if (dispos) *dispos = reply->created ? REG_CREATED_NEW_KEY : REG_OPENED_EXISTING_KEY;
80 TRACE("<- %p\n", *retkey);
85 /******************************************************************************
89 * OUT PHKEY retkey (returns 0 when failure)
90 * IN ACCESS_MASK access
91 * IN POBJECT_ATTRIBUTES attr
93 NTSTATUS WINAPI NtOpenKey( PHKEY retkey, ACCESS_MASK access, const OBJECT_ATTRIBUTES *attr )
96 DWORD len = attr->ObjectName->Length;
98 TRACE( "(%p,%s,%lx,%p)\n", attr->RootDirectory,
99 debugstr_us(attr->ObjectName), access, retkey );
101 if (len > MAX_NAME_LENGTH) return STATUS_BUFFER_OVERFLOW;
102 if (!retkey) return STATUS_INVALID_PARAMETER;
104 SERVER_START_REQ( open_key )
106 req->parent = attr->RootDirectory;
107 req->access = access;
108 wine_server_add_data( req, attr->ObjectName->Buffer, len );
109 ret = wine_server_call( req );
110 *retkey = reply->hkey;
113 TRACE("<- %p\n", *retkey);
118 /******************************************************************************
119 * NtDeleteKey [NTDLL.@]
120 * ZwDeleteKey [NTDLL.@]
122 NTSTATUS WINAPI NtDeleteKey( HKEY hkey )
126 TRACE( "(%p)\n", hkey );
128 SERVER_START_REQ( delete_key )
131 ret = wine_server_call( req );
138 /******************************************************************************
139 * NtDeleteValueKey [NTDLL.@]
140 * ZwDeleteValueKey [NTDLL.@]
142 NTSTATUS WINAPI NtDeleteValueKey( HKEY hkey, const UNICODE_STRING *name )
146 TRACE( "(%p,%s)\n", hkey, debugstr_us(name) );
147 if (name->Length > MAX_NAME_LENGTH) return STATUS_BUFFER_OVERFLOW;
149 SERVER_START_REQ( delete_key_value )
152 wine_server_add_data( req, name->Buffer, name->Length );
153 ret = wine_server_call( req );
160 /******************************************************************************
163 * Implementation of NtQueryKey and NtEnumerateKey
165 static NTSTATUS enumerate_key( HKEY handle, int index, KEY_INFORMATION_CLASS info_class,
166 void *info, DWORD length, DWORD *result_len )
175 case KeyBasicInformation: data_ptr = ((KEY_BASIC_INFORMATION *)info)->Name; break;
176 case KeyFullInformation: data_ptr = ((KEY_FULL_INFORMATION *)info)->Class; break;
177 case KeyNodeInformation: data_ptr = ((KEY_NODE_INFORMATION *)info)->Name; break;
179 FIXME( "Information class %d not implemented\n", info_class );
180 return STATUS_INVALID_PARAMETER;
182 fixed_size = (char *)data_ptr - (char *)info;
184 SERVER_START_REQ( enum_key )
188 req->info_class = info_class;
189 if (length > fixed_size) wine_server_set_reply( req, data_ptr, length - fixed_size );
190 if (!(ret = wine_server_call( req )))
194 RtlSecondsSince1970ToTime( reply->modif, &modif );
198 case KeyBasicInformation:
200 KEY_BASIC_INFORMATION keyinfo;
201 fixed_size = (char *)keyinfo.Name - (char *)&keyinfo;
202 keyinfo.LastWriteTime = modif;
203 keyinfo.TitleIndex = 0;
204 keyinfo.NameLength = reply->namelen;
205 memcpy( info, &keyinfo, min( length, fixed_size ) );
208 case KeyFullInformation:
210 KEY_FULL_INFORMATION keyinfo;
211 fixed_size = (char *)keyinfo.Class - (char *)&keyinfo;
212 keyinfo.LastWriteTime = modif;
213 keyinfo.TitleIndex = 0;
214 keyinfo.ClassLength = wine_server_reply_size(reply);
215 keyinfo.ClassOffset = keyinfo.ClassLength ? fixed_size : -1;
216 keyinfo.SubKeys = reply->subkeys;
217 keyinfo.MaxNameLen = reply->max_subkey;
218 keyinfo.MaxClassLen = reply->max_class;
219 keyinfo.Values = reply->values;
220 keyinfo.MaxValueNameLen = reply->max_value;
221 keyinfo.MaxValueDataLen = reply->max_data;
222 memcpy( info, &keyinfo, min( length, fixed_size ) );
225 case KeyNodeInformation:
227 KEY_NODE_INFORMATION keyinfo;
228 fixed_size = (char *)keyinfo.Name - (char *)&keyinfo;
229 keyinfo.LastWriteTime = modif;
230 keyinfo.TitleIndex = 0;
231 keyinfo.ClassLength = max( 0, wine_server_reply_size(reply) - reply->namelen );
232 keyinfo.ClassOffset = keyinfo.ClassLength ? fixed_size + reply->namelen : -1;
233 keyinfo.NameLength = reply->namelen;
234 memcpy( info, &keyinfo, min( length, fixed_size ) );
238 *result_len = fixed_size + reply->total;
239 if (length < *result_len) ret = STATUS_BUFFER_OVERFLOW;
248 /******************************************************************************
249 * NtEnumerateKey [NTDLL.@]
250 * ZwEnumerateKey [NTDLL.@]
253 * the name copied into the buffer is NOT 0-terminated
255 NTSTATUS WINAPI NtEnumerateKey( HKEY handle, ULONG index, KEY_INFORMATION_CLASS info_class,
256 void *info, DWORD length, DWORD *result_len )
258 /* -1 means query key, so avoid it here */
259 if (index == (ULONG)-1) return STATUS_NO_MORE_ENTRIES;
260 return enumerate_key( handle, index, info_class, info, length, result_len );
264 /******************************************************************************
265 * NtQueryKey [NTDLL.@]
266 * ZwQueryKey [NTDLL.@]
268 NTSTATUS WINAPI NtQueryKey( HKEY handle, KEY_INFORMATION_CLASS info_class,
269 void *info, DWORD length, DWORD *result_len )
271 return enumerate_key( handle, -1, info_class, info, length, result_len );
275 /* fill the key value info structure for a specific info class */
276 static void copy_key_value_info( KEY_VALUE_INFORMATION_CLASS info_class, void *info,
277 DWORD length, int type, int name_len, int data_len )
281 case KeyValueBasicInformation:
283 KEY_VALUE_BASIC_INFORMATION keyinfo;
284 keyinfo.TitleIndex = 0;
286 keyinfo.NameLength = name_len;
287 length = min( length, (char *)keyinfo.Name - (char *)&keyinfo );
288 memcpy( info, &keyinfo, length );
291 case KeyValueFullInformation:
293 KEY_VALUE_FULL_INFORMATION keyinfo;
294 keyinfo.TitleIndex = 0;
296 keyinfo.DataOffset = (char *)keyinfo.Name - (char *)&keyinfo + name_len;
297 keyinfo.DataLength = data_len;
298 keyinfo.NameLength = name_len;
299 length = min( length, (char *)keyinfo.Name - (char *)&keyinfo );
300 memcpy( info, &keyinfo, length );
303 case KeyValuePartialInformation:
305 KEY_VALUE_PARTIAL_INFORMATION keyinfo;
306 keyinfo.TitleIndex = 0;
308 keyinfo.DataLength = data_len;
309 length = min( length, (char *)keyinfo.Data - (char *)&keyinfo );
310 memcpy( info, &keyinfo, length );
319 /******************************************************************************
320 * NtEnumerateValueKey [NTDLL.@]
321 * ZwEnumerateValueKey [NTDLL.@]
323 NTSTATUS WINAPI NtEnumerateValueKey( HKEY handle, ULONG index,
324 KEY_VALUE_INFORMATION_CLASS info_class,
325 void *info, DWORD length, DWORD *result_len )
331 TRACE( "(%p,%lu,%d,%p,%ld)\n", handle, index, info_class, info, length );
333 /* compute the length we want to retrieve */
336 case KeyValueBasicInformation: ptr = ((KEY_VALUE_BASIC_INFORMATION *)info)->Name; break;
337 case KeyValueFullInformation: ptr = ((KEY_VALUE_FULL_INFORMATION *)info)->Name; break;
338 case KeyValuePartialInformation: ptr = ((KEY_VALUE_PARTIAL_INFORMATION *)info)->Data; break;
340 FIXME( "Information class %d not implemented\n", info_class );
341 return STATUS_INVALID_PARAMETER;
343 fixed_size = (char *)ptr - (char *)info;
345 SERVER_START_REQ( enum_key_value )
349 req->info_class = info_class;
350 if (length > fixed_size) wine_server_set_reply( req, ptr, length - fixed_size );
351 if (!(ret = wine_server_call( req )))
353 copy_key_value_info( info_class, info, length, reply->type, reply->namelen,
354 wine_server_reply_size(reply) - reply->namelen );
355 *result_len = fixed_size + reply->total;
356 if (length < *result_len) ret = STATUS_BUFFER_OVERFLOW;
364 /******************************************************************************
365 * NtQueryValueKey [NTDLL.@]
366 * ZwQueryValueKey [NTDLL.@]
369 * the name in the KeyValueInformation is never set
371 NTSTATUS WINAPI NtQueryValueKey( HKEY handle, const UNICODE_STRING *name,
372 KEY_VALUE_INFORMATION_CLASS info_class,
373 void *info, DWORD length, DWORD *result_len )
379 TRACE( "(%p,%s,%d,%p,%ld)\n", handle, debugstr_us(name), info_class, info, length );
381 if (name->Length > MAX_NAME_LENGTH) return STATUS_BUFFER_OVERFLOW;
383 /* compute the length we want to retrieve */
386 case KeyValueBasicInformation:
387 fixed_size = (char *)((KEY_VALUE_BASIC_INFORMATION *)info)->Name - (char *)info;
390 case KeyValueFullInformation:
391 data_ptr = (UCHAR *)((KEY_VALUE_FULL_INFORMATION *)info)->Name;
392 fixed_size = (char *)data_ptr - (char *)info;
394 case KeyValuePartialInformation:
395 data_ptr = ((KEY_VALUE_PARTIAL_INFORMATION *)info)->Data;
396 fixed_size = (char *)data_ptr - (char *)info;
399 FIXME( "Information class %d not implemented\n", info_class );
400 return STATUS_INVALID_PARAMETER;
403 SERVER_START_REQ( get_key_value )
406 wine_server_add_data( req, name->Buffer, name->Length );
407 if (length > fixed_size) wine_server_set_reply( req, data_ptr, length - fixed_size );
408 if (!(ret = wine_server_call( req )))
410 copy_key_value_info( info_class, info, length, reply->type,
411 0, wine_server_reply_size(reply) );
412 *result_len = fixed_size + reply->total;
413 if (length < *result_len) ret = STATUS_BUFFER_OVERFLOW;
421 /******************************************************************************
422 * NtFlushKey [NTDLL.@]
423 * ZwFlushKey [NTDLL.@]
425 NTSTATUS WINAPI NtFlushKey(HKEY KeyHandle)
427 FIXME("(%p) stub!\n",
432 /******************************************************************************
433 * NtLoadKey [NTDLL.@]
434 * ZwLoadKey [NTDLL.@]
436 NTSTATUS WINAPI NtLoadKey( const OBJECT_ATTRIBUTES *attr, const OBJECT_ATTRIBUTES *file )
439 dump_ObjectAttributes(attr);
440 dump_ObjectAttributes(file);
441 return STATUS_SUCCESS;
444 /******************************************************************************
445 * NtNotifyChangeKey [NTDLL.@]
446 * ZwNotifyChangeKey [NTDLL.@]
448 NTSTATUS WINAPI NtNotifyChangeKey(
451 IN PIO_APC_ROUTINE ApcRoutine OPTIONAL,
452 IN PVOID ApcContext OPTIONAL,
453 OUT PIO_STATUS_BLOCK IoStatusBlock,
454 IN ULONG CompletionFilter,
455 IN BOOLEAN Asynchroneous,
456 OUT PVOID ChangeBuffer,
458 IN BOOLEAN WatchSubtree)
460 FIXME("(%p,%p,%p,%p,%p,0x%08lx, 0x%08x,%p,0x%08lx,0x%08x) stub!\n",
461 KeyHandle, Event, ApcRoutine, ApcContext, IoStatusBlock, CompletionFilter,
462 Asynchroneous, ChangeBuffer, Length, WatchSubtree);
463 return STATUS_SUCCESS;
466 /******************************************************************************
467 * NtQueryMultipleValueKey [NTDLL]
468 * ZwQueryMultipleValueKey
471 NTSTATUS WINAPI NtQueryMultipleValueKey(
473 PVALENTW ListOfValuesToQuery,
475 PVOID MultipleValueInformation,
479 FIXME("(%p,%p,0x%08lx,%p,0x%08lx,%p) stub!\n",
480 KeyHandle, ListOfValuesToQuery, NumberOfItems, MultipleValueInformation,
481 Length,ReturnLength);
482 return STATUS_SUCCESS;
485 /******************************************************************************
486 * NtReplaceKey [NTDLL.@]
487 * ZwReplaceKey [NTDLL.@]
489 NTSTATUS WINAPI NtReplaceKey(
490 IN POBJECT_ATTRIBUTES ObjectAttributes,
492 IN POBJECT_ATTRIBUTES ReplacedObjectAttributes)
494 FIXME("(%p),stub!\n", Key);
495 dump_ObjectAttributes(ObjectAttributes);
496 dump_ObjectAttributes(ReplacedObjectAttributes);
497 return STATUS_SUCCESS;
499 /******************************************************************************
500 * NtRestoreKey [NTDLL.@]
501 * ZwRestoreKey [NTDLL.@]
503 NTSTATUS WINAPI NtRestoreKey(
508 FIXME("(%p,%p,0x%08lx) stub\n",
509 KeyHandle, FileHandle, RestoreFlags);
510 return STATUS_SUCCESS;
512 /******************************************************************************
513 * NtSaveKey [NTDLL.@]
514 * ZwSaveKey [NTDLL.@]
516 NTSTATUS WINAPI NtSaveKey(
518 IN HANDLE FileHandle)
520 FIXME("(%p,%p) stub\n",
521 KeyHandle, FileHandle);
522 return STATUS_SUCCESS;
524 /******************************************************************************
525 * NtSetInformationKey [NTDLL.@]
526 * ZwSetInformationKey [NTDLL.@]
528 NTSTATUS WINAPI NtSetInformationKey(
530 IN const int KeyInformationClass,
531 IN PVOID KeyInformation,
532 IN ULONG KeyInformationLength)
534 FIXME("(%p,0x%08x,%p,0x%08lx) stub\n",
535 KeyHandle, KeyInformationClass, KeyInformation, KeyInformationLength);
536 return STATUS_SUCCESS;
540 /******************************************************************************
541 * NtSetValueKey [NTDLL.@]
542 * ZwSetValueKey [NTDLL.@]
545 * win95 does not care about count for REG_SZ and finds out the len by itself (js)
546 * NT does definitely care (aj)
548 NTSTATUS WINAPI NtSetValueKey( HKEY hkey, const UNICODE_STRING *name, ULONG TitleIndex,
549 ULONG type, const void *data, ULONG count )
553 TRACE( "(%p,%s,%ld,%p,%ld)\n", hkey, debugstr_us(name), type, data, count );
555 if (name->Length > MAX_NAME_LENGTH) return STATUS_BUFFER_OVERFLOW;
557 SERVER_START_REQ( set_key_value )
561 req->namelen = name->Length;
562 wine_server_add_data( req, name->Buffer, name->Length );
563 wine_server_add_data( req, data, count );
564 ret = wine_server_call( req );
570 /******************************************************************************
571 * NtUnloadKey [NTDLL.@]
572 * ZwUnloadKey [NTDLL.@]
574 NTSTATUS WINAPI NtUnloadKey(
579 return STATUS_SUCCESS;
582 /******************************************************************************
583 * RtlFormatCurrentUserKeyPath [NTDLL.@]
585 * NOTE: under NT the user name part of the path is an SID.
587 NTSTATUS WINAPI RtlFormatCurrentUserKeyPath( IN OUT PUNICODE_STRING KeyPath)
589 const char *user = wine_get_user_name();
591 ANSI_STRING AnsiPath;
594 if (!(buffer = RtlAllocateHeap( ntdll_get_process_heap(), 0, strlen(user)+16 )))
595 return STATUS_NO_MEMORY;
597 strcpy( buffer, "\\Registry\\User\\" );
598 strcat( buffer, user );
599 RtlInitAnsiString( &AnsiPath, buffer );
600 ret = RtlAnsiStringToUnicodeString(KeyPath, &AnsiPath, TRUE);
601 RtlFreeAnsiString( &AnsiPath );
605 /******************************************************************************
606 * RtlOpenCurrentUser [NTDLL.@]
608 * if we return just HKEY_CURRENT_USER the advapi tries to find a remote
609 * registry (odd handle) and fails
612 DWORD WINAPI RtlOpenCurrentUser(
613 IN ACCESS_MASK DesiredAccess, /* [in] */
614 OUT PHKEY KeyHandle) /* [out] handle of HKEY_CURRENT_USER */
616 OBJECT_ATTRIBUTES ObjectAttributes;
617 UNICODE_STRING ObjectName;
620 TRACE("(0x%08lx, %p) stub\n",DesiredAccess, KeyHandle);
622 RtlFormatCurrentUserKeyPath(&ObjectName);
623 InitializeObjectAttributes(&ObjectAttributes,&ObjectName,OBJ_CASE_INSENSITIVE,0, NULL);
624 ret = NtCreateKey(KeyHandle, DesiredAccess, &ObjectAttributes, 0, NULL, 0, NULL);
625 RtlFreeUnicodeString(&ObjectName);