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"
36 #include "wine/unicode.h"
37 #include "wine/library.h"
38 #include "wine/server.h"
43 #include "ntdll_misc.h"
44 #include "wine/debug.h"
46 WINE_DEFAULT_DEBUG_CHANNEL(reg
);
48 /* maximum length of a key/value name in bytes (without terminating null) */
49 #define MAX_NAME_LENGTH ((MAX_PATH-1) * sizeof(WCHAR))
52 /******************************************************************************
53 * NtCreateKey [NTDLL.@]
54 * ZwCreateKey [NTDLL.@]
56 NTSTATUS WINAPI
NtCreateKey( PHKEY retkey
, ACCESS_MASK access
, const OBJECT_ATTRIBUTES
*attr
,
57 ULONG TitleIndex
, const UNICODE_STRING
*class, ULONG options
,
62 TRACE( "(%p,%s,%s,%lx,%lx,%p)\n", attr
->RootDirectory
, debugstr_us(attr
->ObjectName
),
63 debugstr_us(class), options
, access
, retkey
);
65 if (attr
->ObjectName
->Length
> MAX_NAME_LENGTH
) return STATUS_BUFFER_OVERFLOW
;
66 if (!retkey
) return STATUS_INVALID_PARAMETER
;
68 SERVER_START_REQ( create_key
)
70 req
->parent
= attr
->RootDirectory
;
72 req
->options
= options
;
74 req
->namelen
= attr
->ObjectName
->Length
;
75 wine_server_add_data( req
, attr
->ObjectName
->Buffer
, attr
->ObjectName
->Length
);
76 if (class) wine_server_add_data( req
, class->Buffer
, class->Length
);
77 if (!(ret
= wine_server_call( req
)))
79 *retkey
= reply
->hkey
;
80 if (dispos
) *dispos
= reply
->created
? REG_CREATED_NEW_KEY
: REG_OPENED_EXISTING_KEY
;
84 TRACE("<- %p\n", *retkey
);
89 /******************************************************************************
93 * OUT PHKEY retkey (returns 0 when failure)
94 * IN ACCESS_MASK access
95 * IN POBJECT_ATTRIBUTES attr
97 NTSTATUS WINAPI
NtOpenKey( PHKEY retkey
, ACCESS_MASK access
, const OBJECT_ATTRIBUTES
*attr
)
100 DWORD len
= attr
->ObjectName
->Length
;
102 TRACE( "(%p,%s,%lx,%p)\n", attr
->RootDirectory
,
103 debugstr_us(attr
->ObjectName
), access
, retkey
);
105 if (len
> MAX_NAME_LENGTH
) return STATUS_BUFFER_OVERFLOW
;
106 if (!retkey
) return STATUS_INVALID_PARAMETER
;
108 SERVER_START_REQ( open_key
)
110 req
->parent
= attr
->RootDirectory
;
111 req
->access
= access
;
112 wine_server_add_data( req
, attr
->ObjectName
->Buffer
, len
);
113 ret
= wine_server_call( req
);
114 *retkey
= reply
->hkey
;
117 TRACE("<- %p\n", *retkey
);
122 /******************************************************************************
123 * NtDeleteKey [NTDLL.@]
124 * ZwDeleteKey [NTDLL.@]
126 NTSTATUS WINAPI
NtDeleteKey( HKEY hkey
)
130 TRACE( "(%p)\n", hkey
);
132 SERVER_START_REQ( delete_key
)
135 ret
= wine_server_call( req
);
142 /******************************************************************************
143 * NtDeleteValueKey [NTDLL.@]
144 * ZwDeleteValueKey [NTDLL.@]
146 NTSTATUS WINAPI
NtDeleteValueKey( HKEY hkey
, const UNICODE_STRING
*name
)
150 TRACE( "(%p,%s)\n", hkey
, debugstr_us(name
) );
151 if (name
->Length
> MAX_NAME_LENGTH
) return STATUS_BUFFER_OVERFLOW
;
153 SERVER_START_REQ( delete_key_value
)
156 wine_server_add_data( req
, name
->Buffer
, name
->Length
);
157 ret
= wine_server_call( req
);
164 /******************************************************************************
167 * Implementation of NtQueryKey and NtEnumerateKey
169 static NTSTATUS
enumerate_key( HKEY handle
, int index
, KEY_INFORMATION_CLASS info_class
,
170 void *info
, DWORD length
, DWORD
*result_len
)
179 case KeyBasicInformation
: data_ptr
= ((KEY_BASIC_INFORMATION
*)info
)->Name
; break;
180 case KeyFullInformation
: data_ptr
= ((KEY_FULL_INFORMATION
*)info
)->Class
; break;
181 case KeyNodeInformation
: data_ptr
= ((KEY_NODE_INFORMATION
*)info
)->Name
; break;
183 FIXME( "Information class %d not implemented\n", info_class
);
184 return STATUS_INVALID_PARAMETER
;
186 fixed_size
= (char *)data_ptr
- (char *)info
;
188 SERVER_START_REQ( enum_key
)
192 req
->info_class
= info_class
;
193 if (length
> fixed_size
) wine_server_set_reply( req
, data_ptr
, length
- fixed_size
);
194 if (!(ret
= wine_server_call( req
)))
198 RtlSecondsSince1970ToTime( reply
->modif
, &modif
);
202 case KeyBasicInformation
:
204 KEY_BASIC_INFORMATION keyinfo
;
205 fixed_size
= (char *)keyinfo
.Name
- (char *)&keyinfo
;
206 keyinfo
.LastWriteTime
= modif
;
207 keyinfo
.TitleIndex
= 0;
208 keyinfo
.NameLength
= reply
->namelen
;
209 memcpy( info
, &keyinfo
, min( length
, fixed_size
) );
212 case KeyFullInformation
:
214 KEY_FULL_INFORMATION keyinfo
;
215 fixed_size
= (char *)keyinfo
.Class
- (char *)&keyinfo
;
216 keyinfo
.LastWriteTime
= modif
;
217 keyinfo
.TitleIndex
= 0;
218 keyinfo
.ClassLength
= wine_server_reply_size(reply
);
219 keyinfo
.ClassOffset
= keyinfo
.ClassLength
? fixed_size
: -1;
220 keyinfo
.SubKeys
= reply
->subkeys
;
221 keyinfo
.MaxNameLen
= reply
->max_subkey
;
222 keyinfo
.MaxClassLen
= reply
->max_class
;
223 keyinfo
.Values
= reply
->values
;
224 keyinfo
.MaxValueNameLen
= reply
->max_value
;
225 keyinfo
.MaxValueDataLen
= reply
->max_data
;
226 memcpy( info
, &keyinfo
, min( length
, fixed_size
) );
229 case KeyNodeInformation
:
231 KEY_NODE_INFORMATION keyinfo
;
232 fixed_size
= (char *)keyinfo
.Name
- (char *)&keyinfo
;
233 keyinfo
.LastWriteTime
= modif
;
234 keyinfo
.TitleIndex
= 0;
235 keyinfo
.ClassLength
= max( 0, wine_server_reply_size(reply
) - reply
->namelen
);
236 keyinfo
.ClassOffset
= keyinfo
.ClassLength
? fixed_size
+ reply
->namelen
: -1;
237 keyinfo
.NameLength
= reply
->namelen
;
238 memcpy( info
, &keyinfo
, min( length
, fixed_size
) );
242 *result_len
= fixed_size
+ reply
->total
;
243 if (length
< *result_len
) ret
= STATUS_BUFFER_OVERFLOW
;
252 /******************************************************************************
253 * NtEnumerateKey [NTDLL.@]
254 * ZwEnumerateKey [NTDLL.@]
257 * the name copied into the buffer is NOT 0-terminated
259 NTSTATUS WINAPI
NtEnumerateKey( HKEY handle
, ULONG index
, KEY_INFORMATION_CLASS info_class
,
260 void *info
, DWORD length
, DWORD
*result_len
)
262 /* -1 means query key, so avoid it here */
263 if (index
== (ULONG
)-1) return STATUS_NO_MORE_ENTRIES
;
264 return enumerate_key( handle
, index
, info_class
, info
, length
, result_len
);
268 /******************************************************************************
269 * NtQueryKey [NTDLL.@]
270 * ZwQueryKey [NTDLL.@]
272 NTSTATUS WINAPI
NtQueryKey( HKEY handle
, KEY_INFORMATION_CLASS info_class
,
273 void *info
, DWORD length
, DWORD
*result_len
)
275 return enumerate_key( handle
, -1, info_class
, info
, length
, result_len
);
279 /* fill the key value info structure for a specific info class */
280 static void copy_key_value_info( KEY_VALUE_INFORMATION_CLASS info_class
, void *info
,
281 DWORD length
, int type
, int name_len
, int data_len
)
285 case KeyValueBasicInformation
:
287 KEY_VALUE_BASIC_INFORMATION keyinfo
;
288 keyinfo
.TitleIndex
= 0;
290 keyinfo
.NameLength
= name_len
;
291 length
= min( length
, (char *)keyinfo
.Name
- (char *)&keyinfo
);
292 memcpy( info
, &keyinfo
, length
);
295 case KeyValueFullInformation
:
297 KEY_VALUE_FULL_INFORMATION keyinfo
;
298 keyinfo
.TitleIndex
= 0;
300 keyinfo
.DataOffset
= (char *)keyinfo
.Name
- (char *)&keyinfo
+ name_len
;
301 keyinfo
.DataLength
= data_len
;
302 keyinfo
.NameLength
= name_len
;
303 length
= min( length
, (char *)keyinfo
.Name
- (char *)&keyinfo
);
304 memcpy( info
, &keyinfo
, length
);
307 case KeyValuePartialInformation
:
309 KEY_VALUE_PARTIAL_INFORMATION keyinfo
;
310 keyinfo
.TitleIndex
= 0;
312 keyinfo
.DataLength
= data_len
;
313 length
= min( length
, (char *)keyinfo
.Data
- (char *)&keyinfo
);
314 memcpy( info
, &keyinfo
, length
);
323 /******************************************************************************
324 * NtEnumerateValueKey [NTDLL.@]
325 * ZwEnumerateValueKey [NTDLL.@]
327 NTSTATUS WINAPI
NtEnumerateValueKey( HKEY handle
, ULONG index
,
328 KEY_VALUE_INFORMATION_CLASS info_class
,
329 void *info
, DWORD length
, DWORD
*result_len
)
335 TRACE( "(%p,%lu,%d,%p,%ld)\n", handle
, index
, info_class
, info
, length
);
337 /* compute the length we want to retrieve */
340 case KeyValueBasicInformation
: ptr
= ((KEY_VALUE_BASIC_INFORMATION
*)info
)->Name
; break;
341 case KeyValueFullInformation
: ptr
= ((KEY_VALUE_FULL_INFORMATION
*)info
)->Name
; break;
342 case KeyValuePartialInformation
: ptr
= ((KEY_VALUE_PARTIAL_INFORMATION
*)info
)->Data
; break;
344 FIXME( "Information class %d not implemented\n", info_class
);
345 return STATUS_INVALID_PARAMETER
;
347 fixed_size
= (char *)ptr
- (char *)info
;
349 SERVER_START_REQ( enum_key_value
)
353 req
->info_class
= info_class
;
354 if (length
> fixed_size
) wine_server_set_reply( req
, ptr
, length
- fixed_size
);
355 if (!(ret
= wine_server_call( req
)))
357 copy_key_value_info( info_class
, info
, length
, reply
->type
, reply
->namelen
,
358 wine_server_reply_size(reply
) - reply
->namelen
);
359 *result_len
= fixed_size
+ reply
->total
;
360 if (length
< *result_len
) ret
= STATUS_BUFFER_OVERFLOW
;
368 /******************************************************************************
369 * NtQueryValueKey [NTDLL.@]
370 * ZwQueryValueKey [NTDLL.@]
373 * the name in the KeyValueInformation is never set
375 NTSTATUS WINAPI
NtQueryValueKey( HKEY handle
, const UNICODE_STRING
*name
,
376 KEY_VALUE_INFORMATION_CLASS info_class
,
377 void *info
, DWORD length
, DWORD
*result_len
)
383 TRACE( "(%p,%s,%d,%p,%ld)\n", handle
, debugstr_us(name
), info_class
, info
, length
);
385 if (name
->Length
> MAX_NAME_LENGTH
) return STATUS_BUFFER_OVERFLOW
;
387 /* compute the length we want to retrieve */
390 case KeyValueBasicInformation
:
391 fixed_size
= (char *)((KEY_VALUE_BASIC_INFORMATION
*)info
)->Name
- (char *)info
;
394 case KeyValueFullInformation
:
395 data_ptr
= (UCHAR
*)((KEY_VALUE_FULL_INFORMATION
*)info
)->Name
;
396 fixed_size
= (char *)data_ptr
- (char *)info
;
398 case KeyValuePartialInformation
:
399 data_ptr
= ((KEY_VALUE_PARTIAL_INFORMATION
*)info
)->Data
;
400 fixed_size
= (char *)data_ptr
- (char *)info
;
403 FIXME( "Information class %d not implemented\n", info_class
);
404 return STATUS_INVALID_PARAMETER
;
407 SERVER_START_REQ( get_key_value
)
410 wine_server_add_data( req
, name
->Buffer
, name
->Length
);
411 if (length
> fixed_size
) wine_server_set_reply( req
, data_ptr
, length
- fixed_size
);
412 if (!(ret
= wine_server_call( req
)))
414 copy_key_value_info( info_class
, info
, length
, reply
->type
,
415 0, wine_server_reply_size(reply
) );
416 *result_len
= fixed_size
+ reply
->total
;
417 if (length
< *result_len
) ret
= STATUS_BUFFER_OVERFLOW
;
425 /******************************************************************************
426 * NtFlushKey [NTDLL.@]
427 * ZwFlushKey [NTDLL.@]
429 NTSTATUS WINAPI
NtFlushKey(HKEY KeyHandle
)
431 FIXME("(%p) stub!\n",
436 /******************************************************************************
437 * NtLoadKey [NTDLL.@]
438 * ZwLoadKey [NTDLL.@]
440 NTSTATUS WINAPI
NtLoadKey( const OBJECT_ATTRIBUTES
*attr
, const OBJECT_ATTRIBUTES
*file
)
443 dump_ObjectAttributes(attr
);
444 dump_ObjectAttributes(file
);
445 return STATUS_SUCCESS
;
448 /******************************************************************************
449 * NtNotifyChangeKey [NTDLL.@]
450 * ZwNotifyChangeKey [NTDLL.@]
452 NTSTATUS WINAPI
NtNotifyChangeKey(
455 IN PIO_APC_ROUTINE ApcRoutine OPTIONAL
,
456 IN PVOID ApcContext OPTIONAL
,
457 OUT PIO_STATUS_BLOCK IoStatusBlock
,
458 IN ULONG CompletionFilter
,
459 IN BOOLEAN Asynchroneous
,
460 OUT PVOID ChangeBuffer
,
462 IN BOOLEAN WatchSubtree
)
464 FIXME("(%p,%p,%p,%p,%p,0x%08lx, 0x%08x,%p,0x%08lx,0x%08x) stub!\n",
465 KeyHandle
, Event
, ApcRoutine
, ApcContext
, IoStatusBlock
, CompletionFilter
,
466 Asynchroneous
, ChangeBuffer
, Length
, WatchSubtree
);
467 return STATUS_SUCCESS
;
470 /******************************************************************************
471 * NtQueryMultipleValueKey [NTDLL]
472 * ZwQueryMultipleValueKey
475 NTSTATUS WINAPI
NtQueryMultipleValueKey(
477 PVALENTW ListOfValuesToQuery
,
479 PVOID MultipleValueInformation
,
483 FIXME("(%p,%p,0x%08lx,%p,0x%08lx,%p) stub!\n",
484 KeyHandle
, ListOfValuesToQuery
, NumberOfItems
, MultipleValueInformation
,
485 Length
,ReturnLength
);
486 return STATUS_SUCCESS
;
489 /******************************************************************************
490 * NtReplaceKey [NTDLL.@]
491 * ZwReplaceKey [NTDLL.@]
493 NTSTATUS WINAPI
NtReplaceKey(
494 IN POBJECT_ATTRIBUTES ObjectAttributes
,
496 IN POBJECT_ATTRIBUTES ReplacedObjectAttributes
)
498 FIXME("(%p),stub!\n", Key
);
499 dump_ObjectAttributes(ObjectAttributes
);
500 dump_ObjectAttributes(ReplacedObjectAttributes
);
501 return STATUS_SUCCESS
;
503 /******************************************************************************
504 * NtRestoreKey [NTDLL.@]
505 * ZwRestoreKey [NTDLL.@]
507 NTSTATUS WINAPI
NtRestoreKey(
512 FIXME("(%p,%p,0x%08lx) stub\n",
513 KeyHandle
, FileHandle
, RestoreFlags
);
514 return STATUS_SUCCESS
;
516 /******************************************************************************
517 * NtSaveKey [NTDLL.@]
518 * ZwSaveKey [NTDLL.@]
520 NTSTATUS WINAPI
NtSaveKey(
522 IN HANDLE FileHandle
)
524 FIXME("(%p,%p) stub\n",
525 KeyHandle
, FileHandle
);
526 return STATUS_SUCCESS
;
528 /******************************************************************************
529 * NtSetInformationKey [NTDLL.@]
530 * ZwSetInformationKey [NTDLL.@]
532 NTSTATUS WINAPI
NtSetInformationKey(
534 IN
const int KeyInformationClass
,
535 IN PVOID KeyInformation
,
536 IN ULONG KeyInformationLength
)
538 FIXME("(%p,0x%08x,%p,0x%08lx) stub\n",
539 KeyHandle
, KeyInformationClass
, KeyInformation
, KeyInformationLength
);
540 return STATUS_SUCCESS
;
544 /******************************************************************************
545 * NtSetValueKey [NTDLL.@]
546 * ZwSetValueKey [NTDLL.@]
549 * win95 does not care about count for REG_SZ and finds out the len by itself (js)
550 * NT does definitely care (aj)
552 NTSTATUS WINAPI
NtSetValueKey( HKEY hkey
, const UNICODE_STRING
*name
, ULONG TitleIndex
,
553 ULONG type
, const void *data
, ULONG count
)
557 TRACE( "(%p,%s,%ld,%p,%ld)\n", hkey
, debugstr_us(name
), type
, data
, count
);
559 if (name
->Length
> MAX_NAME_LENGTH
) return STATUS_BUFFER_OVERFLOW
;
561 SERVER_START_REQ( set_key_value
)
565 req
->namelen
= name
->Length
;
566 wine_server_add_data( req
, name
->Buffer
, name
->Length
);
567 wine_server_add_data( req
, data
, count
);
568 ret
= wine_server_call( req
);
574 /******************************************************************************
575 * NtUnloadKey [NTDLL.@]
576 * ZwUnloadKey [NTDLL.@]
578 NTSTATUS WINAPI
NtUnloadKey(
583 return STATUS_SUCCESS
;
586 /******************************************************************************
587 * RtlFormatCurrentUserKeyPath [NTDLL.@]
589 * NOTE: under NT the user name part of the path is an SID.
591 NTSTATUS WINAPI
RtlFormatCurrentUserKeyPath( IN OUT PUNICODE_STRING KeyPath
)
593 const char *user
= wine_get_user_name();
595 ANSI_STRING AnsiPath
;
598 if (!(buffer
= RtlAllocateHeap( ntdll_get_process_heap(), 0, strlen(user
)+16 )))
599 return STATUS_NO_MEMORY
;
601 strcpy( buffer
, "\\Registry\\User\\" );
602 strcat( buffer
, user
);
603 RtlInitAnsiString( &AnsiPath
, buffer
);
604 ret
= RtlAnsiStringToUnicodeString(KeyPath
, &AnsiPath
, TRUE
);
605 RtlFreeAnsiString( &AnsiPath
);
609 /******************************************************************************
610 * RtlOpenCurrentUser [NTDLL.@]
612 * if we return just HKEY_CURRENT_USER the advapi tries to find a remote
613 * registry (odd handle) and fails
616 DWORD WINAPI
RtlOpenCurrentUser(
617 IN ACCESS_MASK DesiredAccess
, /* [in] */
618 OUT PHKEY KeyHandle
) /* [out] handle of HKEY_CURRENT_USER */
620 OBJECT_ATTRIBUTES ObjectAttributes
;
621 UNICODE_STRING ObjectName
;
624 TRACE("(0x%08lx, %p) stub\n",DesiredAccess
, KeyHandle
);
626 RtlFormatCurrentUserKeyPath(&ObjectName
);
627 InitializeObjectAttributes(&ObjectAttributes
,&ObjectName
,OBJ_CASE_INSENSITIVE
,0, NULL
);
628 ret
= NtCreateKey(KeyHandle
, DesiredAccess
, &ObjectAttributes
, 0, NULL
, 0, NULL
);
629 RtlFreeUnicodeString(&ObjectName
);