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