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
14 #include "debugtools.h"
17 #include "wine/unicode.h"
20 #include "ntdll_misc.h"
22 DEFAULT_DEBUG_CHANNEL(reg);
24 static const WCHAR root_name[] = { '\\','R','e','g','i','s','t','r','y','\\',0 };
25 static const UNICODE_STRING root_path =
27 sizeof(root_name)-sizeof(WCHAR), /* Length */
28 sizeof(root_name), /* MaximumLength */
29 (LPWSTR)root_name /* Buffer */
32 /* maximum length of a key/value name in bytes (without terminating null) */
33 #define MAX_NAME_LENGTH ((MAX_PATH-1) * sizeof(WCHAR))
36 /* copy a key name into the request buffer */
37 static inline NTSTATUS copy_nameU( LPWSTR Dest, const UNICODE_STRING *name, UINT max )
39 if (name->Length >= max) return STATUS_BUFFER_OVERFLOW;
40 if (name->Length) memcpy( Dest, name->Buffer, name->Length );
41 Dest[name->Length / sizeof(WCHAR)] = 0;
42 return STATUS_SUCCESS;
46 /******************************************************************************
50 NTSTATUS WINAPI NtCreateKey( PHANDLE retkey, ACCESS_MASK access, const OBJECT_ATTRIBUTES *attr,
51 ULONG TitleIndex, const UNICODE_STRING *class, ULONG options,
55 DWORD len = attr->ObjectName->Length;
57 TRACE( "(0x%x,%s,%s,%lx,%lx,%p)\n", attr->RootDirectory, debugstr_us(attr->ObjectName),
58 debugstr_us(class), options, access, retkey );
60 if (len > MAX_NAME_LENGTH) return STATUS_BUFFER_OVERFLOW;
61 len += sizeof(WCHAR); /* for storing name length */
65 if (len > REQUEST_MAX_VAR_SIZE) return STATUS_BUFFER_OVERFLOW;
67 if (!retkey) return STATUS_INVALID_PARAMETER;
71 struct create_key_request *req = server_alloc_req( sizeof(*req), len );
72 WCHAR *data = server_data_ptr(req);
74 req->parent = attr->RootDirectory;
76 req->options = options;
79 *data++ = attr->ObjectName->Length;
80 memcpy( data, attr->ObjectName->Buffer, attr->ObjectName->Length );
81 if (class) memcpy( (char *)data + attr->ObjectName->Length, class->Buffer, class->Length );
82 if (!(ret = server_call_noerr( REQ_CREATE_KEY )))
85 if (dispos) *dispos = req->created ? REG_CREATED_NEW_KEY : REG_OPENED_EXISTING_KEY;
93 /******************************************************************************
94 * NtOpenKey [NTDLL.129]
96 * OUT PHANDLE retkey (returns 0 when failure)
97 * IN ACCESS_MASK access
98 * IN POBJECT_ATTRIBUTES attr
100 NTSTATUS WINAPI NtOpenKey( PHANDLE retkey, ACCESS_MASK access, const OBJECT_ATTRIBUTES *attr )
103 DWORD len = attr->ObjectName->Length;
105 TRACE( "(0x%x,%s,%lx,%p)\n", attr->RootDirectory,
106 debugstr_us(attr->ObjectName), access, retkey );
108 if (len > MAX_NAME_LENGTH) return STATUS_BUFFER_OVERFLOW;
109 if (!retkey) return STATUS_INVALID_PARAMETER;
114 struct open_key_request *req = server_alloc_req( sizeof(*req), len );
115 req->parent = attr->RootDirectory;
116 req->access = access;
117 memcpy( server_data_ptr(req), attr->ObjectName->Buffer, len );
118 if (!(ret = server_call_noerr( REQ_OPEN_KEY ))) *retkey = req->hkey;
125 /******************************************************************************
126 * NtDeleteKey [NTDLL]
129 NTSTATUS WINAPI NtDeleteKey( HANDLE hkey )
133 TRACE( "(%x)\n", hkey );
137 struct delete_key_request *req = server_alloc_req( sizeof(*req), 0 );
139 ret = server_call_noerr( REQ_DELETE_KEY );
146 /******************************************************************************
147 * NtDeleteValueKey [NTDLL]
150 NTSTATUS WINAPI NtDeleteValueKey( HANDLE hkey, const UNICODE_STRING *name )
154 TRACE( "(0x%x,%s)\n", hkey, debugstr_us(name) );
155 if (name->Length > MAX_NAME_LENGTH) return STATUS_BUFFER_OVERFLOW;
159 struct delete_key_value_request *req = server_alloc_req( sizeof(*req), name->Length );
162 memcpy( server_data_ptr(req), name->Buffer, name->Length );
163 ret = server_call_noerr( REQ_DELETE_KEY_VALUE );
170 /******************************************************************************
173 * Helper function for NtQueryKey and NtEnumerateKey
175 static NTSTATUS fill_key_info( KEY_INFORMATION_CLASS info_class, void *info, DWORD length,
176 DWORD *result_len, const struct enum_key_request *req )
178 WCHAR *name_ptr = server_data_ptr(req);
179 int name_size = *name_ptr++;
180 WCHAR *class_ptr = (WCHAR *)((char *)name_ptr + name_size);
181 int class_size = server_data_size(req) - sizeof(WCHAR) - name_size;
185 RtlSecondsSince1970ToTime( req->modif, &modif );
189 case KeyBasicInformation:
191 KEY_BASIC_INFORMATION keyinfo;
192 fixed_size = sizeof(keyinfo) - sizeof(keyinfo.Name);
193 keyinfo.LastWriteTime = modif;
194 keyinfo.TitleIndex = 0;
195 keyinfo.NameLength = name_size;
196 memcpy( info, &keyinfo, min( length, fixed_size ) );
200 case KeyFullInformation:
202 KEY_FULL_INFORMATION keyinfo;
203 fixed_size = sizeof(keyinfo) - sizeof(keyinfo.Class);
204 keyinfo.LastWriteTime = modif;
205 keyinfo.TitleIndex = 0;
206 keyinfo.ClassLength = class_size;
207 keyinfo.ClassOffset = keyinfo.ClassLength ? fixed_size : -1;
208 keyinfo.SubKeys = req->subkeys;
209 keyinfo.MaxNameLen = req->max_subkey;
210 keyinfo.MaxClassLen = req->max_class;
211 keyinfo.Values = req->values;
212 keyinfo.MaxValueNameLen = req->max_value;
213 keyinfo.MaxValueDataLen = req->max_data;
214 memcpy( info, &keyinfo, min( length, fixed_size ) );
218 case KeyNodeInformation:
220 KEY_NODE_INFORMATION keyinfo;
221 fixed_size = sizeof(keyinfo) - sizeof(keyinfo.Name);
222 keyinfo.LastWriteTime = modif;
223 keyinfo.TitleIndex = 0;
224 keyinfo.ClassLength = class_size;
225 keyinfo.ClassOffset = fixed_size + name_size;
226 if (!keyinfo.ClassLength || keyinfo.ClassOffset > length) keyinfo.ClassOffset = -1;
227 keyinfo.NameLength = name_size;
228 memcpy( info, &keyinfo, min( length, fixed_size ) );
232 FIXME("Information class not implemented\n");
233 return STATUS_INVALID_PARAMETER;
236 *result_len = fixed_size + name_size + class_size;
237 if (length <= fixed_size) return STATUS_BUFFER_OVERFLOW;
238 length -= fixed_size;
243 memcpy( (char *)info + fixed_size, name_ptr, min(length,name_size) );
244 if (length < name_size) return STATUS_BUFFER_OVERFLOW;
251 memcpy( (char *)info + fixed_size + name_size, class_ptr, min(length,class_size) );
252 if (length < class_size) return STATUS_BUFFER_OVERFLOW;
254 return STATUS_SUCCESS;
259 /******************************************************************************
260 * NtEnumerateKey [NTDLL]
264 * the name copied into the buffer is NOT 0-terminated
266 NTSTATUS WINAPI NtEnumerateKey( HANDLE handle, ULONG index, KEY_INFORMATION_CLASS info_class,
267 void *info, DWORD length, DWORD *result_len )
271 /* -1 means query key, so avoid it here */
272 if (index == (ULONG)-1) return STATUS_NO_MORE_ENTRIES;
276 struct enum_key_request *req = server_alloc_req( sizeof(*req), REQUEST_MAX_VAR_SIZE );
279 req->full = (info_class == KeyFullInformation);
280 if (!(ret = server_call_noerr( REQ_ENUM_KEY )))
282 ret = fill_key_info( info_class, info, length, result_len, req );
290 /******************************************************************************
294 NTSTATUS WINAPI NtQueryKey( HANDLE handle, KEY_INFORMATION_CLASS info_class,
295 void *info, DWORD length, DWORD *result_len )
301 struct enum_key_request *req = server_alloc_req( sizeof(*req), REQUEST_MAX_VAR_SIZE );
304 req->full = (info_class == KeyFullInformation);
305 if (!(ret = server_call_noerr( REQ_ENUM_KEY )))
307 ret = fill_key_info( info_class, info, length, result_len, req );
314 /******************************************************************************
315 * NtEnumerateValueKey [NTDLL]
316 * ZwEnumerateValueKey
318 NTSTATUS WINAPI NtEnumerateValueKey(
321 KEY_VALUE_INFORMATION_CLASS KeyInformationClass,
322 PVOID KeyInformation,
326 struct enum_key_value_request *req = get_req_buffer();
330 TRACE("(0x%08x,0x%08lx,0x%08x,%p,0x%08lx,%p)\n",
331 KeyHandle, Index, KeyInformationClass, KeyInformation, Length, ResultLength);
333 req->hkey = KeyHandle;
335 if ((ret = server_call_noerr(REQ_ENUM_KEY_VALUE)) != STATUS_SUCCESS) return ret;
337 switch (KeyInformationClass)
339 case KeyBasicInformation:
341 PKEY_VALUE_BASIC_INFORMATION kbi = KeyInformation;
343 NameLength = strlenW(req->name) * sizeof(WCHAR);
344 *ResultLength = sizeof(KEY_VALUE_BASIC_INFORMATION) - sizeof(WCHAR) + NameLength;
345 if (*ResultLength > Length) return STATUS_BUFFER_TOO_SMALL;
348 kbi->Type = req->type;
349 kbi->NameLength = NameLength;
350 memcpy(kbi->Name, req->name, kbi->NameLength);
353 case KeyValueFullInformation:
355 PKEY_VALUE_FULL_INFORMATION kbi = KeyInformation;
358 NameLength = strlenW(req->name) * sizeof(WCHAR);
359 DataOffset = sizeof(KEY_VALUE_FULL_INFORMATION) - sizeof(WCHAR) + NameLength;
360 *ResultLength = DataOffset + req->len;
362 if (*ResultLength > Length) return STATUS_BUFFER_TOO_SMALL;
365 kbi->Type = req->type;
366 kbi->DataOffset = DataOffset;
367 kbi->DataLength = req->len;
368 kbi->NameLength = NameLength;
369 memcpy(kbi->Name, req->name, kbi->NameLength);
370 memcpy(((LPBYTE)kbi) + DataOffset, req->data, req->len);
373 case KeyValuePartialInformation:
375 PKEY_VALUE_PARTIAL_INFORMATION kbi = KeyInformation;
377 *ResultLength = sizeof(KEY_VALUE_PARTIAL_INFORMATION) - sizeof(WCHAR) + req->len;
379 if (*ResultLength > Length) return STATUS_BUFFER_TOO_SMALL;
382 kbi->Type = req->type;
383 kbi->DataLength = req->len;
384 memcpy(kbi->Data, req->data, req->len);
388 FIXME("not implemented\n");
390 return STATUS_SUCCESS;
393 /******************************************************************************
397 NTSTATUS WINAPI NtFlushKey(HANDLE KeyHandle)
399 FIXME("(0x%08x) stub!\n",
404 /******************************************************************************
408 NTSTATUS WINAPI NtLoadKey( const OBJECT_ATTRIBUTES *attr, const OBJECT_ATTRIBUTES *file )
411 dump_ObjectAttributes(attr);
412 dump_ObjectAttributes(file);
413 return STATUS_SUCCESS;
416 /******************************************************************************
417 * NtNotifyChangeKey [NTDLL]
420 NTSTATUS WINAPI NtNotifyChangeKey(
423 IN PIO_APC_ROUTINE ApcRoutine OPTIONAL,
424 IN PVOID ApcContext OPTIONAL,
425 OUT PIO_STATUS_BLOCK IoStatusBlock,
426 IN ULONG CompletionFilter,
427 IN BOOLEAN Asynchroneous,
428 OUT PVOID ChangeBuffer,
430 IN BOOLEAN WatchSubtree)
432 FIXME("(0x%08x,0x%08x,%p,%p,%p,0x%08lx, 0x%08x,%p,0x%08lx,0x%08x) stub!\n",
433 KeyHandle, Event, ApcRoutine, ApcContext, IoStatusBlock, CompletionFilter,
434 Asynchroneous, ChangeBuffer, Length, WatchSubtree);
435 return STATUS_SUCCESS;
438 /******************************************************************************
439 * NtQueryMultipleValueKey [NTDLL]
440 * ZwQueryMultipleValueKey
443 NTSTATUS WINAPI NtQueryMultipleValueKey(
445 PVALENTW ListOfValuesToQuery,
447 PVOID MultipleValueInformation,
451 FIXME("(0x%08x,%p,0x%08lx,%p,0x%08lx,%p) stub!\n",
452 KeyHandle, ListOfValuesToQuery, NumberOfItems, MultipleValueInformation,
453 Length,ReturnLength);
454 return STATUS_SUCCESS;
457 /******************************************************************************
458 * NtQueryValueKey [NTDLL]
462 * the name in the KeyValueInformation is never set
464 NTSTATUS WINAPI NtQueryValueKey( HANDLE handle, const UNICODE_STRING *name,
465 KEY_VALUE_INFORMATION_CLASS info_class,
466 void *info, DWORD length, DWORD *result_len )
470 int fixed_size = 0, data_len = 0, offset = 0, type = 0, total_len = 0;
472 TRACE( "(0x%x,%s,%d,%p,%ld)\n", handle, debugstr_us(name), info_class, info, length );
474 if (name->Length > MAX_NAME_LENGTH) return STATUS_BUFFER_OVERFLOW;
476 /* compute the length we want to retrieve */
479 case KeyValueBasicInformation:
480 fixed_size = sizeof(KEY_VALUE_BASIC_INFORMATION) - sizeof(WCHAR);
483 case KeyValueFullInformation:
484 fixed_size = sizeof(KEY_VALUE_FULL_INFORMATION) - sizeof(WCHAR);
485 data_ptr = (char *)info + fixed_size;
487 case KeyValuePartialInformation:
488 fixed_size = sizeof(KEY_VALUE_PARTIAL_INFORMATION) - sizeof(UCHAR);
489 data_ptr = (char *)info + fixed_size;
492 FIXME( "Information class %d not implemented\n", info_class );
493 return STATUS_INVALID_PARAMETER;
495 if (data_ptr && length > fixed_size) data_len = length - fixed_size;
499 size_t reqlen = min( data_len, REQUEST_MAX_VAR_SIZE );
500 reqlen = max( reqlen, name->Length + sizeof(WCHAR) );
504 struct get_key_value_request *req = server_alloc_req( sizeof(*req), reqlen );
505 WCHAR *nameptr = server_data_ptr(req);
508 req->offset = offset;
509 *nameptr++ = name->Length;
510 memcpy( nameptr, name->Buffer, name->Length );
512 if (!(ret = server_call_noerr( REQ_GET_KEY_VALUE )))
514 size_t size = min( server_data_size(req), data_len );
516 total_len = req->len;
519 memcpy( data_ptr + offset, server_data_ptr(req), size );
527 } while (data_len && offset < total_len);
529 *result_len = total_len + fixed_size;
531 if (offset < total_len) ret = STATUS_BUFFER_OVERFLOW;
532 if (length < fixed_size) ret = STATUS_BUFFER_OVERFLOW;
536 case KeyValueBasicInformation:
538 KEY_VALUE_BASIC_INFORMATION keyinfo;
539 keyinfo.TitleIndex = 0;
541 keyinfo.NameLength = 0;
542 memcpy( info, &keyinfo, min(fixed_size,length) );
545 case KeyValueFullInformation:
547 KEY_VALUE_FULL_INFORMATION keyinfo;
548 keyinfo.TitleIndex = 0;
550 keyinfo.DataOffset = fixed_size;
551 keyinfo.DataLength = total_len;
552 keyinfo.NameLength = 0;
553 memcpy( info, &keyinfo, min(fixed_size,length) );
556 case KeyValuePartialInformation:
558 KEY_VALUE_PARTIAL_INFORMATION keyinfo;
559 keyinfo.TitleIndex = 0;
561 keyinfo.DataLength = total_len;
562 memcpy( info, &keyinfo, min(fixed_size,length) );
571 /******************************************************************************
572 * NtReplaceKey [NTDLL]
575 NTSTATUS WINAPI NtReplaceKey(
576 IN POBJECT_ATTRIBUTES ObjectAttributes,
578 IN POBJECT_ATTRIBUTES ReplacedObjectAttributes)
580 FIXME("(0x%08x),stub!\n", Key);
581 dump_ObjectAttributes(ObjectAttributes);
582 dump_ObjectAttributes(ReplacedObjectAttributes);
583 return STATUS_SUCCESS;
585 /******************************************************************************
586 * NtRestoreKey [NTDLL]
589 NTSTATUS WINAPI NtRestoreKey(
594 FIXME("(0x%08x,0x%08x,0x%08lx) stub\n",
595 KeyHandle, FileHandle, RestoreFlags);
596 return STATUS_SUCCESS;
598 /******************************************************************************
602 NTSTATUS WINAPI NtSaveKey(
604 IN HANDLE FileHandle)
606 FIXME("(0x%08x,0x%08x) stub\n",
607 KeyHandle, FileHandle);
608 return STATUS_SUCCESS;
610 /******************************************************************************
611 * NtSetInformationKey [NTDLL]
612 * ZwSetInformationKey
614 NTSTATUS WINAPI NtSetInformationKey(
616 IN const int KeyInformationClass,
617 IN PVOID KeyInformation,
618 IN ULONG KeyInformationLength)
620 FIXME("(0x%08x,0x%08x,%p,0x%08lx) stub\n",
621 KeyHandle, KeyInformationClass, KeyInformation, KeyInformationLength);
622 return STATUS_SUCCESS;
626 /******************************************************************************
627 * NtSetValueKey [NTDLL]
631 * win95 does not care about count for REG_SZ and finds out the len by itself (js)
632 * NT does definitely care (aj)
634 NTSTATUS WINAPI NtSetValueKey( HANDLE hkey, const UNICODE_STRING *name, ULONG TitleIndex,
635 ULONG type, const void *data, ULONG count )
640 TRACE( "(0x%x,%s,%ld,%p,%ld)\n", hkey, debugstr_us(name), type, data, count );
642 if (name->Length > MAX_NAME_LENGTH) return STATUS_BUFFER_OVERFLOW;
644 namelen = name->Length + sizeof(WCHAR); /* for storing length */
649 ULONG len = count - pos;
650 if (len > REQUEST_MAX_VAR_SIZE - namelen) len = REQUEST_MAX_VAR_SIZE - namelen;
654 struct set_key_value_request *req = server_alloc_req( sizeof(*req), namelen + len );
655 WCHAR *name_ptr = server_data_ptr(req);
661 *name_ptr++ = name->Length;
662 memcpy( name_ptr, name->Buffer, name->Length );
663 memcpy( (char *)name_ptr + name->Length, (char *)data + pos, len );
665 ret = server_call_noerr( REQ_SET_KEY_VALUE );
668 } while (!ret && pos < count);
672 /******************************************************************************
673 * NtUnloadKey [NTDLL]
676 NTSTATUS WINAPI NtUnloadKey(
679 FIXME("(0x%08x) stub\n",
681 return STATUS_SUCCESS;
684 /******************************************************************************
685 * RtlFormatCurrentUserKeyPath [NTDLL.371]
687 NTSTATUS WINAPI RtlFormatCurrentUserKeyPath(
688 IN OUT PUNICODE_STRING KeyPath)
690 /* LPSTR Path = "\\REGISTRY\\USER\\S-1-5-21-0000000000-000000000-0000000000-500";*/
691 LPSTR Path = "\\REGISTRY\\USER\\.DEFAULT";
692 ANSI_STRING AnsiPath;
694 FIXME("(%p) stub\n",KeyPath);
695 RtlInitAnsiString(&AnsiPath, Path);
696 return RtlAnsiStringToUnicodeString(KeyPath, &AnsiPath, TRUE);
699 /******************************************************************************
700 * RtlOpenCurrentUser [NTDLL]
702 * if we return just HKEY_CURRENT_USER the advapi try's to find a remote
703 * registry (odd handle) and fails
706 DWORD WINAPI RtlOpenCurrentUser(
707 IN ACCESS_MASK DesiredAccess, /* [in] */
708 OUT PHANDLE KeyHandle) /* [out] handle of HKEY_CURRENT_USER */
710 OBJECT_ATTRIBUTES ObjectAttributes;
711 UNICODE_STRING ObjectName;
714 TRACE("(0x%08lx, %p) stub\n",DesiredAccess, KeyHandle);
716 RtlFormatCurrentUserKeyPath(&ObjectName);
717 InitializeObjectAttributes(&ObjectAttributes,&ObjectName,OBJ_CASE_INSENSITIVE,0, NULL);
718 ret = NtOpenKey(KeyHandle, DesiredAccess, &ObjectAttributes);
719 RtlFreeUnicodeString(&ObjectName);