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
);