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/debug.h"
32 #include "wine/unicode.h"
33 #include "wine/server.h"
35 #include "ntdll_misc.h"
37 WINE_DEFAULT_DEBUG_CHANNEL(reg);
39 /* maximum length of a key/value name in bytes (without terminating null) */
40 #define MAX_NAME_LENGTH ((MAX_PATH-1) * sizeof(WCHAR))
43 /******************************************************************************
44 * NtCreateKey [NTDLL.@]
45 * ZwCreateKey [NTDLL.@]
47 NTSTATUS WINAPI NtCreateKey( PHANDLE retkey, ACCESS_MASK access, const OBJECT_ATTRIBUTES *attr,
48 ULONG TitleIndex, const UNICODE_STRING *class, ULONG options,
53 TRACE( "(0x%x,%s,%s,%lx,%lx,%p)\n", attr->RootDirectory, debugstr_us(attr->ObjectName),
54 debugstr_us(class), options, access, retkey );
56 if (attr->ObjectName->Length > MAX_NAME_LENGTH) return STATUS_BUFFER_OVERFLOW;
57 if (!retkey) return STATUS_INVALID_PARAMETER;
59 SERVER_START_REQ( create_key )
61 req->parent = attr->RootDirectory;
63 req->options = options;
65 req->namelen = attr->ObjectName->Length;
66 wine_server_add_data( req, attr->ObjectName->Buffer, attr->ObjectName->Length );
67 if (class) wine_server_add_data( req, class->Buffer, class->Length );
68 if (!(ret = wine_server_call( req )))
70 *retkey = reply->hkey;
71 if (dispos) *dispos = reply->created ? REG_CREATED_NEW_KEY : REG_OPENED_EXISTING_KEY;
75 TRACE("<- 0x%04x\n", *retkey);
80 /******************************************************************************
84 * OUT PHANDLE retkey (returns 0 when failure)
85 * IN ACCESS_MASK access
86 * IN POBJECT_ATTRIBUTES attr
88 NTSTATUS WINAPI NtOpenKey( PHANDLE retkey, ACCESS_MASK access, const OBJECT_ATTRIBUTES *attr )
91 DWORD len = attr->ObjectName->Length;
93 TRACE( "(0x%x,%s,%lx,%p)\n", attr->RootDirectory,
94 debugstr_us(attr->ObjectName), access, retkey );
96 if (len > MAX_NAME_LENGTH) return STATUS_BUFFER_OVERFLOW;
97 if (!retkey) return STATUS_INVALID_PARAMETER;
99 SERVER_START_REQ( open_key )
101 req->parent = attr->RootDirectory;
102 req->access = access;
103 wine_server_add_data( req, attr->ObjectName->Buffer, len );
104 ret = wine_server_call( req );
105 *retkey = reply->hkey;
108 TRACE("<- 0x%04x\n", *retkey);
113 /******************************************************************************
114 * NtDeleteKey [NTDLL.@]
115 * ZwDeleteKey [NTDLL.@]
117 NTSTATUS WINAPI NtDeleteKey( HANDLE hkey )
121 TRACE( "(%x)\n", hkey );
123 SERVER_START_REQ( delete_key )
126 ret = wine_server_call( req );
133 /******************************************************************************
134 * NtDeleteValueKey [NTDLL.@]
135 * ZwDeleteValueKey [NTDLL.@]
137 NTSTATUS WINAPI NtDeleteValueKey( HANDLE hkey, const UNICODE_STRING *name )
141 TRACE( "(0x%x,%s)\n", hkey, debugstr_us(name) );
142 if (name->Length > MAX_NAME_LENGTH) return STATUS_BUFFER_OVERFLOW;
144 SERVER_START_REQ( delete_key_value )
147 wine_server_add_data( req, name->Buffer, name->Length );
148 ret = wine_server_call( req );
155 /******************************************************************************
158 * Implementation of NtQueryKey and NtEnumerateKey
160 static NTSTATUS enumerate_key( HANDLE handle, int index, KEY_INFORMATION_CLASS info_class,
161 void *info, DWORD length, DWORD *result_len )
170 case KeyBasicInformation: data_ptr = ((KEY_BASIC_INFORMATION *)info)->Name; break;
171 case KeyFullInformation: data_ptr = ((KEY_FULL_INFORMATION *)info)->Class; break;
172 case KeyNodeInformation: data_ptr = ((KEY_NODE_INFORMATION *)info)->Name; break;
174 FIXME( "Information class %d not implemented\n", info_class );
175 return STATUS_INVALID_PARAMETER;
177 fixed_size = (char *)data_ptr - (char *)info;
179 SERVER_START_REQ( enum_key )
183 req->info_class = info_class;
184 if (length > fixed_size) wine_server_set_reply( req, data_ptr, length - fixed_size );
185 if (!(ret = wine_server_call( req )))
189 RtlSecondsSince1970ToTime( reply->modif, (FILETIME *)&modif );
193 case KeyBasicInformation:
195 KEY_BASIC_INFORMATION keyinfo;
196 fixed_size = (char *)keyinfo.Name - (char *)&keyinfo;
197 keyinfo.LastWriteTime = modif;
198 keyinfo.TitleIndex = 0;
199 keyinfo.NameLength = reply->namelen;
200 memcpy( info, &keyinfo, min( length, fixed_size ) );
203 case KeyFullInformation:
205 KEY_FULL_INFORMATION keyinfo;
206 fixed_size = (char *)keyinfo.Class - (char *)&keyinfo;
207 keyinfo.LastWriteTime = modif;
208 keyinfo.TitleIndex = 0;
209 keyinfo.ClassLength = wine_server_reply_size(reply);
210 keyinfo.ClassOffset = keyinfo.ClassLength ? fixed_size : -1;
211 keyinfo.SubKeys = reply->subkeys;
212 keyinfo.MaxNameLen = reply->max_subkey;
213 keyinfo.MaxClassLen = reply->max_class;
214 keyinfo.Values = reply->values;
215 keyinfo.MaxValueNameLen = reply->max_value;
216 keyinfo.MaxValueDataLen = reply->max_data;
217 memcpy( info, &keyinfo, min( length, fixed_size ) );
220 case KeyNodeInformation:
222 KEY_NODE_INFORMATION keyinfo;
223 fixed_size = (char *)keyinfo.Name - (char *)&keyinfo;
224 keyinfo.LastWriteTime = modif;
225 keyinfo.TitleIndex = 0;
226 keyinfo.ClassLength = max( 0, wine_server_reply_size(reply) - reply->namelen );
227 keyinfo.ClassOffset = keyinfo.ClassLength ? fixed_size + reply->namelen : -1;
228 keyinfo.NameLength = reply->namelen;
229 memcpy( info, &keyinfo, min( length, fixed_size ) );
233 *result_len = fixed_size + reply->total;
234 if (length < *result_len) ret = STATUS_BUFFER_OVERFLOW;
243 /******************************************************************************
244 * NtEnumerateKey [NTDLL.@]
245 * ZwEnumerateKey [NTDLL.@]
248 * the name copied into the buffer is NOT 0-terminated
250 NTSTATUS WINAPI NtEnumerateKey( HANDLE handle, ULONG index, KEY_INFORMATION_CLASS info_class,
251 void *info, DWORD length, DWORD *result_len )
253 /* -1 means query key, so avoid it here */
254 if (index == (ULONG)-1) return STATUS_NO_MORE_ENTRIES;
255 return enumerate_key( handle, index, info_class, info, length, result_len );
259 /******************************************************************************
260 * NtQueryKey [NTDLL.@]
261 * ZwQueryKey [NTDLL.@]
263 NTSTATUS WINAPI NtQueryKey( HANDLE handle, KEY_INFORMATION_CLASS info_class,
264 void *info, DWORD length, DWORD *result_len )
266 return enumerate_key( handle, -1, info_class, info, length, result_len );
270 /* fill the key value info structure for a specific info class */
271 static void copy_key_value_info( KEY_VALUE_INFORMATION_CLASS info_class, void *info,
272 DWORD length, int type, int name_len, int data_len )
276 case KeyValueBasicInformation:
278 KEY_VALUE_BASIC_INFORMATION keyinfo;
279 keyinfo.TitleIndex = 0;
281 keyinfo.NameLength = name_len;
282 length = min( length, (char *)keyinfo.Name - (char *)&keyinfo );
283 memcpy( info, &keyinfo, length );
286 case KeyValueFullInformation:
288 KEY_VALUE_FULL_INFORMATION keyinfo;
289 keyinfo.TitleIndex = 0;
291 keyinfo.DataOffset = (char *)keyinfo.Name - (char *)&keyinfo + name_len;
292 keyinfo.DataLength = data_len;
293 keyinfo.NameLength = name_len;
294 length = min( length, (char *)keyinfo.Name - (char *)&keyinfo );
295 memcpy( info, &keyinfo, length );
298 case KeyValuePartialInformation:
300 KEY_VALUE_PARTIAL_INFORMATION keyinfo;
301 keyinfo.TitleIndex = 0;
303 keyinfo.DataLength = data_len;
304 length = min( length, (char *)keyinfo.Data - (char *)&keyinfo );
305 memcpy( info, &keyinfo, length );
314 /******************************************************************************
315 * NtEnumerateValueKey [NTDLL.@]
316 * ZwEnumerateValueKey [NTDLL.@]
318 NTSTATUS WINAPI NtEnumerateValueKey( HANDLE handle, ULONG index,
319 KEY_VALUE_INFORMATION_CLASS info_class,
320 void *info, DWORD length, DWORD *result_len )
326 TRACE( "(0x%x,%lu,%d,%p,%ld)\n", handle, index, info_class, info, length );
328 /* compute the length we want to retrieve */
331 case KeyValueBasicInformation: ptr = ((KEY_VALUE_BASIC_INFORMATION *)info)->Name; break;
332 case KeyValueFullInformation: ptr = ((KEY_VALUE_FULL_INFORMATION *)info)->Name; break;
333 case KeyValuePartialInformation: ptr = ((KEY_VALUE_PARTIAL_INFORMATION *)info)->Data; break;
335 FIXME( "Information class %d not implemented\n", info_class );
336 return STATUS_INVALID_PARAMETER;
338 fixed_size = (char *)ptr - (char *)info;
340 SERVER_START_REQ( enum_key_value )
344 req->info_class = info_class;
345 if (length > fixed_size) wine_server_set_reply( req, ptr, length - fixed_size );
346 if (!(ret = wine_server_call( req )))
348 copy_key_value_info( info_class, info, length, reply->type, reply->namelen,
349 wine_server_reply_size(reply) - reply->namelen );
350 *result_len = fixed_size + reply->total;
351 if (length < *result_len) ret = STATUS_BUFFER_OVERFLOW;
359 /******************************************************************************
360 * NtQueryValueKey [NTDLL.@]
361 * ZwQueryValueKey [NTDLL.@]
364 * the name in the KeyValueInformation is never set
366 NTSTATUS WINAPI NtQueryValueKey( HANDLE handle, const UNICODE_STRING *name,
367 KEY_VALUE_INFORMATION_CLASS info_class,
368 void *info, DWORD length, DWORD *result_len )
374 TRACE( "(0x%x,%s,%d,%p,%ld)\n", handle, debugstr_us(name), info_class, info, length );
376 if (name->Length > MAX_NAME_LENGTH) return STATUS_BUFFER_OVERFLOW;
378 /* compute the length we want to retrieve */
381 case KeyValueBasicInformation:
382 fixed_size = (char *)((KEY_VALUE_BASIC_INFORMATION *)info)->Name - (char *)info;
385 case KeyValueFullInformation:
386 data_ptr = (UCHAR *)((KEY_VALUE_FULL_INFORMATION *)info)->Name;
387 fixed_size = (char *)data_ptr - (char *)info;
389 case KeyValuePartialInformation:
390 data_ptr = ((KEY_VALUE_PARTIAL_INFORMATION *)info)->Data;
391 fixed_size = (char *)data_ptr - (char *)info;
394 FIXME( "Information class %d not implemented\n", info_class );
395 return STATUS_INVALID_PARAMETER;
398 SERVER_START_REQ( get_key_value )
401 wine_server_add_data( req, name->Buffer, name->Length );
402 if (length > fixed_size) wine_server_set_reply( req, data_ptr, length - fixed_size );
403 if (!(ret = wine_server_call( req )))
405 copy_key_value_info( info_class, info, length, reply->type,
406 0, wine_server_reply_size(reply) );
407 *result_len = fixed_size + reply->total;
408 if (length < *result_len) ret = STATUS_BUFFER_OVERFLOW;
416 /******************************************************************************
417 * NtFlushKey [NTDLL.@]
418 * ZwFlushKey [NTDLL.@]
420 NTSTATUS WINAPI NtFlushKey(HANDLE KeyHandle)
422 FIXME("(0x%08x) stub!\n",
427 /******************************************************************************
428 * NtLoadKey [NTDLL.@]
429 * ZwLoadKey [NTDLL.@]
431 NTSTATUS WINAPI NtLoadKey( const OBJECT_ATTRIBUTES *attr, const OBJECT_ATTRIBUTES *file )
434 dump_ObjectAttributes(attr);
435 dump_ObjectAttributes(file);
436 return STATUS_SUCCESS;
439 /******************************************************************************
440 * NtNotifyChangeKey [NTDLL.@]
441 * ZwNotifyChangeKey [NTDLL.@]
443 NTSTATUS WINAPI NtNotifyChangeKey(
446 IN PIO_APC_ROUTINE ApcRoutine OPTIONAL,
447 IN PVOID ApcContext OPTIONAL,
448 OUT PIO_STATUS_BLOCK IoStatusBlock,
449 IN ULONG CompletionFilter,
450 IN BOOLEAN Asynchroneous,
451 OUT PVOID ChangeBuffer,
453 IN BOOLEAN WatchSubtree)
455 FIXME("(0x%08x,0x%08x,%p,%p,%p,0x%08lx, 0x%08x,%p,0x%08lx,0x%08x) stub!\n",
456 KeyHandle, Event, ApcRoutine, ApcContext, IoStatusBlock, CompletionFilter,
457 Asynchroneous, ChangeBuffer, Length, WatchSubtree);
458 return STATUS_SUCCESS;
461 /******************************************************************************
462 * NtQueryMultipleValueKey [NTDLL]
463 * ZwQueryMultipleValueKey
466 NTSTATUS WINAPI NtQueryMultipleValueKey(
468 PVALENTW ListOfValuesToQuery,
470 PVOID MultipleValueInformation,
474 FIXME("(0x%08x,%p,0x%08lx,%p,0x%08lx,%p) stub!\n",
475 KeyHandle, ListOfValuesToQuery, NumberOfItems, MultipleValueInformation,
476 Length,ReturnLength);
477 return STATUS_SUCCESS;
480 /******************************************************************************
481 * NtReplaceKey [NTDLL.@]
482 * ZwReplaceKey [NTDLL.@]
484 NTSTATUS WINAPI NtReplaceKey(
485 IN POBJECT_ATTRIBUTES ObjectAttributes,
487 IN POBJECT_ATTRIBUTES ReplacedObjectAttributes)
489 FIXME("(0x%08x),stub!\n", Key);
490 dump_ObjectAttributes(ObjectAttributes);
491 dump_ObjectAttributes(ReplacedObjectAttributes);
492 return STATUS_SUCCESS;
494 /******************************************************************************
495 * NtRestoreKey [NTDLL.@]
496 * ZwRestoreKey [NTDLL.@]
498 NTSTATUS WINAPI NtRestoreKey(
503 FIXME("(0x%08x,0x%08x,0x%08lx) stub\n",
504 KeyHandle, FileHandle, RestoreFlags);
505 return STATUS_SUCCESS;
507 /******************************************************************************
508 * NtSaveKey [NTDLL.@]
509 * ZwSaveKey [NTDLL.@]
511 NTSTATUS WINAPI NtSaveKey(
513 IN HANDLE FileHandle)
515 FIXME("(0x%08x,0x%08x) stub\n",
516 KeyHandle, FileHandle);
517 return STATUS_SUCCESS;
519 /******************************************************************************
520 * NtSetInformationKey [NTDLL.@]
521 * ZwSetInformationKey [NTDLL.@]
523 NTSTATUS WINAPI NtSetInformationKey(
525 IN const int KeyInformationClass,
526 IN PVOID KeyInformation,
527 IN ULONG KeyInformationLength)
529 FIXME("(0x%08x,0x%08x,%p,0x%08lx) stub\n",
530 KeyHandle, KeyInformationClass, KeyInformation, KeyInformationLength);
531 return STATUS_SUCCESS;
535 /******************************************************************************
536 * NtSetValueKey [NTDLL.@]
537 * ZwSetValueKey [NTDLL.@]
540 * win95 does not care about count for REG_SZ and finds out the len by itself (js)
541 * NT does definitely care (aj)
543 NTSTATUS WINAPI NtSetValueKey( HANDLE hkey, const UNICODE_STRING *name, ULONG TitleIndex,
544 ULONG type, const void *data, ULONG count )
548 TRACE( "(0x%x,%s,%ld,%p,%ld)\n", hkey, debugstr_us(name), type, data, count );
550 if (name->Length > MAX_NAME_LENGTH) return STATUS_BUFFER_OVERFLOW;
552 SERVER_START_REQ( set_key_value )
556 req->namelen = name->Length;
557 wine_server_add_data( req, name->Buffer, name->Length );
558 wine_server_add_data( req, data, count );
559 ret = wine_server_call( req );
565 /******************************************************************************
566 * NtUnloadKey [NTDLL.@]
567 * ZwUnloadKey [NTDLL.@]
569 NTSTATUS WINAPI NtUnloadKey(
572 FIXME("(0x%08x) stub\n",
574 return STATUS_SUCCESS;
577 /******************************************************************************
578 * RtlFormatCurrentUserKeyPath [NTDLL.@]
580 NTSTATUS WINAPI RtlFormatCurrentUserKeyPath(
581 IN OUT PUNICODE_STRING KeyPath)
583 /* LPSTR Path = "\\REGISTRY\\USER\\S-1-5-21-0000000000-000000000-0000000000-500";*/
584 LPSTR Path = "\\REGISTRY\\USER\\.DEFAULT";
585 ANSI_STRING AnsiPath;
587 FIXME("(%p) stub\n",KeyPath);
588 RtlInitAnsiString(&AnsiPath, Path);
589 return RtlAnsiStringToUnicodeString(KeyPath, &AnsiPath, TRUE);
592 /******************************************************************************
593 * RtlOpenCurrentUser [NTDLL.@]
595 * if we return just HKEY_CURRENT_USER the advapi tries to find a remote
596 * registry (odd handle) and fails
599 DWORD WINAPI RtlOpenCurrentUser(
600 IN ACCESS_MASK DesiredAccess, /* [in] */
601 OUT PHANDLE KeyHandle) /* [out] handle of HKEY_CURRENT_USER */
603 OBJECT_ATTRIBUTES ObjectAttributes;
604 UNICODE_STRING ObjectName;
607 TRACE("(0x%08lx, %p) stub\n",DesiredAccess, KeyHandle);
609 RtlFormatCurrentUserKeyPath(&ObjectName);
610 InitializeObjectAttributes(&ObjectAttributes,&ObjectName,OBJ_CASE_INSENSITIVE,0, NULL);
611 ret = NtOpenKey(KeyHandle, DesiredAccess, &ObjectAttributes);
612 RtlFreeUnicodeString(&ObjectName);