Fixed handling of \\Registry prefix.
[wine.git] / dlls / ntdll / reg.c
blob52b33eebc6c5c2f3326295cba76ac7ac2ebc8063
1 /*
2 * Registry functions
4 * Copyright (C) 1999 Juergen Schmied
5 * Copyright (C) 2000 Alexandre Julliard
7 * NOTES:
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
14 #include <string.h>
15 #include "debugtools.h"
16 #include "winreg.h"
17 #include "winerror.h"
18 #include "wine/unicode.h"
19 #include "server.h"
20 #include "ntddk.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
33 NTSTATUS WINAPI NtCreateKey( PHANDLE retkey, ACCESS_MASK access, const OBJECT_ATTRIBUTES *attr,
34 ULONG TitleIndex, const UNICODE_STRING *class, ULONG options,
35 PULONG dispos )
37 NTSTATUS ret;
38 DWORD len = attr->ObjectName->Length;
40 TRACE( "(0x%x,%s,%s,%lx,%lx,%p)\n", attr->RootDirectory, debugstr_us(attr->ObjectName),
41 debugstr_us(class), options, access, retkey );
43 if (len > MAX_NAME_LENGTH) return STATUS_BUFFER_OVERFLOW;
44 len += sizeof(WCHAR); /* for storing name length */
45 if (class)
47 len += class->Length;
48 if (len > REQUEST_MAX_VAR_SIZE) return STATUS_BUFFER_OVERFLOW;
50 if (!retkey) return STATUS_INVALID_PARAMETER;
52 SERVER_START_VAR_REQ( create_key, len )
54 WCHAR *data = server_data_ptr(req);
56 req->parent = attr->RootDirectory;
57 req->access = access;
58 req->options = options;
59 req->modif = 0;
61 *data++ = attr->ObjectName->Length;
62 memcpy( data, attr->ObjectName->Buffer, attr->ObjectName->Length );
63 if (class) memcpy( (char *)data + attr->ObjectName->Length, class->Buffer, class->Length );
64 if (!(ret = SERVER_CALL()))
66 *retkey = req->hkey;
67 if (dispos) *dispos = req->created ? REG_CREATED_NEW_KEY : REG_OPENED_EXISTING_KEY;
70 SERVER_END_VAR_REQ;
71 TRACE("<- 0x%04x\n", *retkey);
72 return ret;
76 /******************************************************************************
77 * NtOpenKey [NTDLL.129]
78 * ZwOpenKey
79 * OUT PHANDLE retkey (returns 0 when failure)
80 * IN ACCESS_MASK access
81 * IN POBJECT_ATTRIBUTES attr
83 NTSTATUS WINAPI NtOpenKey( PHANDLE retkey, ACCESS_MASK access, const OBJECT_ATTRIBUTES *attr )
85 NTSTATUS ret;
86 DWORD len = attr->ObjectName->Length;
88 TRACE( "(0x%x,%s,%lx,%p)\n", attr->RootDirectory,
89 debugstr_us(attr->ObjectName), access, retkey );
91 if (len > MAX_NAME_LENGTH) return STATUS_BUFFER_OVERFLOW;
92 if (!retkey) return STATUS_INVALID_PARAMETER;
94 SERVER_START_VAR_REQ( open_key, len )
96 req->parent = attr->RootDirectory;
97 req->access = access;
98 memcpy( server_data_ptr(req), attr->ObjectName->Buffer, len );
99 ret = SERVER_CALL();
100 *retkey = req->hkey;
102 SERVER_END_VAR_REQ;
103 TRACE("<- 0x%04x\n", *retkey);
104 return ret;
108 /******************************************************************************
109 * NtDeleteKey [NTDLL]
110 * ZwDeleteKey
112 NTSTATUS WINAPI NtDeleteKey( HANDLE hkey )
114 NTSTATUS ret;
116 TRACE( "(%x)\n", hkey );
118 SERVER_START_REQ( delete_key )
120 req->hkey = hkey;
121 ret = SERVER_CALL();
123 SERVER_END_REQ;
124 return ret;
128 /******************************************************************************
129 * NtDeleteValueKey [NTDLL]
130 * ZwDeleteValueKey
132 NTSTATUS WINAPI NtDeleteValueKey( HANDLE hkey, const UNICODE_STRING *name )
134 NTSTATUS ret;
136 TRACE( "(0x%x,%s)\n", hkey, debugstr_us(name) );
137 if (name->Length > MAX_NAME_LENGTH) return STATUS_BUFFER_OVERFLOW;
139 SERVER_START_VAR_REQ( delete_key_value, name->Length )
141 req->hkey = hkey;
142 memcpy( server_data_ptr(req), name->Buffer, name->Length );
143 ret = SERVER_CALL();
145 SERVER_END_VAR_REQ;
146 return ret;
150 /******************************************************************************
151 * fill_key_info
153 * Helper function for NtQueryKey and NtEnumerateKey
155 static NTSTATUS fill_key_info( KEY_INFORMATION_CLASS info_class, void *info, DWORD length,
156 DWORD *result_len, const struct enum_key_request *req )
158 WCHAR *name_ptr = server_data_ptr(req);
159 int name_size = *name_ptr++;
160 WCHAR *class_ptr = (WCHAR *)((char *)name_ptr + name_size);
161 int class_size = server_data_size(req) - sizeof(WCHAR) - name_size;
162 int fixed_size;
163 FILETIME modif;
165 RtlSecondsSince1970ToTime( req->modif, &modif );
167 switch(info_class)
169 case KeyBasicInformation:
171 KEY_BASIC_INFORMATION keyinfo;
172 fixed_size = sizeof(keyinfo) - sizeof(keyinfo.Name);
173 keyinfo.LastWriteTime = modif;
174 keyinfo.TitleIndex = 0;
175 keyinfo.NameLength = name_size;
176 memcpy( info, &keyinfo, min( length, fixed_size ) );
177 class_size = 0;
179 break;
180 case KeyFullInformation:
182 KEY_FULL_INFORMATION keyinfo;
183 fixed_size = sizeof(keyinfo) - sizeof(keyinfo.Class);
184 keyinfo.LastWriteTime = modif;
185 keyinfo.TitleIndex = 0;
186 keyinfo.ClassLength = class_size;
187 keyinfo.ClassOffset = keyinfo.ClassLength ? fixed_size : -1;
188 keyinfo.SubKeys = req->subkeys;
189 keyinfo.MaxNameLen = req->max_subkey;
190 keyinfo.MaxClassLen = req->max_class;
191 keyinfo.Values = req->values;
192 keyinfo.MaxValueNameLen = req->max_value;
193 keyinfo.MaxValueDataLen = req->max_data;
194 memcpy( info, &keyinfo, min( length, fixed_size ) );
195 name_size = 0;
197 break;
198 case KeyNodeInformation:
200 KEY_NODE_INFORMATION keyinfo;
201 fixed_size = sizeof(keyinfo) - sizeof(keyinfo.Name);
202 keyinfo.LastWriteTime = modif;
203 keyinfo.TitleIndex = 0;
204 keyinfo.ClassLength = class_size;
205 keyinfo.ClassOffset = fixed_size + name_size;
206 if (!keyinfo.ClassLength || keyinfo.ClassOffset > length) keyinfo.ClassOffset = -1;
207 keyinfo.NameLength = name_size;
208 memcpy( info, &keyinfo, min( length, fixed_size ) );
210 break;
211 default:
212 FIXME("Information class not implemented\n");
213 return STATUS_INVALID_PARAMETER;
216 *result_len = fixed_size + name_size + class_size;
217 if (length <= fixed_size) return STATUS_BUFFER_OVERFLOW;
218 length -= fixed_size;
220 /* copy the name */
221 if (name_size)
223 memcpy( (char *)info + fixed_size, name_ptr, min(length,name_size) );
224 if (length < name_size) return STATUS_BUFFER_OVERFLOW;
225 length -= name_size;
228 /* copy the class */
229 if (class_size)
231 memcpy( (char *)info + fixed_size + name_size, class_ptr, min(length,class_size) );
232 if (length < class_size) return STATUS_BUFFER_OVERFLOW;
234 return STATUS_SUCCESS;
239 /******************************************************************************
240 * NtEnumerateKey [NTDLL]
241 * ZwEnumerateKey
243 * NOTES
244 * the name copied into the buffer is NOT 0-terminated
246 NTSTATUS WINAPI NtEnumerateKey( HANDLE handle, ULONG index, KEY_INFORMATION_CLASS info_class,
247 void *info, DWORD length, DWORD *result_len )
249 NTSTATUS ret;
251 /* -1 means query key, so avoid it here */
252 if (index == (ULONG)-1) return STATUS_NO_MORE_ENTRIES;
254 SERVER_START_VAR_REQ( enum_key, REQUEST_MAX_VAR_SIZE )
256 req->hkey = handle;
257 req->index = index;
258 req->full = (info_class == KeyFullInformation);
259 if (!(ret = SERVER_CALL()))
261 ret = fill_key_info( info_class, info, length, result_len, req );
264 SERVER_END_VAR_REQ;
265 return ret;
269 /******************************************************************************
270 * NtQueryKey [NTDLL]
271 * ZwQueryKey
273 NTSTATUS WINAPI NtQueryKey( HANDLE handle, KEY_INFORMATION_CLASS info_class,
274 void *info, DWORD length, DWORD *result_len )
276 NTSTATUS ret;
278 SERVER_START_VAR_REQ( enum_key, REQUEST_MAX_VAR_SIZE )
280 req->hkey = handle;
281 req->index = -1;
282 req->full = (info_class == KeyFullInformation);
283 if (!(ret = SERVER_CALL()))
285 ret = fill_key_info( info_class, info, length, result_len, req );
288 SERVER_END_VAR_REQ;
289 return ret;
293 /* fill the key value info structure for a specific info class */
294 static void copy_key_value_info( KEY_VALUE_INFORMATION_CLASS info_class, void *info,
295 DWORD length, int type, int name_len, int data_len )
297 switch(info_class)
299 case KeyValueBasicInformation:
301 KEY_VALUE_BASIC_INFORMATION keyinfo;
302 keyinfo.TitleIndex = 0;
303 keyinfo.Type = type;
304 keyinfo.NameLength = name_len;
305 length = min( length, sizeof(keyinfo) - sizeof(keyinfo.Name) );
306 memcpy( info, &keyinfo, length );
307 break;
309 case KeyValueFullInformation:
311 KEY_VALUE_FULL_INFORMATION keyinfo;
312 keyinfo.TitleIndex = 0;
313 keyinfo.Type = type;
314 keyinfo.DataOffset = sizeof(keyinfo) - sizeof(keyinfo.Name) + name_len;
315 keyinfo.DataLength = data_len;
316 keyinfo.NameLength = name_len;
317 length = min( length, sizeof(keyinfo) - sizeof(keyinfo.Name) );
318 memcpy( info, &keyinfo, length );
319 break;
321 case KeyValuePartialInformation:
323 KEY_VALUE_PARTIAL_INFORMATION keyinfo;
324 keyinfo.TitleIndex = 0;
325 keyinfo.Type = type;
326 keyinfo.DataLength = data_len;
327 length = min( length, sizeof(keyinfo) - sizeof(keyinfo.Data) );
328 memcpy( info, &keyinfo, length );
329 break;
331 default:
332 break;
337 /******************************************************************************
338 * NtEnumerateValueKey [NTDLL]
339 * ZwEnumerateValueKey
341 NTSTATUS WINAPI NtEnumerateValueKey( HANDLE handle, ULONG index,
342 KEY_VALUE_INFORMATION_CLASS info_class,
343 void *info, DWORD length, DWORD *result_len )
345 NTSTATUS ret;
346 char *data_ptr, *name_ptr;
347 int fixed_size = 0, name_len = 0, data_len = 0, offset = 0, type = 0, total_len = 0;
349 TRACE( "(0x%x,%lu,%d,%p,%ld)\n", handle, index, info_class, info, length );
351 /* compute the length we want to retrieve */
352 switch(info_class)
354 case KeyValueBasicInformation:
355 fixed_size = sizeof(KEY_VALUE_BASIC_INFORMATION) - sizeof(WCHAR);
356 name_ptr = (char *)info + fixed_size;
357 data_ptr = NULL;
358 break;
359 case KeyValueFullInformation:
360 fixed_size = sizeof(KEY_VALUE_FULL_INFORMATION) - sizeof(WCHAR);
361 name_ptr = data_ptr = (char *)info + fixed_size;
362 break;
363 case KeyValuePartialInformation:
364 fixed_size = sizeof(KEY_VALUE_PARTIAL_INFORMATION) - sizeof(UCHAR);
365 name_ptr = NULL;
366 data_ptr = (char *)info + fixed_size;
367 break;
368 default:
369 FIXME( "Information class %d not implemented\n", info_class );
370 return STATUS_INVALID_PARAMETER;
372 if (length > fixed_size) data_len = length - fixed_size;
376 size_t reqlen = data_len + sizeof(WCHAR);
377 if (name_ptr && !offset) reqlen += MAX_PATH*sizeof(WCHAR);
378 reqlen = min( reqlen, REQUEST_MAX_VAR_SIZE );
380 SERVER_START_VAR_REQ( enum_key_value, reqlen )
382 req->hkey = handle;
383 req->index = index;
384 req->offset = offset;
386 if (!(ret = SERVER_CALL()))
388 size_t size = server_data_size(req) - sizeof(WCHAR);
389 WCHAR *name = server_data_ptr(req);
390 if (!offset) /* name is only present on the first request */
392 name_len = *name++;
393 size -= name_len;
394 if (name_ptr)
396 if (name_len > data_len) /* overflow */
398 memcpy( name_ptr, name, data_len );
399 data_len = 0;
400 ret = STATUS_BUFFER_OVERFLOW;
402 else
404 memcpy( name_ptr, name, name_len );
405 data_len -= name_len;
406 if (data_ptr) data_ptr += name_len;
409 name += name_len / sizeof(WCHAR);
411 else name++; /* skip 0 length */
413 if (data_ptr)
415 size = min( size, data_len );
416 memcpy( data_ptr + offset, name, size );
417 offset += size;
418 data_len -= size;
420 type = req->type;
421 total_len = req->len;
424 SERVER_END_VAR_REQ;
425 if (ret) return ret;
426 } while (data_len && data_ptr && offset < total_len);
428 *result_len = total_len + fixed_size + (name_ptr ? name_len : 0);
430 if (data_ptr && offset < total_len) ret = STATUS_BUFFER_OVERFLOW;
431 if (length < fixed_size) ret = STATUS_BUFFER_OVERFLOW;
433 copy_key_value_info( info_class, info, length, type, name_len, total_len );
434 return ret;
439 /******************************************************************************
440 * NtQueryValueKey [NTDLL]
441 * ZwQueryValueKey
443 * NOTES
444 * the name in the KeyValueInformation is never set
446 NTSTATUS WINAPI NtQueryValueKey( HANDLE handle, const UNICODE_STRING *name,
447 KEY_VALUE_INFORMATION_CLASS info_class,
448 void *info, DWORD length, DWORD *result_len )
450 NTSTATUS ret;
451 char *data_ptr;
452 int fixed_size = 0, data_len = 0, offset = 0, type = 0, total_len = 0;
454 TRACE( "(0x%x,%s,%d,%p,%ld)\n", handle, debugstr_us(name), info_class, info, length );
456 if (name->Length > MAX_NAME_LENGTH) return STATUS_BUFFER_OVERFLOW;
458 /* compute the length we want to retrieve */
459 switch(info_class)
461 case KeyValueBasicInformation:
462 fixed_size = sizeof(KEY_VALUE_BASIC_INFORMATION) - sizeof(WCHAR);
463 data_ptr = NULL;
464 break;
465 case KeyValueFullInformation:
466 fixed_size = sizeof(KEY_VALUE_FULL_INFORMATION) - sizeof(WCHAR);
467 data_ptr = (char *)info + fixed_size;
468 break;
469 case KeyValuePartialInformation:
470 fixed_size = sizeof(KEY_VALUE_PARTIAL_INFORMATION) - sizeof(UCHAR);
471 data_ptr = (char *)info + fixed_size;
472 break;
473 default:
474 FIXME( "Information class %d not implemented\n", info_class );
475 return STATUS_INVALID_PARAMETER;
477 if (data_ptr && length > fixed_size) data_len = length - fixed_size;
481 size_t reqlen = min( data_len, REQUEST_MAX_VAR_SIZE );
482 reqlen = max( reqlen, name->Length + sizeof(WCHAR) );
484 SERVER_START_VAR_REQ( get_key_value, reqlen )
486 WCHAR *nameptr = server_data_ptr(req);
488 req->hkey = handle;
489 req->offset = offset;
490 *nameptr++ = name->Length;
491 memcpy( nameptr, name->Buffer, name->Length );
493 if (!(ret = SERVER_CALL()))
495 size_t size = min( server_data_size(req), data_len );
496 type = req->type;
497 total_len = req->len;
498 if (size)
500 memcpy( data_ptr + offset, server_data_ptr(req), size );
501 offset += size;
502 data_len -= size;
506 SERVER_END_VAR_REQ;
507 if (ret) return ret;
508 } while (data_len && offset < total_len);
510 *result_len = total_len + fixed_size;
512 if (offset < total_len) ret = STATUS_BUFFER_OVERFLOW;
513 if (length < fixed_size) ret = STATUS_BUFFER_OVERFLOW;
515 copy_key_value_info( info_class, info, length, type, 0, total_len );
516 return ret;
520 /******************************************************************************
521 * NtFlushKey [NTDLL]
522 * ZwFlushKey
524 NTSTATUS WINAPI NtFlushKey(HANDLE KeyHandle)
526 FIXME("(0x%08x) stub!\n",
527 KeyHandle);
528 return 1;
531 /******************************************************************************
532 * NtLoadKey [NTDLL]
533 * ZwLoadKey
535 NTSTATUS WINAPI NtLoadKey( const OBJECT_ATTRIBUTES *attr, const OBJECT_ATTRIBUTES *file )
537 FIXME("stub!\n");
538 dump_ObjectAttributes(attr);
539 dump_ObjectAttributes(file);
540 return STATUS_SUCCESS;
543 /******************************************************************************
544 * NtNotifyChangeKey [NTDLL]
545 * ZwNotifyChangeKey
547 NTSTATUS WINAPI NtNotifyChangeKey(
548 IN HANDLE KeyHandle,
549 IN HANDLE Event,
550 IN PIO_APC_ROUTINE ApcRoutine OPTIONAL,
551 IN PVOID ApcContext OPTIONAL,
552 OUT PIO_STATUS_BLOCK IoStatusBlock,
553 IN ULONG CompletionFilter,
554 IN BOOLEAN Asynchroneous,
555 OUT PVOID ChangeBuffer,
556 IN ULONG Length,
557 IN BOOLEAN WatchSubtree)
559 FIXME("(0x%08x,0x%08x,%p,%p,%p,0x%08lx, 0x%08x,%p,0x%08lx,0x%08x) stub!\n",
560 KeyHandle, Event, ApcRoutine, ApcContext, IoStatusBlock, CompletionFilter,
561 Asynchroneous, ChangeBuffer, Length, WatchSubtree);
562 return STATUS_SUCCESS;
565 /******************************************************************************
566 * NtQueryMultipleValueKey [NTDLL]
567 * ZwQueryMultipleValueKey
570 NTSTATUS WINAPI NtQueryMultipleValueKey(
571 HANDLE KeyHandle,
572 PVALENTW ListOfValuesToQuery,
573 ULONG NumberOfItems,
574 PVOID MultipleValueInformation,
575 ULONG Length,
576 PULONG ReturnLength)
578 FIXME("(0x%08x,%p,0x%08lx,%p,0x%08lx,%p) stub!\n",
579 KeyHandle, ListOfValuesToQuery, NumberOfItems, MultipleValueInformation,
580 Length,ReturnLength);
581 return STATUS_SUCCESS;
584 /******************************************************************************
585 * NtReplaceKey [NTDLL]
586 * ZwReplaceKey
588 NTSTATUS WINAPI NtReplaceKey(
589 IN POBJECT_ATTRIBUTES ObjectAttributes,
590 IN HANDLE Key,
591 IN POBJECT_ATTRIBUTES ReplacedObjectAttributes)
593 FIXME("(0x%08x),stub!\n", Key);
594 dump_ObjectAttributes(ObjectAttributes);
595 dump_ObjectAttributes(ReplacedObjectAttributes);
596 return STATUS_SUCCESS;
598 /******************************************************************************
599 * NtRestoreKey [NTDLL]
600 * ZwRestoreKey
602 NTSTATUS WINAPI NtRestoreKey(
603 HANDLE KeyHandle,
604 HANDLE FileHandle,
605 ULONG RestoreFlags)
607 FIXME("(0x%08x,0x%08x,0x%08lx) stub\n",
608 KeyHandle, FileHandle, RestoreFlags);
609 return STATUS_SUCCESS;
611 /******************************************************************************
612 * NtSaveKey [NTDLL]
613 * ZwSaveKey
615 NTSTATUS WINAPI NtSaveKey(
616 IN HANDLE KeyHandle,
617 IN HANDLE FileHandle)
619 FIXME("(0x%08x,0x%08x) stub\n",
620 KeyHandle, FileHandle);
621 return STATUS_SUCCESS;
623 /******************************************************************************
624 * NtSetInformationKey [NTDLL]
625 * ZwSetInformationKey
627 NTSTATUS WINAPI NtSetInformationKey(
628 IN HANDLE KeyHandle,
629 IN const int KeyInformationClass,
630 IN PVOID KeyInformation,
631 IN ULONG KeyInformationLength)
633 FIXME("(0x%08x,0x%08x,%p,0x%08lx) stub\n",
634 KeyHandle, KeyInformationClass, KeyInformation, KeyInformationLength);
635 return STATUS_SUCCESS;
639 /******************************************************************************
640 * NtSetValueKey [NTDLL]
641 * ZwSetValueKey
643 * NOTES
644 * win95 does not care about count for REG_SZ and finds out the len by itself (js)
645 * NT does definitely care (aj)
647 NTSTATUS WINAPI NtSetValueKey( HANDLE hkey, const UNICODE_STRING *name, ULONG TitleIndex,
648 ULONG type, const void *data, ULONG count )
650 NTSTATUS ret;
651 ULONG namelen, pos;
653 TRACE( "(0x%x,%s,%ld,%p,%ld)\n", hkey, debugstr_us(name), type, data, count );
655 if (name->Length > MAX_NAME_LENGTH) return STATUS_BUFFER_OVERFLOW;
657 namelen = name->Length + sizeof(WCHAR); /* for storing length */
658 pos = 0;
662 ULONG len = count - pos;
663 if (len > REQUEST_MAX_VAR_SIZE - namelen) len = REQUEST_MAX_VAR_SIZE - namelen;
665 SERVER_START_VAR_REQ( set_key_value, namelen + len )
667 WCHAR *name_ptr = server_data_ptr(req);
669 req->hkey = hkey;
670 req->type = type;
671 req->total = count;
672 req->offset = pos;
673 *name_ptr++ = name->Length;
674 memcpy( name_ptr, name->Buffer, name->Length );
675 memcpy( (char *)name_ptr + name->Length, (char *)data + pos, len );
676 pos += len;
677 ret = SERVER_CALL();
679 SERVER_END_VAR_REQ;
680 } while (!ret && pos < count);
681 return ret;
684 /******************************************************************************
685 * NtUnloadKey [NTDLL]
686 * ZwUnloadKey
688 NTSTATUS WINAPI NtUnloadKey(
689 IN HANDLE KeyHandle)
691 FIXME("(0x%08x) stub\n",
692 KeyHandle);
693 return STATUS_SUCCESS;
696 /******************************************************************************
697 * RtlFormatCurrentUserKeyPath [NTDLL.371]
699 NTSTATUS WINAPI RtlFormatCurrentUserKeyPath(
700 IN OUT PUNICODE_STRING KeyPath)
702 /* LPSTR Path = "\\REGISTRY\\USER\\S-1-5-21-0000000000-000000000-0000000000-500";*/
703 LPSTR Path = "\\REGISTRY\\USER\\.DEFAULT";
704 ANSI_STRING AnsiPath;
706 FIXME("(%p) stub\n",KeyPath);
707 RtlInitAnsiString(&AnsiPath, Path);
708 return RtlAnsiStringToUnicodeString(KeyPath, &AnsiPath, TRUE);
711 /******************************************************************************
712 * RtlOpenCurrentUser [NTDLL]
714 * if we return just HKEY_CURRENT_USER the advapi try's to find a remote
715 * registry (odd handle) and fails
718 DWORD WINAPI RtlOpenCurrentUser(
719 IN ACCESS_MASK DesiredAccess, /* [in] */
720 OUT PHANDLE KeyHandle) /* [out] handle of HKEY_CURRENT_USER */
722 OBJECT_ATTRIBUTES ObjectAttributes;
723 UNICODE_STRING ObjectName;
724 NTSTATUS ret;
726 TRACE("(0x%08lx, %p) stub\n",DesiredAccess, KeyHandle);
728 RtlFormatCurrentUserKeyPath(&ObjectName);
729 InitializeObjectAttributes(&ObjectAttributes,&ObjectName,OBJ_CASE_INSENSITIVE,0, NULL);
730 ret = NtOpenKey(KeyHandle, DesiredAccess, &ObjectAttributes);
731 RtlFreeUnicodeString(&ObjectName);
732 return ret;