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
);
88 /******************************************************************************
89 * RtlpNtCreateKey [NTDLL.@]
93 NTSTATUS WINAPI
RtlpNtCreateKey( PHKEY retkey
, ACCESS_MASK access
, OBJECT_ATTRIBUTES
*attr
,
94 ULONG TitleIndex
, const UNICODE_STRING
*class, ULONG options
,
98 attr
->Attributes
&= ~(OBJ_PERMANENT
|OBJ_EXCLUSIVE
);
100 return NtCreateKey(retkey
, access
, attr
, 0, NULL
, 0, dispos
);
103 /******************************************************************************
104 * NtOpenKey [NTDLL.@]
105 * ZwOpenKey [NTDLL.@]
107 * OUT PHKEY retkey (returns 0 when failure)
108 * IN ACCESS_MASK access
109 * IN POBJECT_ATTRIBUTES attr
111 NTSTATUS WINAPI
NtOpenKey( PHKEY retkey
, ACCESS_MASK access
, const OBJECT_ATTRIBUTES
*attr
)
114 DWORD len
= attr
->ObjectName
->Length
;
116 TRACE( "(%p,%s,%lx,%p)\n", attr
->RootDirectory
,
117 debugstr_us(attr
->ObjectName
), access
, retkey
);
119 if (len
> MAX_NAME_LENGTH
) return STATUS_BUFFER_OVERFLOW
;
120 if (!retkey
) return STATUS_INVALID_PARAMETER
;
122 SERVER_START_REQ( open_key
)
124 req
->parent
= attr
->RootDirectory
;
125 req
->access
= access
;
126 wine_server_add_data( req
, attr
->ObjectName
->Buffer
, len
);
127 ret
= wine_server_call( req
);
128 *retkey
= reply
->hkey
;
131 TRACE("<- %p\n", *retkey
);
135 /******************************************************************************
136 * RtlpNtOpenKey [NTDLL.@]
140 NTSTATUS WINAPI
RtlpNtOpenKey( PHKEY retkey
, ACCESS_MASK access
, OBJECT_ATTRIBUTES
*attr
)
143 attr
->Attributes
&= ~(OBJ_PERMANENT
|OBJ_EXCLUSIVE
);
144 return NtOpenKey(retkey
, access
, attr
);
147 /******************************************************************************
148 * NtDeleteKey [NTDLL.@]
149 * ZwDeleteKey [NTDLL.@]
151 NTSTATUS WINAPI
NtDeleteKey( HKEY hkey
)
155 TRACE( "(%p)\n", hkey
);
157 SERVER_START_REQ( delete_key
)
160 ret
= wine_server_call( req
);
166 /******************************************************************************
167 * RtlpNtMakeTemporaryKey [NTDLL.@]
171 NTSTATUS WINAPI
RtlpNtMakeTemporaryKey( HKEY hkey
)
173 return NtDeleteKey(hkey
);
176 /******************************************************************************
177 * NtDeleteValueKey [NTDLL.@]
178 * ZwDeleteValueKey [NTDLL.@]
180 NTSTATUS WINAPI
NtDeleteValueKey( HKEY hkey
, const UNICODE_STRING
*name
)
184 TRACE( "(%p,%s)\n", hkey
, debugstr_us(name
) );
185 if (name
->Length
> MAX_NAME_LENGTH
) return STATUS_BUFFER_OVERFLOW
;
187 SERVER_START_REQ( delete_key_value
)
190 wine_server_add_data( req
, name
->Buffer
, name
->Length
);
191 ret
= wine_server_call( req
);
198 /******************************************************************************
201 * Implementation of NtQueryKey and NtEnumerateKey
203 static NTSTATUS
enumerate_key( HKEY handle
, int index
, KEY_INFORMATION_CLASS info_class
,
204 void *info
, DWORD length
, DWORD
*result_len
)
213 case KeyBasicInformation
: data_ptr
= ((KEY_BASIC_INFORMATION
*)info
)->Name
; break;
214 case KeyFullInformation
: data_ptr
= ((KEY_FULL_INFORMATION
*)info
)->Class
; break;
215 case KeyNodeInformation
: data_ptr
= ((KEY_NODE_INFORMATION
*)info
)->Name
; break;
217 FIXME( "Information class %d not implemented\n", info_class
);
218 return STATUS_INVALID_PARAMETER
;
220 fixed_size
= (char *)data_ptr
- (char *)info
;
222 SERVER_START_REQ( enum_key
)
226 req
->info_class
= info_class
;
227 if (length
> fixed_size
) wine_server_set_reply( req
, data_ptr
, length
- fixed_size
);
228 if (!(ret
= wine_server_call( req
)))
232 RtlSecondsSince1970ToTime( reply
->modif
, &modif
);
236 case KeyBasicInformation
:
238 KEY_BASIC_INFORMATION keyinfo
;
239 fixed_size
= (char *)keyinfo
.Name
- (char *)&keyinfo
;
240 keyinfo
.LastWriteTime
= modif
;
241 keyinfo
.TitleIndex
= 0;
242 keyinfo
.NameLength
= reply
->namelen
;
243 memcpy( info
, &keyinfo
, min( length
, fixed_size
) );
246 case KeyFullInformation
:
248 KEY_FULL_INFORMATION keyinfo
;
249 fixed_size
= (char *)keyinfo
.Class
- (char *)&keyinfo
;
250 keyinfo
.LastWriteTime
= modif
;
251 keyinfo
.TitleIndex
= 0;
252 keyinfo
.ClassLength
= wine_server_reply_size(reply
);
253 keyinfo
.ClassOffset
= keyinfo
.ClassLength
? fixed_size
: -1;
254 keyinfo
.SubKeys
= reply
->subkeys
;
255 keyinfo
.MaxNameLen
= reply
->max_subkey
;
256 keyinfo
.MaxClassLen
= reply
->max_class
;
257 keyinfo
.Values
= reply
->values
;
258 keyinfo
.MaxValueNameLen
= reply
->max_value
;
259 keyinfo
.MaxValueDataLen
= reply
->max_data
;
260 memcpy( info
, &keyinfo
, min( length
, fixed_size
) );
263 case KeyNodeInformation
:
265 KEY_NODE_INFORMATION keyinfo
;
266 fixed_size
= (char *)keyinfo
.Name
- (char *)&keyinfo
;
267 keyinfo
.LastWriteTime
= modif
;
268 keyinfo
.TitleIndex
= 0;
269 keyinfo
.ClassLength
= max( 0, wine_server_reply_size(reply
) - reply
->namelen
);
270 keyinfo
.ClassOffset
= keyinfo
.ClassLength
? fixed_size
+ reply
->namelen
: -1;
271 keyinfo
.NameLength
= reply
->namelen
;
272 memcpy( info
, &keyinfo
, min( length
, fixed_size
) );
276 *result_len
= fixed_size
+ reply
->total
;
277 if (length
< *result_len
) ret
= STATUS_BUFFER_OVERFLOW
;
286 /******************************************************************************
287 * NtEnumerateKey [NTDLL.@]
288 * ZwEnumerateKey [NTDLL.@]
291 * the name copied into the buffer is NOT 0-terminated
293 NTSTATUS WINAPI
NtEnumerateKey( HKEY handle
, ULONG index
, KEY_INFORMATION_CLASS info_class
,
294 void *info
, DWORD length
, DWORD
*result_len
)
296 /* -1 means query key, so avoid it here */
297 if (index
== (ULONG
)-1) return STATUS_NO_MORE_ENTRIES
;
298 return enumerate_key( handle
, index
, info_class
, info
, length
, result_len
);
302 /******************************************************************************
303 * RtlpNtEnumerateSubKey [NTDLL.@]
306 NTSTATUS WINAPI
RtlpNtEnumerateSubKey( HKEY handle
, UNICODE_STRING
*out
, ULONG index
)
308 KEY_BASIC_INFORMATION
*info
;
309 DWORD dwLen
, dwResultLen
;
314 dwLen
= out
->Length
+ sizeof(KEY_BASIC_INFORMATION
);
315 info
= (KEY_BASIC_INFORMATION
*)RtlAllocateHeap( ntdll_get_process_heap(), 0, dwLen
);
317 return STATUS_NO_MEMORY
;
325 ret
= NtEnumerateKey( handle
, index
, KeyBasicInformation
, info
, dwLen
, &dwResultLen
);
326 dwResultLen
-= sizeof(KEY_BASIC_INFORMATION
);
328 if (ret
== STATUS_BUFFER_OVERFLOW
)
329 out
->Length
= dwResultLen
;
332 if (out
->Length
< info
->NameLength
)
334 out
->Length
= dwResultLen
;
335 ret
= STATUS_BUFFER_OVERFLOW
;
339 out
->Length
= info
->NameLength
;
340 memcpy(out
->Buffer
, info
->Name
, info
->NameLength
);
345 RtlFreeHeap( ntdll_get_process_heap(), 0, info
);
349 /******************************************************************************
350 * NtQueryKey [NTDLL.@]
351 * ZwQueryKey [NTDLL.@]
353 NTSTATUS WINAPI
NtQueryKey( HKEY handle
, KEY_INFORMATION_CLASS info_class
,
354 void *info
, DWORD length
, DWORD
*result_len
)
356 return enumerate_key( handle
, -1, info_class
, info
, length
, result_len
);
360 /* fill the key value info structure for a specific info class */
361 static void copy_key_value_info( KEY_VALUE_INFORMATION_CLASS info_class
, void *info
,
362 DWORD length
, int type
, int name_len
, int data_len
)
366 case KeyValueBasicInformation
:
368 KEY_VALUE_BASIC_INFORMATION keyinfo
;
369 keyinfo
.TitleIndex
= 0;
371 keyinfo
.NameLength
= name_len
;
372 length
= min( length
, (char *)keyinfo
.Name
- (char *)&keyinfo
);
373 memcpy( info
, &keyinfo
, length
);
376 case KeyValueFullInformation
:
378 KEY_VALUE_FULL_INFORMATION keyinfo
;
379 keyinfo
.TitleIndex
= 0;
381 keyinfo
.DataOffset
= (char *)keyinfo
.Name
- (char *)&keyinfo
+ name_len
;
382 keyinfo
.DataLength
= data_len
;
383 keyinfo
.NameLength
= name_len
;
384 length
= min( length
, (char *)keyinfo
.Name
- (char *)&keyinfo
);
385 memcpy( info
, &keyinfo
, length
);
388 case KeyValuePartialInformation
:
390 KEY_VALUE_PARTIAL_INFORMATION keyinfo
;
391 keyinfo
.TitleIndex
= 0;
393 keyinfo
.DataLength
= data_len
;
394 length
= min( length
, (char *)keyinfo
.Data
- (char *)&keyinfo
);
395 memcpy( info
, &keyinfo
, length
);
404 /******************************************************************************
405 * NtEnumerateValueKey [NTDLL.@]
406 * ZwEnumerateValueKey [NTDLL.@]
408 NTSTATUS WINAPI
NtEnumerateValueKey( HKEY handle
, ULONG index
,
409 KEY_VALUE_INFORMATION_CLASS info_class
,
410 void *info
, DWORD length
, DWORD
*result_len
)
416 TRACE( "(%p,%lu,%d,%p,%ld)\n", handle
, index
, info_class
, info
, length
);
418 /* compute the length we want to retrieve */
421 case KeyValueBasicInformation
: ptr
= ((KEY_VALUE_BASIC_INFORMATION
*)info
)->Name
; break;
422 case KeyValueFullInformation
: ptr
= ((KEY_VALUE_FULL_INFORMATION
*)info
)->Name
; break;
423 case KeyValuePartialInformation
: ptr
= ((KEY_VALUE_PARTIAL_INFORMATION
*)info
)->Data
; break;
425 FIXME( "Information class %d not implemented\n", info_class
);
426 return STATUS_INVALID_PARAMETER
;
428 fixed_size
= (char *)ptr
- (char *)info
;
430 SERVER_START_REQ( enum_key_value
)
434 req
->info_class
= info_class
;
435 if (length
> fixed_size
) wine_server_set_reply( req
, ptr
, length
- fixed_size
);
436 if (!(ret
= wine_server_call( req
)))
438 copy_key_value_info( info_class
, info
, length
, reply
->type
, reply
->namelen
,
439 wine_server_reply_size(reply
) - reply
->namelen
);
440 *result_len
= fixed_size
+ reply
->total
;
441 if (length
< *result_len
) ret
= STATUS_BUFFER_OVERFLOW
;
449 /******************************************************************************
450 * NtQueryValueKey [NTDLL.@]
451 * ZwQueryValueKey [NTDLL.@]
454 * the name in the KeyValueInformation is never set
456 NTSTATUS WINAPI
NtQueryValueKey( HKEY handle
, const UNICODE_STRING
*name
,
457 KEY_VALUE_INFORMATION_CLASS info_class
,
458 void *info
, DWORD length
, DWORD
*result_len
)
464 TRACE( "(%p,%s,%d,%p,%ld)\n", handle
, debugstr_us(name
), info_class
, info
, length
);
466 if (name
->Length
> MAX_NAME_LENGTH
) return STATUS_BUFFER_OVERFLOW
;
468 /* compute the length we want to retrieve */
471 case KeyValueBasicInformation
:
472 fixed_size
= (char *)((KEY_VALUE_BASIC_INFORMATION
*)info
)->Name
- (char *)info
;
475 case KeyValueFullInformation
:
476 data_ptr
= (UCHAR
*)((KEY_VALUE_FULL_INFORMATION
*)info
)->Name
;
477 fixed_size
= (char *)data_ptr
- (char *)info
;
479 case KeyValuePartialInformation
:
480 data_ptr
= ((KEY_VALUE_PARTIAL_INFORMATION
*)info
)->Data
;
481 fixed_size
= (char *)data_ptr
- (char *)info
;
484 FIXME( "Information class %d not implemented\n", info_class
);
485 return STATUS_INVALID_PARAMETER
;
488 SERVER_START_REQ( get_key_value
)
491 wine_server_add_data( req
, name
->Buffer
, name
->Length
);
492 if (length
> fixed_size
) wine_server_set_reply( req
, data_ptr
, length
- fixed_size
);
493 if (!(ret
= wine_server_call( req
)))
495 copy_key_value_info( info_class
, info
, length
, reply
->type
,
496 0, wine_server_reply_size(reply
) );
497 *result_len
= fixed_size
+ reply
->total
;
498 if (length
< *result_len
) ret
= STATUS_BUFFER_OVERFLOW
;
505 /******************************************************************************
506 * RtlpNtQueryValueKey [NTDLL.@]
509 NTSTATUS WINAPI
RtlpNtQueryValueKey( HKEY handle
, ULONG
*result_type
, PBYTE dest
,
512 KEY_VALUE_PARTIAL_INFORMATION
*info
;
516 DWORD dwLen
= sizeof (KEY_VALUE_PARTIAL_INFORMATION
) + result_len
? *result_len
: 0;
518 info
= (KEY_VALUE_PARTIAL_INFORMATION
*)RtlAllocateHeap( ntdll_get_process_heap(), 0, dwLen
);
520 return STATUS_NO_MEMORY
;
523 ret
= NtQueryValueKey( handle
, &name
, KeyValuePartialInformation
, info
, dwLen
, &dwResultLen
);
525 if (!ret
|| ret
== STATUS_BUFFER_OVERFLOW
)
528 *result_len
= info
->DataLength
;
531 *result_type
= info
->Type
;
533 if (ret
!= STATUS_BUFFER_OVERFLOW
)
534 memcpy( dest
, info
->Data
, info
->DataLength
);
537 RtlFreeHeap( ntdll_get_process_heap(), 0, info
);
541 /******************************************************************************
542 * NtFlushKey [NTDLL.@]
543 * ZwFlushKey [NTDLL.@]
545 NTSTATUS WINAPI
NtFlushKey(HKEY key
)
549 TRACE("key=%p\n", key
);
551 SERVER_START_REQ( flush_key
)
554 ret
= wine_server_call( req
);
561 /******************************************************************************
562 * NtLoadKey [NTDLL.@]
563 * ZwLoadKey [NTDLL.@]
565 NTSTATUS WINAPI
NtLoadKey( const OBJECT_ATTRIBUTES
*attr
, const OBJECT_ATTRIBUTES
*file
)
568 dump_ObjectAttributes(attr
);
569 dump_ObjectAttributes(file
);
570 return STATUS_SUCCESS
;
573 /******************************************************************************
574 * NtNotifyChangeKey [NTDLL.@]
575 * ZwNotifyChangeKey [NTDLL.@]
577 NTSTATUS WINAPI
NtNotifyChangeKey(
580 IN PIO_APC_ROUTINE ApcRoutine OPTIONAL
,
581 IN PVOID ApcContext OPTIONAL
,
582 OUT PIO_STATUS_BLOCK IoStatusBlock
,
583 IN ULONG CompletionFilter
,
584 IN BOOLEAN Asynchroneous
,
585 OUT PVOID ChangeBuffer
,
587 IN BOOLEAN WatchSubtree
)
589 FIXME("(%p,%p,%p,%p,%p,0x%08lx, 0x%08x,%p,0x%08lx,0x%08x) stub!\n",
590 KeyHandle
, Event
, ApcRoutine
, ApcContext
, IoStatusBlock
, CompletionFilter
,
591 Asynchroneous
, ChangeBuffer
, Length
, WatchSubtree
);
592 return STATUS_SUCCESS
;
595 /******************************************************************************
596 * NtQueryMultipleValueKey [NTDLL]
597 * ZwQueryMultipleValueKey
600 NTSTATUS WINAPI
NtQueryMultipleValueKey(
602 PVALENTW ListOfValuesToQuery
,
604 PVOID MultipleValueInformation
,
608 FIXME("(%p,%p,0x%08lx,%p,0x%08lx,%p) stub!\n",
609 KeyHandle
, ListOfValuesToQuery
, NumberOfItems
, MultipleValueInformation
,
610 Length
,ReturnLength
);
611 return STATUS_SUCCESS
;
614 /******************************************************************************
615 * NtReplaceKey [NTDLL.@]
616 * ZwReplaceKey [NTDLL.@]
618 NTSTATUS WINAPI
NtReplaceKey(
619 IN POBJECT_ATTRIBUTES ObjectAttributes
,
621 IN POBJECT_ATTRIBUTES ReplacedObjectAttributes
)
623 FIXME("(%p),stub!\n", Key
);
624 dump_ObjectAttributes(ObjectAttributes
);
625 dump_ObjectAttributes(ReplacedObjectAttributes
);
626 return STATUS_SUCCESS
;
628 /******************************************************************************
629 * NtRestoreKey [NTDLL.@]
630 * ZwRestoreKey [NTDLL.@]
632 NTSTATUS WINAPI
NtRestoreKey(
637 FIXME("(%p,%p,0x%08lx) stub\n",
638 KeyHandle
, FileHandle
, RestoreFlags
);
639 return STATUS_SUCCESS
;
641 /******************************************************************************
642 * NtSaveKey [NTDLL.@]
643 * ZwSaveKey [NTDLL.@]
645 NTSTATUS WINAPI
NtSaveKey(
647 IN HANDLE FileHandle
)
649 FIXME("(%p,%p) stub\n",
650 KeyHandle
, FileHandle
);
651 return STATUS_SUCCESS
;
653 /******************************************************************************
654 * NtSetInformationKey [NTDLL.@]
655 * ZwSetInformationKey [NTDLL.@]
657 NTSTATUS WINAPI
NtSetInformationKey(
659 IN
const int KeyInformationClass
,
660 IN PVOID KeyInformation
,
661 IN ULONG KeyInformationLength
)
663 FIXME("(%p,0x%08x,%p,0x%08lx) stub\n",
664 KeyHandle
, KeyInformationClass
, KeyInformation
, KeyInformationLength
);
665 return STATUS_SUCCESS
;
669 /******************************************************************************
670 * NtSetValueKey [NTDLL.@]
671 * ZwSetValueKey [NTDLL.@]
674 * win95 does not care about count for REG_SZ and finds out the len by itself (js)
675 * NT does definitely care (aj)
677 NTSTATUS WINAPI
NtSetValueKey( HKEY hkey
, const UNICODE_STRING
*name
, ULONG TitleIndex
,
678 ULONG type
, const void *data
, ULONG count
)
682 TRACE( "(%p,%s,%ld,%p,%ld)\n", hkey
, debugstr_us(name
), type
, data
, count
);
684 if (name
->Length
> MAX_NAME_LENGTH
) return STATUS_BUFFER_OVERFLOW
;
686 SERVER_START_REQ( set_key_value
)
690 req
->namelen
= name
->Length
;
691 wine_server_add_data( req
, name
->Buffer
, name
->Length
);
692 wine_server_add_data( req
, data
, count
);
693 ret
= wine_server_call( req
);
699 /******************************************************************************
700 * RtlpNtSetValueKey [NTDLL.@]
703 NTSTATUS WINAPI
RtlpNtSetValueKey( HKEY hkey
, ULONG type
, const void *data
,
709 return NtSetValueKey( hkey
, &name
, 0, type
, data
, count
);
712 /******************************************************************************
713 * NtUnloadKey [NTDLL.@]
714 * ZwUnloadKey [NTDLL.@]
716 NTSTATUS WINAPI
NtUnloadKey(
721 return STATUS_SUCCESS
;
724 /******************************************************************************
725 * RtlFormatCurrentUserKeyPath [NTDLL.@]
727 * NOTE: under NT the user name part of the path is an SID.
729 NTSTATUS WINAPI
RtlFormatCurrentUserKeyPath( IN OUT PUNICODE_STRING KeyPath
)
731 const char *user
= wine_get_user_name();
733 ANSI_STRING AnsiPath
;
736 if (!(buffer
= RtlAllocateHeap( ntdll_get_process_heap(), 0, strlen(user
)+16 )))
737 return STATUS_NO_MEMORY
;
739 strcpy( buffer
, "\\Registry\\User\\" );
740 strcat( buffer
, user
);
741 RtlInitAnsiString( &AnsiPath
, buffer
);
742 ret
= RtlAnsiStringToUnicodeString(KeyPath
, &AnsiPath
, TRUE
);
743 RtlFreeAnsiString( &AnsiPath
);
747 /******************************************************************************
748 * RtlOpenCurrentUser [NTDLL.@]
750 * if we return just HKEY_CURRENT_USER the advapi tries to find a remote
751 * registry (odd handle) and fails
754 DWORD WINAPI
RtlOpenCurrentUser(
755 IN ACCESS_MASK DesiredAccess
, /* [in] */
756 OUT PHKEY KeyHandle
) /* [out] handle of HKEY_CURRENT_USER */
758 OBJECT_ATTRIBUTES ObjectAttributes
;
759 UNICODE_STRING ObjectName
;
762 TRACE("(0x%08lx, %p) stub\n",DesiredAccess
, KeyHandle
);
764 RtlFormatCurrentUserKeyPath(&ObjectName
);
765 InitializeObjectAttributes(&ObjectAttributes
,&ObjectName
,OBJ_CASE_INSENSITIVE
,0, NULL
);
766 ret
= NtCreateKey(KeyHandle
, DesiredAccess
, &ObjectAttributes
, 0, NULL
, 0, NULL
);
767 RtlFreeUnicodeString(&ObjectName
);