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"
32 #include "wine/debug.h"
35 #include "wine/unicode.h"
36 #include "wine/server.h"
38 #include "ntdll_misc.h"
40 WINE_DEFAULT_DEBUG_CHANNEL(reg
);
42 /* maximum length of a key/value name in bytes (without terminating null) */
43 #define MAX_NAME_LENGTH ((MAX_PATH-1) * sizeof(WCHAR))
46 /******************************************************************************
47 * NtCreateKey [NTDLL.@]
48 * ZwCreateKey [NTDLL.@]
50 NTSTATUS WINAPI
NtCreateKey( PHANDLE retkey
, ACCESS_MASK access
, const OBJECT_ATTRIBUTES
*attr
,
51 ULONG TitleIndex
, const UNICODE_STRING
*class, ULONG options
,
56 TRACE( "(0x%x,%s,%s,%lx,%lx,%p)\n", attr
->RootDirectory
, debugstr_us(attr
->ObjectName
),
57 debugstr_us(class), options
, access
, retkey
);
59 if (attr
->ObjectName
->Length
> MAX_NAME_LENGTH
) return STATUS_BUFFER_OVERFLOW
;
60 if (!retkey
) return STATUS_INVALID_PARAMETER
;
62 SERVER_START_REQ( create_key
)
64 req
->parent
= attr
->RootDirectory
;
66 req
->options
= options
;
68 req
->namelen
= attr
->ObjectName
->Length
;
69 wine_server_add_data( req
, attr
->ObjectName
->Buffer
, attr
->ObjectName
->Length
);
70 if (class) wine_server_add_data( req
, class->Buffer
, class->Length
);
71 if (!(ret
= wine_server_call( req
)))
73 *retkey
= reply
->hkey
;
74 if (dispos
) *dispos
= reply
->created
? REG_CREATED_NEW_KEY
: REG_OPENED_EXISTING_KEY
;
78 TRACE("<- 0x%04x\n", *retkey
);
83 /******************************************************************************
87 * OUT PHANDLE retkey (returns 0 when failure)
88 * IN ACCESS_MASK access
89 * IN POBJECT_ATTRIBUTES attr
91 NTSTATUS WINAPI
NtOpenKey( PHANDLE retkey
, ACCESS_MASK access
, const OBJECT_ATTRIBUTES
*attr
)
94 DWORD len
= attr
->ObjectName
->Length
;
96 TRACE( "(0x%x,%s,%lx,%p)\n", attr
->RootDirectory
,
97 debugstr_us(attr
->ObjectName
), access
, retkey
);
99 if (len
> MAX_NAME_LENGTH
) return STATUS_BUFFER_OVERFLOW
;
100 if (!retkey
) return STATUS_INVALID_PARAMETER
;
102 SERVER_START_REQ( open_key
)
104 req
->parent
= attr
->RootDirectory
;
105 req
->access
= access
;
106 wine_server_add_data( req
, attr
->ObjectName
->Buffer
, len
);
107 ret
= wine_server_call( req
);
108 *retkey
= reply
->hkey
;
111 TRACE("<- 0x%04x\n", *retkey
);
116 /******************************************************************************
117 * NtDeleteKey [NTDLL.@]
118 * ZwDeleteKey [NTDLL.@]
120 NTSTATUS WINAPI
NtDeleteKey( HANDLE hkey
)
124 TRACE( "(%x)\n", hkey
);
126 SERVER_START_REQ( delete_key
)
129 ret
= wine_server_call( req
);
136 /******************************************************************************
137 * NtDeleteValueKey [NTDLL.@]
138 * ZwDeleteValueKey [NTDLL.@]
140 NTSTATUS WINAPI
NtDeleteValueKey( HANDLE hkey
, const UNICODE_STRING
*name
)
144 TRACE( "(0x%x,%s)\n", hkey
, debugstr_us(name
) );
145 if (name
->Length
> MAX_NAME_LENGTH
) return STATUS_BUFFER_OVERFLOW
;
147 SERVER_START_REQ( delete_key_value
)
150 wine_server_add_data( req
, name
->Buffer
, name
->Length
);
151 ret
= wine_server_call( req
);
158 /******************************************************************************
161 * Implementation of NtQueryKey and NtEnumerateKey
163 static NTSTATUS
enumerate_key( HANDLE handle
, int index
, KEY_INFORMATION_CLASS info_class
,
164 void *info
, DWORD length
, DWORD
*result_len
)
173 case KeyBasicInformation
: data_ptr
= ((KEY_BASIC_INFORMATION
*)info
)->Name
; break;
174 case KeyFullInformation
: data_ptr
= ((KEY_FULL_INFORMATION
*)info
)->Class
; break;
175 case KeyNodeInformation
: data_ptr
= ((KEY_NODE_INFORMATION
*)info
)->Name
; break;
177 FIXME( "Information class %d not implemented\n", info_class
);
178 return STATUS_INVALID_PARAMETER
;
180 fixed_size
= (char *)data_ptr
- (char *)info
;
182 SERVER_START_REQ( enum_key
)
186 req
->info_class
= info_class
;
187 if (length
> fixed_size
) wine_server_set_reply( req
, data_ptr
, length
- fixed_size
);
188 if (!(ret
= wine_server_call( req
)))
192 RtlSecondsSince1970ToTime( reply
->modif
, (FILETIME
*)&modif
);
196 case KeyBasicInformation
:
198 KEY_BASIC_INFORMATION keyinfo
;
199 fixed_size
= (char *)keyinfo
.Name
- (char *)&keyinfo
;
200 keyinfo
.LastWriteTime
= modif
;
201 keyinfo
.TitleIndex
= 0;
202 keyinfo
.NameLength
= reply
->namelen
;
203 memcpy( info
, &keyinfo
, min( length
, fixed_size
) );
206 case KeyFullInformation
:
208 KEY_FULL_INFORMATION keyinfo
;
209 fixed_size
= (char *)keyinfo
.Class
- (char *)&keyinfo
;
210 keyinfo
.LastWriteTime
= modif
;
211 keyinfo
.TitleIndex
= 0;
212 keyinfo
.ClassLength
= wine_server_reply_size(reply
);
213 keyinfo
.ClassOffset
= keyinfo
.ClassLength
? fixed_size
: -1;
214 keyinfo
.SubKeys
= reply
->subkeys
;
215 keyinfo
.MaxNameLen
= reply
->max_subkey
;
216 keyinfo
.MaxClassLen
= reply
->max_class
;
217 keyinfo
.Values
= reply
->values
;
218 keyinfo
.MaxValueNameLen
= reply
->max_value
;
219 keyinfo
.MaxValueDataLen
= reply
->max_data
;
220 memcpy( info
, &keyinfo
, min( length
, fixed_size
) );
223 case KeyNodeInformation
:
225 KEY_NODE_INFORMATION keyinfo
;
226 fixed_size
= (char *)keyinfo
.Name
- (char *)&keyinfo
;
227 keyinfo
.LastWriteTime
= modif
;
228 keyinfo
.TitleIndex
= 0;
229 keyinfo
.ClassLength
= max( 0, wine_server_reply_size(reply
) - reply
->namelen
);
230 keyinfo
.ClassOffset
= keyinfo
.ClassLength
? fixed_size
+ reply
->namelen
: -1;
231 keyinfo
.NameLength
= reply
->namelen
;
232 memcpy( info
, &keyinfo
, min( length
, fixed_size
) );
236 *result_len
= fixed_size
+ reply
->total
;
237 if (length
< *result_len
) ret
= STATUS_BUFFER_OVERFLOW
;
246 /******************************************************************************
247 * NtEnumerateKey [NTDLL.@]
248 * ZwEnumerateKey [NTDLL.@]
251 * the name copied into the buffer is NOT 0-terminated
253 NTSTATUS WINAPI
NtEnumerateKey( HANDLE handle
, ULONG index
, KEY_INFORMATION_CLASS info_class
,
254 void *info
, DWORD length
, DWORD
*result_len
)
256 /* -1 means query key, so avoid it here */
257 if (index
== (ULONG
)-1) return STATUS_NO_MORE_ENTRIES
;
258 return enumerate_key( handle
, index
, info_class
, info
, length
, result_len
);
262 /******************************************************************************
263 * NtQueryKey [NTDLL.@]
264 * ZwQueryKey [NTDLL.@]
266 NTSTATUS WINAPI
NtQueryKey( HANDLE handle
, KEY_INFORMATION_CLASS info_class
,
267 void *info
, DWORD length
, DWORD
*result_len
)
269 return enumerate_key( handle
, -1, info_class
, info
, length
, result_len
);
273 /* fill the key value info structure for a specific info class */
274 static void copy_key_value_info( KEY_VALUE_INFORMATION_CLASS info_class
, void *info
,
275 DWORD length
, int type
, int name_len
, int data_len
)
279 case KeyValueBasicInformation
:
281 KEY_VALUE_BASIC_INFORMATION keyinfo
;
282 keyinfo
.TitleIndex
= 0;
284 keyinfo
.NameLength
= name_len
;
285 length
= min( length
, (char *)keyinfo
.Name
- (char *)&keyinfo
);
286 memcpy( info
, &keyinfo
, length
);
289 case KeyValueFullInformation
:
291 KEY_VALUE_FULL_INFORMATION keyinfo
;
292 keyinfo
.TitleIndex
= 0;
294 keyinfo
.DataOffset
= (char *)keyinfo
.Name
- (char *)&keyinfo
+ name_len
;
295 keyinfo
.DataLength
= data_len
;
296 keyinfo
.NameLength
= name_len
;
297 length
= min( length
, (char *)keyinfo
.Name
- (char *)&keyinfo
);
298 memcpy( info
, &keyinfo
, length
);
301 case KeyValuePartialInformation
:
303 KEY_VALUE_PARTIAL_INFORMATION keyinfo
;
304 keyinfo
.TitleIndex
= 0;
306 keyinfo
.DataLength
= data_len
;
307 length
= min( length
, (char *)keyinfo
.Data
- (char *)&keyinfo
);
308 memcpy( info
, &keyinfo
, length
);
317 /******************************************************************************
318 * NtEnumerateValueKey [NTDLL.@]
319 * ZwEnumerateValueKey [NTDLL.@]
321 NTSTATUS WINAPI
NtEnumerateValueKey( HANDLE handle
, ULONG index
,
322 KEY_VALUE_INFORMATION_CLASS info_class
,
323 void *info
, DWORD length
, DWORD
*result_len
)
329 TRACE( "(0x%x,%lu,%d,%p,%ld)\n", handle
, index
, info_class
, info
, length
);
331 /* compute the length we want to retrieve */
334 case KeyValueBasicInformation
: ptr
= ((KEY_VALUE_BASIC_INFORMATION
*)info
)->Name
; break;
335 case KeyValueFullInformation
: ptr
= ((KEY_VALUE_FULL_INFORMATION
*)info
)->Name
; break;
336 case KeyValuePartialInformation
: ptr
= ((KEY_VALUE_PARTIAL_INFORMATION
*)info
)->Data
; break;
338 FIXME( "Information class %d not implemented\n", info_class
);
339 return STATUS_INVALID_PARAMETER
;
341 fixed_size
= (char *)ptr
- (char *)info
;
343 SERVER_START_REQ( enum_key_value
)
347 req
->info_class
= info_class
;
348 if (length
> fixed_size
) wine_server_set_reply( req
, ptr
, length
- fixed_size
);
349 if (!(ret
= wine_server_call( req
)))
351 copy_key_value_info( info_class
, info
, length
, reply
->type
, reply
->namelen
,
352 wine_server_reply_size(reply
) - reply
->namelen
);
353 *result_len
= fixed_size
+ reply
->total
;
354 if (length
< *result_len
) ret
= STATUS_BUFFER_OVERFLOW
;
362 /******************************************************************************
363 * NtQueryValueKey [NTDLL.@]
364 * ZwQueryValueKey [NTDLL.@]
367 * the name in the KeyValueInformation is never set
369 NTSTATUS WINAPI
NtQueryValueKey( HANDLE handle
, const UNICODE_STRING
*name
,
370 KEY_VALUE_INFORMATION_CLASS info_class
,
371 void *info
, DWORD length
, DWORD
*result_len
)
377 TRACE( "(0x%x,%s,%d,%p,%ld)\n", handle
, debugstr_us(name
), info_class
, info
, length
);
379 if (name
->Length
> MAX_NAME_LENGTH
) return STATUS_BUFFER_OVERFLOW
;
381 /* compute the length we want to retrieve */
384 case KeyValueBasicInformation
:
385 fixed_size
= (char *)((KEY_VALUE_BASIC_INFORMATION
*)info
)->Name
- (char *)info
;
388 case KeyValueFullInformation
:
389 data_ptr
= (UCHAR
*)((KEY_VALUE_FULL_INFORMATION
*)info
)->Name
;
390 fixed_size
= (char *)data_ptr
- (char *)info
;
392 case KeyValuePartialInformation
:
393 data_ptr
= ((KEY_VALUE_PARTIAL_INFORMATION
*)info
)->Data
;
394 fixed_size
= (char *)data_ptr
- (char *)info
;
397 FIXME( "Information class %d not implemented\n", info_class
);
398 return STATUS_INVALID_PARAMETER
;
401 SERVER_START_REQ( get_key_value
)
404 wine_server_add_data( req
, name
->Buffer
, name
->Length
);
405 if (length
> fixed_size
) wine_server_set_reply( req
, data_ptr
, length
- fixed_size
);
406 if (!(ret
= wine_server_call( req
)))
408 copy_key_value_info( info_class
, info
, length
, reply
->type
,
409 0, wine_server_reply_size(reply
) );
410 *result_len
= fixed_size
+ reply
->total
;
411 if (length
< *result_len
) ret
= STATUS_BUFFER_OVERFLOW
;
419 /******************************************************************************
420 * NtFlushKey [NTDLL.@]
421 * ZwFlushKey [NTDLL.@]
423 NTSTATUS WINAPI
NtFlushKey(HANDLE KeyHandle
)
425 FIXME("(0x%08x) stub!\n",
430 /******************************************************************************
431 * NtLoadKey [NTDLL.@]
432 * ZwLoadKey [NTDLL.@]
434 NTSTATUS WINAPI
NtLoadKey( const OBJECT_ATTRIBUTES
*attr
, const OBJECT_ATTRIBUTES
*file
)
437 dump_ObjectAttributes(attr
);
438 dump_ObjectAttributes(file
);
439 return STATUS_SUCCESS
;
442 /******************************************************************************
443 * NtNotifyChangeKey [NTDLL.@]
444 * ZwNotifyChangeKey [NTDLL.@]
446 NTSTATUS WINAPI
NtNotifyChangeKey(
449 IN PIO_APC_ROUTINE ApcRoutine OPTIONAL
,
450 IN PVOID ApcContext OPTIONAL
,
451 OUT PIO_STATUS_BLOCK IoStatusBlock
,
452 IN ULONG CompletionFilter
,
453 IN BOOLEAN Asynchroneous
,
454 OUT PVOID ChangeBuffer
,
456 IN BOOLEAN WatchSubtree
)
458 FIXME("(0x%08x,0x%08x,%p,%p,%p,0x%08lx, 0x%08x,%p,0x%08lx,0x%08x) stub!\n",
459 KeyHandle
, Event
, ApcRoutine
, ApcContext
, IoStatusBlock
, CompletionFilter
,
460 Asynchroneous
, ChangeBuffer
, Length
, WatchSubtree
);
461 return STATUS_SUCCESS
;
464 /******************************************************************************
465 * NtQueryMultipleValueKey [NTDLL]
466 * ZwQueryMultipleValueKey
469 NTSTATUS WINAPI
NtQueryMultipleValueKey(
471 PVALENTW ListOfValuesToQuery
,
473 PVOID MultipleValueInformation
,
477 FIXME("(0x%08x,%p,0x%08lx,%p,0x%08lx,%p) stub!\n",
478 KeyHandle
, ListOfValuesToQuery
, NumberOfItems
, MultipleValueInformation
,
479 Length
,ReturnLength
);
480 return STATUS_SUCCESS
;
483 /******************************************************************************
484 * NtReplaceKey [NTDLL.@]
485 * ZwReplaceKey [NTDLL.@]
487 NTSTATUS WINAPI
NtReplaceKey(
488 IN POBJECT_ATTRIBUTES ObjectAttributes
,
490 IN POBJECT_ATTRIBUTES ReplacedObjectAttributes
)
492 FIXME("(0x%08x),stub!\n", Key
);
493 dump_ObjectAttributes(ObjectAttributes
);
494 dump_ObjectAttributes(ReplacedObjectAttributes
);
495 return STATUS_SUCCESS
;
497 /******************************************************************************
498 * NtRestoreKey [NTDLL.@]
499 * ZwRestoreKey [NTDLL.@]
501 NTSTATUS WINAPI
NtRestoreKey(
506 FIXME("(0x%08x,0x%08x,0x%08lx) stub\n",
507 KeyHandle
, FileHandle
, RestoreFlags
);
508 return STATUS_SUCCESS
;
510 /******************************************************************************
511 * NtSaveKey [NTDLL.@]
512 * ZwSaveKey [NTDLL.@]
514 NTSTATUS WINAPI
NtSaveKey(
516 IN HANDLE FileHandle
)
518 FIXME("(0x%08x,0x%08x) stub\n",
519 KeyHandle
, FileHandle
);
520 return STATUS_SUCCESS
;
522 /******************************************************************************
523 * NtSetInformationKey [NTDLL.@]
524 * ZwSetInformationKey [NTDLL.@]
526 NTSTATUS WINAPI
NtSetInformationKey(
528 IN
const int KeyInformationClass
,
529 IN PVOID KeyInformation
,
530 IN ULONG KeyInformationLength
)
532 FIXME("(0x%08x,0x%08x,%p,0x%08lx) stub\n",
533 KeyHandle
, KeyInformationClass
, KeyInformation
, KeyInformationLength
);
534 return STATUS_SUCCESS
;
538 /******************************************************************************
539 * NtSetValueKey [NTDLL.@]
540 * ZwSetValueKey [NTDLL.@]
543 * win95 does not care about count for REG_SZ and finds out the len by itself (js)
544 * NT does definitely care (aj)
546 NTSTATUS WINAPI
NtSetValueKey( HANDLE hkey
, const UNICODE_STRING
*name
, ULONG TitleIndex
,
547 ULONG type
, const void *data
, ULONG count
)
551 TRACE( "(0x%x,%s,%ld,%p,%ld)\n", hkey
, debugstr_us(name
), type
, data
, count
);
553 if (name
->Length
> MAX_NAME_LENGTH
) return STATUS_BUFFER_OVERFLOW
;
555 SERVER_START_REQ( set_key_value
)
559 req
->namelen
= name
->Length
;
560 wine_server_add_data( req
, name
->Buffer
, name
->Length
);
561 wine_server_add_data( req
, data
, count
);
562 ret
= wine_server_call( req
);
568 /******************************************************************************
569 * NtUnloadKey [NTDLL.@]
570 * ZwUnloadKey [NTDLL.@]
572 NTSTATUS WINAPI
NtUnloadKey(
575 FIXME("(0x%08x) stub\n",
577 return STATUS_SUCCESS
;
580 /******************************************************************************
581 * RtlFormatCurrentUserKeyPath [NTDLL.@]
583 NTSTATUS WINAPI
RtlFormatCurrentUserKeyPath(
584 IN OUT PUNICODE_STRING KeyPath
)
586 /* LPSTR Path = "\\REGISTRY\\USER\\S-1-5-21-0000000000-000000000-0000000000-500";*/
587 LPSTR Path
= "\\REGISTRY\\USER\\.DEFAULT";
588 ANSI_STRING AnsiPath
;
590 FIXME("(%p) stub\n",KeyPath
);
591 RtlInitAnsiString(&AnsiPath
, Path
);
592 return RtlAnsiStringToUnicodeString(KeyPath
, &AnsiPath
, TRUE
);
595 /******************************************************************************
596 * RtlOpenCurrentUser [NTDLL.@]
598 * if we return just HKEY_CURRENT_USER the advapi tries to find a remote
599 * registry (odd handle) and fails
602 DWORD WINAPI
RtlOpenCurrentUser(
603 IN ACCESS_MASK DesiredAccess
, /* [in] */
604 OUT PHANDLE KeyHandle
) /* [out] handle of HKEY_CURRENT_USER */
606 OBJECT_ATTRIBUTES ObjectAttributes
;
607 UNICODE_STRING ObjectName
;
610 TRACE("(0x%08lx, %p) stub\n",DesiredAccess
, KeyHandle
);
612 RtlFormatCurrentUserKeyPath(&ObjectName
);
613 InitializeObjectAttributes(&ObjectAttributes
,&ObjectName
,OBJ_CASE_INSENSITIVE
,0, NULL
);
614 ret
= NtOpenKey(KeyHandle
, DesiredAccess
, &ObjectAttributes
);
615 RtlFreeUnicodeString(&ObjectName
);