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,
39 TRACE( "(0x%x,%s,%s,%lx,%lx,%p)\n", attr->RootDirectory, debugstr_us(attr->ObjectName),
40 debugstr_us(class), options, access, retkey );
42 if (attr->ObjectName->Length > MAX_NAME_LENGTH) return STATUS_BUFFER_OVERFLOW;
43 if (!retkey) return STATUS_INVALID_PARAMETER;
45 SERVER_START_REQ( create_key )
47 req->parent = attr->RootDirectory;
49 req->options = options;
51 req->namelen = attr->ObjectName->Length;
52 wine_server_add_data( req, attr->ObjectName->Buffer, attr->ObjectName->Length );
53 if (class) wine_server_add_data( req, class->Buffer, class->Length );
54 if (!(ret = wine_server_call( req )))
56 *retkey = reply->hkey;
57 if (dispos) *dispos = reply->created ? REG_CREATED_NEW_KEY : REG_OPENED_EXISTING_KEY;
61 TRACE("<- 0x%04x\n", *retkey);
66 /******************************************************************************
70 * OUT PHANDLE retkey (returns 0 when failure)
71 * IN ACCESS_MASK access
72 * IN POBJECT_ATTRIBUTES attr
74 NTSTATUS WINAPI NtOpenKey( PHANDLE retkey, ACCESS_MASK access, const OBJECT_ATTRIBUTES *attr )
77 DWORD len = attr->ObjectName->Length;
79 TRACE( "(0x%x,%s,%lx,%p)\n", attr->RootDirectory,
80 debugstr_us(attr->ObjectName), access, retkey );
82 if (len > MAX_NAME_LENGTH) return STATUS_BUFFER_OVERFLOW;
83 if (!retkey) return STATUS_INVALID_PARAMETER;
85 SERVER_START_REQ( open_key )
87 req->parent = attr->RootDirectory;
89 wine_server_add_data( req, attr->ObjectName->Buffer, len );
90 ret = wine_server_call( req );
91 *retkey = reply->hkey;
94 TRACE("<- 0x%04x\n", *retkey);
99 /******************************************************************************
100 * NtDeleteKey [NTDLL.@]
101 * ZwDeleteKey [NTDLL.@]
103 NTSTATUS WINAPI NtDeleteKey( HANDLE hkey )
107 TRACE( "(%x)\n", hkey );
109 SERVER_START_REQ( delete_key )
112 ret = wine_server_call( req );
119 /******************************************************************************
120 * NtDeleteValueKey [NTDLL.@]
121 * ZwDeleteValueKey [NTDLL.@]
123 NTSTATUS WINAPI NtDeleteValueKey( HANDLE hkey, const UNICODE_STRING *name )
127 TRACE( "(0x%x,%s)\n", hkey, debugstr_us(name) );
128 if (name->Length > MAX_NAME_LENGTH) return STATUS_BUFFER_OVERFLOW;
130 SERVER_START_REQ( delete_key_value )
133 wine_server_add_data( req, name->Buffer, name->Length );
134 ret = wine_server_call( req );
141 /******************************************************************************
144 * Implementation of NtQueryKey and NtEnumerateKey
146 static NTSTATUS enumerate_key( HANDLE handle, int index, KEY_INFORMATION_CLASS info_class,
147 void *info, DWORD length, DWORD *result_len )
156 case KeyBasicInformation: data_ptr = ((KEY_BASIC_INFORMATION *)info)->Name; break;
157 case KeyFullInformation: data_ptr = ((KEY_FULL_INFORMATION *)info)->Class; break;
158 case KeyNodeInformation: data_ptr = ((KEY_NODE_INFORMATION *)info)->Name; break;
160 FIXME( "Information class %d not implemented\n", info_class );
161 return STATUS_INVALID_PARAMETER;
163 fixed_size = (char *)data_ptr - (char *)info;
165 SERVER_START_REQ( enum_key )
169 req->info_class = info_class;
170 if (length > fixed_size) wine_server_set_reply( req, data_ptr, length - fixed_size );
171 if (!(ret = wine_server_call( req )))
175 RtlSecondsSince1970ToTime( reply->modif, (FILETIME *)&modif );
179 case KeyBasicInformation:
181 KEY_BASIC_INFORMATION keyinfo;
182 fixed_size = (char *)keyinfo.Name - (char *)&keyinfo;
183 keyinfo.LastWriteTime = modif;
184 keyinfo.TitleIndex = 0;
185 keyinfo.NameLength = reply->namelen;
186 memcpy( info, &keyinfo, min( length, fixed_size ) );
189 case KeyFullInformation:
191 KEY_FULL_INFORMATION keyinfo;
192 fixed_size = (char *)keyinfo.Class - (char *)&keyinfo;
193 keyinfo.LastWriteTime = modif;
194 keyinfo.TitleIndex = 0;
195 keyinfo.ClassLength = wine_server_reply_size(reply);
196 keyinfo.ClassOffset = keyinfo.ClassLength ? fixed_size : -1;
197 keyinfo.SubKeys = reply->subkeys;
198 keyinfo.MaxNameLen = reply->max_subkey;
199 keyinfo.MaxClassLen = reply->max_class;
200 keyinfo.Values = reply->values;
201 keyinfo.MaxValueNameLen = reply->max_value;
202 keyinfo.MaxValueDataLen = reply->max_data;
203 memcpy( info, &keyinfo, min( length, fixed_size ) );
206 case KeyNodeInformation:
208 KEY_NODE_INFORMATION keyinfo;
209 fixed_size = (char *)keyinfo.Name - (char *)&keyinfo;
210 keyinfo.LastWriteTime = modif;
211 keyinfo.TitleIndex = 0;
212 keyinfo.ClassLength = max( 0, wine_server_reply_size(reply) - reply->namelen );
213 keyinfo.ClassOffset = keyinfo.ClassLength ? fixed_size + reply->namelen : -1;
214 keyinfo.NameLength = reply->namelen;
215 memcpy( info, &keyinfo, min( length, fixed_size ) );
219 *result_len = fixed_size + reply->total;
220 if (length < *result_len) ret = STATUS_BUFFER_OVERFLOW;
229 /******************************************************************************
230 * NtEnumerateKey [NTDLL.@]
231 * ZwEnumerateKey [NTDLL.@]
234 * the name copied into the buffer is NOT 0-terminated
236 NTSTATUS WINAPI NtEnumerateKey( HANDLE handle, ULONG index, KEY_INFORMATION_CLASS info_class,
237 void *info, DWORD length, DWORD *result_len )
239 /* -1 means query key, so avoid it here */
240 if (index == (ULONG)-1) return STATUS_NO_MORE_ENTRIES;
241 return enumerate_key( handle, index, info_class, info, length, result_len );
245 /******************************************************************************
246 * NtQueryKey [NTDLL.@]
247 * ZwQueryKey [NTDLL.@]
249 NTSTATUS WINAPI NtQueryKey( HANDLE handle, KEY_INFORMATION_CLASS info_class,
250 void *info, DWORD length, DWORD *result_len )
252 return enumerate_key( handle, -1, info_class, info, length, result_len );
256 /* fill the key value info structure for a specific info class */
257 static void copy_key_value_info( KEY_VALUE_INFORMATION_CLASS info_class, void *info,
258 DWORD length, int type, int name_len, int data_len )
262 case KeyValueBasicInformation:
264 KEY_VALUE_BASIC_INFORMATION keyinfo;
265 keyinfo.TitleIndex = 0;
267 keyinfo.NameLength = name_len;
268 length = min( length, (char *)keyinfo.Name - (char *)&keyinfo );
269 memcpy( info, &keyinfo, length );
272 case KeyValueFullInformation:
274 KEY_VALUE_FULL_INFORMATION keyinfo;
275 keyinfo.TitleIndex = 0;
277 keyinfo.DataOffset = (char *)keyinfo.Name - (char *)&keyinfo + name_len;
278 keyinfo.DataLength = data_len;
279 keyinfo.NameLength = name_len;
280 length = min( length, (char *)keyinfo.Name - (char *)&keyinfo );
281 memcpy( info, &keyinfo, length );
284 case KeyValuePartialInformation:
286 KEY_VALUE_PARTIAL_INFORMATION keyinfo;
287 keyinfo.TitleIndex = 0;
289 keyinfo.DataLength = data_len;
290 length = min( length, (char *)keyinfo.Data - (char *)&keyinfo );
291 memcpy( info, &keyinfo, length );
300 /******************************************************************************
301 * NtEnumerateValueKey [NTDLL.@]
302 * ZwEnumerateValueKey [NTDLL.@]
304 NTSTATUS WINAPI NtEnumerateValueKey( HANDLE handle, ULONG index,
305 KEY_VALUE_INFORMATION_CLASS info_class,
306 void *info, DWORD length, DWORD *result_len )
312 TRACE( "(0x%x,%lu,%d,%p,%ld)\n", handle, index, info_class, info, length );
314 /* compute the length we want to retrieve */
317 case KeyValueBasicInformation: ptr = ((KEY_VALUE_BASIC_INFORMATION *)info)->Name; break;
318 case KeyValueFullInformation: ptr = ((KEY_VALUE_FULL_INFORMATION *)info)->Name; break;
319 case KeyValuePartialInformation: ptr = ((KEY_VALUE_PARTIAL_INFORMATION *)info)->Data; break;
321 FIXME( "Information class %d not implemented\n", info_class );
322 return STATUS_INVALID_PARAMETER;
324 fixed_size = (char *)ptr - (char *)info;
326 SERVER_START_REQ( enum_key_value )
330 req->info_class = info_class;
331 if (length > fixed_size) wine_server_set_reply( req, ptr, length - fixed_size );
332 if (!(ret = wine_server_call( req )))
334 copy_key_value_info( info_class, info, length, reply->type, reply->namelen,
335 wine_server_reply_size(reply) - reply->namelen );
336 *result_len = fixed_size + reply->total;
337 if (length < *result_len) ret = STATUS_BUFFER_OVERFLOW;
345 /******************************************************************************
346 * NtQueryValueKey [NTDLL.@]
347 * ZwQueryValueKey [NTDLL.@]
350 * the name in the KeyValueInformation is never set
352 NTSTATUS WINAPI NtQueryValueKey( HANDLE handle, const UNICODE_STRING *name,
353 KEY_VALUE_INFORMATION_CLASS info_class,
354 void *info, DWORD length, DWORD *result_len )
360 TRACE( "(0x%x,%s,%d,%p,%ld)\n", handle, debugstr_us(name), info_class, info, length );
362 if (name->Length > MAX_NAME_LENGTH) return STATUS_BUFFER_OVERFLOW;
364 /* compute the length we want to retrieve */
367 case KeyValueBasicInformation:
368 fixed_size = (char *)((KEY_VALUE_BASIC_INFORMATION *)info)->Name - (char *)info;
371 case KeyValueFullInformation:
372 data_ptr = (UCHAR *)((KEY_VALUE_FULL_INFORMATION *)info)->Name;
373 fixed_size = (char *)data_ptr - (char *)info;
375 case KeyValuePartialInformation:
376 data_ptr = ((KEY_VALUE_PARTIAL_INFORMATION *)info)->Data;
377 fixed_size = (char *)data_ptr - (char *)info;
380 FIXME( "Information class %d not implemented\n", info_class );
381 return STATUS_INVALID_PARAMETER;
384 SERVER_START_REQ( get_key_value )
387 wine_server_add_data( req, name->Buffer, name->Length );
388 if (length > fixed_size) wine_server_set_reply( req, data_ptr, length - fixed_size );
389 if (!(ret = wine_server_call( req )))
391 copy_key_value_info( info_class, info, length, reply->type,
392 0, wine_server_reply_size(reply) );
393 *result_len = fixed_size + reply->total;
394 if (length < *result_len) ret = STATUS_BUFFER_OVERFLOW;
402 /******************************************************************************
403 * NtFlushKey [NTDLL.@]
404 * ZwFlushKey [NTDLL.@]
406 NTSTATUS WINAPI NtFlushKey(HANDLE KeyHandle)
408 FIXME("(0x%08x) stub!\n",
413 /******************************************************************************
414 * NtLoadKey [NTDLL.@]
415 * ZwLoadKey [NTDLL.@]
417 NTSTATUS WINAPI NtLoadKey( const OBJECT_ATTRIBUTES *attr, const OBJECT_ATTRIBUTES *file )
420 dump_ObjectAttributes(attr);
421 dump_ObjectAttributes(file);
422 return STATUS_SUCCESS;
425 /******************************************************************************
426 * NtNotifyChangeKey [NTDLL.@]
427 * ZwNotifyChangeKey [NTDLL.@]
429 NTSTATUS WINAPI NtNotifyChangeKey(
432 IN PIO_APC_ROUTINE ApcRoutine OPTIONAL,
433 IN PVOID ApcContext OPTIONAL,
434 OUT PIO_STATUS_BLOCK IoStatusBlock,
435 IN ULONG CompletionFilter,
436 IN BOOLEAN Asynchroneous,
437 OUT PVOID ChangeBuffer,
439 IN BOOLEAN WatchSubtree)
441 FIXME("(0x%08x,0x%08x,%p,%p,%p,0x%08lx, 0x%08x,%p,0x%08lx,0x%08x) stub!\n",
442 KeyHandle, Event, ApcRoutine, ApcContext, IoStatusBlock, CompletionFilter,
443 Asynchroneous, ChangeBuffer, Length, WatchSubtree);
444 return STATUS_SUCCESS;
447 /******************************************************************************
448 * NtQueryMultipleValueKey [NTDLL]
449 * ZwQueryMultipleValueKey
452 NTSTATUS WINAPI NtQueryMultipleValueKey(
454 PVALENTW ListOfValuesToQuery,
456 PVOID MultipleValueInformation,
460 FIXME("(0x%08x,%p,0x%08lx,%p,0x%08lx,%p) stub!\n",
461 KeyHandle, ListOfValuesToQuery, NumberOfItems, MultipleValueInformation,
462 Length,ReturnLength);
463 return STATUS_SUCCESS;
466 /******************************************************************************
467 * NtReplaceKey [NTDLL.@]
468 * ZwReplaceKey [NTDLL.@]
470 NTSTATUS WINAPI NtReplaceKey(
471 IN POBJECT_ATTRIBUTES ObjectAttributes,
473 IN POBJECT_ATTRIBUTES ReplacedObjectAttributes)
475 FIXME("(0x%08x),stub!\n", Key);
476 dump_ObjectAttributes(ObjectAttributes);
477 dump_ObjectAttributes(ReplacedObjectAttributes);
478 return STATUS_SUCCESS;
480 /******************************************************************************
481 * NtRestoreKey [NTDLL.@]
482 * ZwRestoreKey [NTDLL.@]
484 NTSTATUS WINAPI NtRestoreKey(
489 FIXME("(0x%08x,0x%08x,0x%08lx) stub\n",
490 KeyHandle, FileHandle, RestoreFlags);
491 return STATUS_SUCCESS;
493 /******************************************************************************
494 * NtSaveKey [NTDLL.@]
495 * ZwSaveKey [NTDLL.@]
497 NTSTATUS WINAPI NtSaveKey(
499 IN HANDLE FileHandle)
501 FIXME("(0x%08x,0x%08x) stub\n",
502 KeyHandle, FileHandle);
503 return STATUS_SUCCESS;
505 /******************************************************************************
506 * NtSetInformationKey [NTDLL.@]
507 * ZwSetInformationKey [NTDLL.@]
509 NTSTATUS WINAPI NtSetInformationKey(
511 IN const int KeyInformationClass,
512 IN PVOID KeyInformation,
513 IN ULONG KeyInformationLength)
515 FIXME("(0x%08x,0x%08x,%p,0x%08lx) stub\n",
516 KeyHandle, KeyInformationClass, KeyInformation, KeyInformationLength);
517 return STATUS_SUCCESS;
521 /******************************************************************************
522 * NtSetValueKey [NTDLL.@]
523 * ZwSetValueKey [NTDLL.@]
526 * win95 does not care about count for REG_SZ and finds out the len by itself (js)
527 * NT does definitely care (aj)
529 NTSTATUS WINAPI NtSetValueKey( HANDLE hkey, const UNICODE_STRING *name, ULONG TitleIndex,
530 ULONG type, const void *data, ULONG count )
534 TRACE( "(0x%x,%s,%ld,%p,%ld)\n", hkey, debugstr_us(name), type, data, count );
536 if (name->Length > MAX_NAME_LENGTH) return STATUS_BUFFER_OVERFLOW;
538 SERVER_START_REQ( set_key_value )
542 req->namelen = name->Length;
543 wine_server_add_data( req, name->Buffer, name->Length );
544 wine_server_add_data( req, data, count );
545 ret = wine_server_call( req );
551 /******************************************************************************
552 * NtUnloadKey [NTDLL.@]
553 * ZwUnloadKey [NTDLL.@]
555 NTSTATUS WINAPI NtUnloadKey(
558 FIXME("(0x%08x) stub\n",
560 return STATUS_SUCCESS;
563 /******************************************************************************
564 * RtlFormatCurrentUserKeyPath [NTDLL.@]
566 NTSTATUS WINAPI RtlFormatCurrentUserKeyPath(
567 IN OUT PUNICODE_STRING KeyPath)
569 /* LPSTR Path = "\\REGISTRY\\USER\\S-1-5-21-0000000000-000000000-0000000000-500";*/
570 LPSTR Path = "\\REGISTRY\\USER\\.DEFAULT";
571 ANSI_STRING AnsiPath;
573 FIXME("(%p) stub\n",KeyPath);
574 RtlInitAnsiString(&AnsiPath, Path);
575 return RtlAnsiStringToUnicodeString(KeyPath, &AnsiPath, TRUE);
578 /******************************************************************************
579 * RtlOpenCurrentUser [NTDLL.@]
581 * if we return just HKEY_CURRENT_USER the advapi tries to find a remote
582 * registry (odd handle) and fails
585 DWORD WINAPI RtlOpenCurrentUser(
586 IN ACCESS_MASK DesiredAccess, /* [in] */
587 OUT PHANDLE KeyHandle) /* [out] handle of HKEY_CURRENT_USER */
589 OBJECT_ATTRIBUTES ObjectAttributes;
590 UNICODE_STRING ObjectName;
593 TRACE("(0x%08lx, %p) stub\n",DesiredAccess, KeyHandle);
595 RtlFormatCurrentUserKeyPath(&ObjectName);
596 InitializeObjectAttributes(&ObjectAttributes,&ObjectName,OBJ_CASE_INSENSITIVE,0, NULL);
597 ret = NtOpenKey(KeyHandle, DesiredAccess, &ObjectAttributes);
598 RtlFreeUnicodeString(&ObjectName);