Cleaned up debug channels a bit.
[wine] / dlls / ntdll / reg.c
1 /*
2  *      registry functions
3  *
4  * NOTES:
5  *      HKEY_LOCAL_MACHINE      \\REGISTRY\\MACHINE
6  *      HKEY_USERS              \\REGISTRY\\USER
7  *      HKEY_CURRENT_CONFIG     \\REGISTRY\\MACHINE\\SYSTEM\\CURRENTCONTROLSET\\HARDWARE PROFILES\\CURRENT
8   *     HKEY_CLASSES            \\REGISTRY\\MACHINE\\SOFTWARE\\CLASSES
9  */
10
11 #include "debugtools.h"
12 #include "winreg.h"
13 #include "winerror.h"
14 #include "file.h"
15 #include "server.h"
16 #include "ntddk.h"
17 #include "crtdll.h"
18 #include "ntdll_misc.h"
19
20 DEFAULT_DEBUG_CHANNEL(ntdll);
21
22 /* copy a key name into the request buffer */
23 static inline NTSTATUS copy_nameU( LPWSTR Dest, PUNICODE_STRING Name, UINT Offset )
24 {
25         if (Name->Buffer) 
26         {
27           if ((Name->Length-Offset) > MAX_PATH) return STATUS_BUFFER_OVERFLOW;
28           lstrcpyW( Dest, Name->Buffer+Offset );
29         }
30         else Dest[0] = 0;
31         return STATUS_SUCCESS;
32 }
33
34 /* translates predefined paths to HKEY_ constants */
35 static BOOLEAN _NtKeyToWinKey(
36         IN POBJECT_ATTRIBUTES ObjectAttributes,
37         OUT UINT * Offset,      /* offset within ObjectName */
38         OUT HKEY * KeyHandle)   /* translated handle */
39 {
40         static const WCHAR KeyPath_HKLM[] = {
41                 '\\','R','E','G','I','S','T','R','Y',
42                 '\\','M','A','C','H','I','N','E',0};
43         static const WCHAR KeyPath_HKU [] = {
44                 '\\','R','E','G','I','S','T','R','Y',
45                 '\\','U','S','E','R',0};
46         static const WCHAR KeyPath_HCC [] = {
47                 '\\','R','E','G','I','S','T','R','Y',
48                 '\\','M','A','C','H','I','N','E',
49                 '\\','S','Y','S','T','E','M',
50                 '\\','C','U','R','R','E','N','T','C','O','N','T','R','O','L','S','E','T',
51                 '\\','H','A','R','D','W','A','R','E','P','R','O','F','I','L','E','S',
52                 '\\','C','U','R','R','E','N','T',0};
53         static const WCHAR KeyPath_HCR [] = {
54                 '\\','R','E','G','I','S','T','R','Y',
55                 '\\','M','A','C','H','I','N','E',
56                 '\\','S','O','F','T','W','A','R','E',
57                 '\\','C','L','A','S','S','E','S',0};
58         int len;
59         PUNICODE_STRING ObjectName = ObjectAttributes->ObjectName;
60
61         if(ObjectAttributes->RootDirectory)
62         {
63           len = 0;
64           *KeyHandle = ObjectAttributes->RootDirectory;
65         }
66         else if((ObjectName->Length > (len=lstrlenW(KeyPath_HKLM)))
67         && (0==CRTDLL__wcsnicmp(ObjectName->Buffer,KeyPath_HKLM,len)))
68         {  *KeyHandle = HKEY_LOCAL_MACHINE;
69         }
70         else if((ObjectName->Length > (len=lstrlenW(KeyPath_HKU)))
71         && (0==CRTDLL__wcsnicmp(ObjectName->Buffer,KeyPath_HKU,len)))
72         {  *KeyHandle = HKEY_USERS;
73         }
74         else if((ObjectName->Length > (len=lstrlenW(KeyPath_HCR)))
75         && (0==CRTDLL__wcsnicmp(ObjectName->Buffer,KeyPath_HCR,len)))
76         {  *KeyHandle = HKEY_CLASSES_ROOT;
77         }
78         else if((ObjectName->Length > (len=lstrlenW(KeyPath_HCC)))
79         && (0==CRTDLL__wcsnicmp(ObjectName->Buffer,KeyPath_HCC,len)))
80         {  *KeyHandle = HKEY_CURRENT_CONFIG;
81         }
82         else
83         {
84           *KeyHandle = 0;
85           *Offset = 0;
86           return FALSE;
87         }
88
89         if (len > 0 && ObjectName->Buffer[len] == (WCHAR)'\\') len++;
90         *Offset = len;
91
92         TRACE("off=%u hkey=0x%08x\n", *Offset, *KeyHandle);
93         return TRUE;
94 }
95
96 /******************************************************************************
97  * NtCreateKey [NTDLL]
98  * ZwCreateKey
99  */
100 NTSTATUS WINAPI NtCreateKey(
101         PHANDLE KeyHandle,
102         ACCESS_MASK DesiredAccess,
103         POBJECT_ATTRIBUTES ObjectAttributes,
104         ULONG TitleIndex,
105         PUNICODE_STRING Class,
106         ULONG CreateOptions,
107         PULONG Disposition)
108 {
109         struct create_key_request *req = get_req_buffer();
110         UINT ObjectNameOffset;
111         HKEY RootDirectory;
112         NTSTATUS ret;
113
114         TRACE("(%p,0x%08lx,0x%08lx,%p(%s),0x%08lx,%p)\n",
115         KeyHandle, DesiredAccess, TitleIndex, Class, debugstr_us(Class), CreateOptions, Disposition);
116         dump_ObjectAttributes(ObjectAttributes);
117
118         if (!KeyHandle)
119           return STATUS_INVALID_PARAMETER;
120
121         _NtKeyToWinKey(ObjectAttributes, &ObjectNameOffset, &RootDirectory);
122
123         req->parent  = RootDirectory;
124         req->access  = DesiredAccess;
125         req->options = CreateOptions;
126         req->modif   = time(NULL);
127
128         if (copy_nameU( req->name, ObjectAttributes->ObjectName, ObjectNameOffset ) != STATUS_SUCCESS) 
129           return STATUS_INVALID_PARAMETER;
130
131         if (Class)
132         {
133           int ClassLen = Class->Length+1;
134           if ( ClassLen*sizeof(WCHAR) > server_remaining(req->class)) return STATUS_BUFFER_OVERFLOW;
135           lstrcpynW( req->class, Class->Buffer, ClassLen);
136         }
137         else
138           req->class[0] = 0x0000;
139
140         if (!(ret = server_call_noerr(REQ_CREATE_KEY)))
141         {
142           *KeyHandle = req->hkey;
143           if (Disposition) *Disposition = req->created ? REG_CREATED_NEW_KEY : REG_OPENED_EXISTING_KEY;
144         }
145         return ret;
146 }
147
148 /******************************************************************************
149  * NtOpenKey [NTDLL.129]
150  * ZwOpenKey
151  *   OUT        PHANDLE                 KeyHandle (returns 0 when failure)
152  *   IN         ACCESS_MASK             DesiredAccess
153  *   IN         POBJECT_ATTRIBUTES      ObjectAttributes 
154  */
155 NTSTATUS WINAPI NtOpenKey(
156         PHANDLE KeyHandle,
157         ACCESS_MASK DesiredAccess,
158         POBJECT_ATTRIBUTES ObjectAttributes) 
159 {
160         struct open_key_request *req = get_req_buffer();
161         UINT ObjectNameOffset;
162         HKEY RootDirectory;
163         NTSTATUS ret;
164
165         TRACE("(%p,0x%08lx)\n", KeyHandle, DesiredAccess);
166         dump_ObjectAttributes(ObjectAttributes);
167
168         if (!KeyHandle) return STATUS_INVALID_PARAMETER;
169         *KeyHandle = 0;
170
171         _NtKeyToWinKey(ObjectAttributes, &ObjectNameOffset, &RootDirectory);
172
173         req->parent = RootDirectory;
174         req->access = DesiredAccess;
175
176         if (copy_nameU( req->name, ObjectAttributes->ObjectName, ObjectNameOffset ) != STATUS_SUCCESS) 
177           return STATUS_INVALID_PARAMETER;
178
179         if (!(ret = server_call_noerr(REQ_OPEN_KEY)))
180         {
181           *KeyHandle = req->hkey;
182         }
183         return ret;
184 }
185
186 /******************************************************************************
187  * NtDeleteKey [NTDLL]
188  * ZwDeleteKey
189  */
190 NTSTATUS WINAPI NtDeleteKey(HANDLE KeyHandle)
191 {
192         FIXME("(0x%08x) stub!\n",
193         KeyHandle);
194         return STATUS_SUCCESS;
195 }
196
197 /******************************************************************************
198  * NtDeleteValueKey [NTDLL]
199  * ZwDeleteValueKey
200  */
201 NTSTATUS WINAPI NtDeleteValueKey(
202         IN HANDLE KeyHandle,
203         IN PUNICODE_STRING ValueName)
204 {
205         FIXME("(0x%08x,%p(%s)) stub!\n",
206         KeyHandle, ValueName,debugstr_us(ValueName));
207         return STATUS_SUCCESS;
208 }
209
210 /******************************************************************************
211  * NtEnumerateKey [NTDLL]
212  * ZwEnumerateKey
213  *
214  * NOTES
215  *  the name copied into the buffer is NOT 0-terminated 
216  */
217 NTSTATUS WINAPI NtEnumerateKey(
218         HANDLE KeyHandle,
219         ULONG Index,
220         KEY_INFORMATION_CLASS KeyInformationClass,
221         PVOID KeyInformation,
222         ULONG Length,
223         PULONG ResultLength)
224 {
225         struct enum_key_request *req = get_req_buffer();
226         NTSTATUS ret;
227
228         TRACE("(0x%08x,0x%08lx,0x%08x,%p,0x%08lx,%p)\n",
229         KeyHandle, Index, KeyInformationClass, KeyInformation, Length, ResultLength);
230
231         req->hkey = KeyHandle;
232         req->index = Index;
233         if ((ret = server_call_noerr(REQ_ENUM_KEY)) != STATUS_SUCCESS) return ret;
234
235         switch (KeyInformationClass)
236         {
237           case KeyBasicInformation:
238             {
239               PKEY_BASIC_INFORMATION kbi = KeyInformation;
240               UINT NameLength = lstrlenW(req->name) * sizeof(WCHAR);
241               *ResultLength = sizeof(KEY_BASIC_INFORMATION) - sizeof(WCHAR) + NameLength;
242               if (Length < *ResultLength) return STATUS_BUFFER_OVERFLOW;
243
244               DOSFS_UnixTimeToFileTime(req->modif, &kbi->LastWriteTime, 0);
245               kbi->TitleIndex = 0;
246               kbi->NameLength = NameLength;
247               memcpy (kbi->Name, req->name, NameLength);
248             }
249             break;
250           case KeyFullInformation:
251             {
252               PKEY_FULL_INFORMATION kfi = KeyInformation;
253               kfi->ClassLength = lstrlenW(req->class) * sizeof(WCHAR);
254               kfi->ClassOffset = (kfi->ClassLength) ?
255                 sizeof(KEY_FULL_INFORMATION) - sizeof(WCHAR) : 0xffffffff;
256               *ResultLength = sizeof(KEY_FULL_INFORMATION) - sizeof(WCHAR) + kfi->ClassLength;
257               if (Length < *ResultLength) return STATUS_BUFFER_OVERFLOW;
258
259               DOSFS_UnixTimeToFileTime(req->modif, &kfi->LastWriteTime, 0);
260               kfi->TitleIndex = 0;
261 /*            kfi->SubKeys = req->subkeys;
262               kfi->MaxNameLength = req->max_subkey;
263               kfi->MaxClassLength = req->max_class;
264               kfi->Values = req->values;
265               kfi->MaxValueNameLen = req->max_value;
266               kfi->MaxValueDataLen = req->max_data;
267 */
268               FIXME("incomplete\n");
269               if (kfi->ClassLength) memcpy (kfi->Class, req->class, kfi->ClassLength);
270             }
271             break;
272           case KeyNodeInformation:
273             {
274               PKEY_NODE_INFORMATION kni = KeyInformation;
275               kni->ClassLength = lstrlenW(req->class) * sizeof(WCHAR);
276               kni->NameLength = lstrlenW(req->name) * sizeof(WCHAR);
277               kni->ClassOffset = (kni->ClassLength) ?
278                 sizeof(KEY_NODE_INFORMATION) - sizeof(WCHAR) + kni->NameLength : 0xffffffff;
279
280               *ResultLength = sizeof(KEY_NODE_INFORMATION) - sizeof(WCHAR) + kni->NameLength + kni->ClassLength;
281               if (Length < *ResultLength) return STATUS_BUFFER_OVERFLOW;
282
283               DOSFS_UnixTimeToFileTime(req->modif, &kni->LastWriteTime, 0);
284               kni->TitleIndex = 0;
285               memcpy (kni->Name, req->name, kni->NameLength);
286               if (kni->ClassLength) memcpy ((char *) KeyInformation + kni->ClassOffset, req->class, kni->ClassLength);
287             }
288             break;
289           default:
290             FIXME("KeyInformationClass not implemented\n");
291             return STATUS_UNSUCCESSFUL;
292         }
293         TRACE("buf=%lu len=%lu\n", Length, *ResultLength);
294         return ret;
295 }
296
297 /******************************************************************************
298  * NtQueryKey [NTDLL]
299  * ZwQueryKey
300  */
301 NTSTATUS WINAPI NtQueryKey(
302         HANDLE KeyHandle,
303         KEY_INFORMATION_CLASS KeyInformationClass,
304         PVOID KeyInformation,
305         ULONG Length,
306         PULONG ResultLength)
307 {
308         struct query_key_info_request *req = get_req_buffer();
309         NTSTATUS ret;
310         
311         TRACE("(0x%08x,0x%08x,%p,0x%08lx,%p) stub\n",
312         KeyHandle, KeyInformationClass, KeyInformation, Length, ResultLength);
313         
314         req->hkey = KeyHandle;
315         if ((ret = server_call_noerr(REQ_QUERY_KEY_INFO)) != STATUS_SUCCESS) return ret;
316         
317         switch (KeyInformationClass)
318         {
319           case KeyBasicInformation:
320             {
321               PKEY_BASIC_INFORMATION kbi = KeyInformation;
322               UINT NameLength = lstrlenW(req->name) * sizeof(WCHAR);
323               *ResultLength = sizeof(KEY_BASIC_INFORMATION) - sizeof(WCHAR) + NameLength;
324               if (Length < *ResultLength) return STATUS_BUFFER_OVERFLOW;
325
326               DOSFS_UnixTimeToFileTime(req->modif, &kbi->LastWriteTime, 0);
327               kbi->TitleIndex = 0;
328               kbi->NameLength = NameLength;
329               memcpy (kbi->Name, req->name, NameLength);
330             }
331             break;
332           case KeyFullInformation:
333             {
334               PKEY_FULL_INFORMATION kfi = KeyInformation;
335               kfi->ClassLength = lstrlenW(req->class) * sizeof(WCHAR);
336               kfi->ClassOffset = (kfi->ClassLength) ?
337                 sizeof(KEY_FULL_INFORMATION) - sizeof(WCHAR) : 0xffffffff;
338
339               *ResultLength = sizeof(KEY_FULL_INFORMATION) - sizeof(WCHAR) + kfi->ClassLength;
340               if (Length < *ResultLength) return STATUS_BUFFER_OVERFLOW;
341
342               DOSFS_UnixTimeToFileTime(req->modif, &kfi->LastWriteTime, 0);
343               kfi->TitleIndex = 0;
344               kfi->SubKeys = req->subkeys;
345               kfi->MaxNameLen = req->max_subkey;
346               kfi->MaxClassLen = req->max_class;
347               kfi->Values = req->values;
348               kfi->MaxValueNameLen = req->max_value;
349               kfi->MaxValueDataLen = req->max_data;
350               if(kfi->ClassLength) memcpy ((char *) KeyInformation + kfi->ClassOffset, req->class, kfi->ClassLength);
351             }
352             break;
353           case KeyNodeInformation:
354             {
355               PKEY_NODE_INFORMATION kni = KeyInformation;
356               kni->ClassLength = lstrlenW(req->class) * sizeof(WCHAR);
357               kni->NameLength = lstrlenW(req->name) * sizeof(WCHAR);
358               kni->ClassOffset = (kni->ClassLength) ?
359                 sizeof(KEY_NODE_INFORMATION) - sizeof(WCHAR) + kni->NameLength : 0xffffffff;
360
361               *ResultLength = sizeof(KEY_NODE_INFORMATION) - sizeof(WCHAR) + kni->NameLength + kni->ClassLength;
362               if (Length < *ResultLength) return STATUS_BUFFER_OVERFLOW;
363
364               DOSFS_UnixTimeToFileTime(req->modif, &kni->LastWriteTime, 0);
365               kni->TitleIndex = 0;
366               memcpy (kni->Name, req->name, kni->NameLength);
367               if(kni->ClassLength) memcpy ((char *) KeyInformation + kni->ClassOffset, req->class, kni->ClassLength);
368             }
369             break;
370           default:
371             FIXME("KeyInformationClass not implemented\n");
372             return STATUS_UNSUCCESSFUL;
373         }
374         return ret;
375 }
376
377 /******************************************************************************
378  *  NtEnumerateValueKey [NTDLL] 
379  *  ZwEnumerateValueKey
380  */
381 NTSTATUS WINAPI NtEnumerateValueKey(
382         HANDLE KeyHandle,
383         ULONG Index,
384         KEY_VALUE_INFORMATION_CLASS KeyInformationClass,
385         PVOID KeyInformation,
386         ULONG Length,
387         PULONG ResultLength)
388 {
389         struct enum_key_value_request *req = get_req_buffer();
390         UINT NameLength;
391         NTSTATUS ret;
392         
393         TRACE("(0x%08x,0x%08lx,0x%08x,%p,0x%08lx,%p)\n",
394         KeyHandle, Index, KeyInformationClass, KeyInformation, Length, ResultLength);
395
396         req->hkey = KeyHandle;
397         req->index = Index;
398         if ((ret = server_call_noerr(REQ_ENUM_KEY_VALUE)) != STATUS_SUCCESS) return ret;
399
400         switch (KeyInformationClass)
401         {
402           case KeyBasicInformation:
403             {
404               PKEY_VALUE_BASIC_INFORMATION kbi = KeyInformation;
405               
406               NameLength = lstrlenW(req->name) * sizeof(WCHAR);
407               *ResultLength = sizeof(KEY_VALUE_BASIC_INFORMATION) - sizeof(WCHAR) + NameLength;
408               if (*ResultLength > Length) return STATUS_BUFFER_TOO_SMALL;
409
410               kbi->TitleIndex = 0;
411               kbi->Type = req->type;
412               kbi->NameLength = NameLength;
413               memcpy(kbi->Name, req->name, kbi->NameLength);
414             }
415             break;
416           case KeyValueFullInformation:
417             {
418               PKEY_VALUE_FULL_INFORMATION kbi = KeyInformation;
419               UINT DataOffset;
420
421               NameLength = lstrlenW(req->name) * sizeof(WCHAR);
422               DataOffset = sizeof(KEY_VALUE_FULL_INFORMATION) - sizeof(WCHAR) + NameLength;
423               *ResultLength = DataOffset + req->len;
424
425               if (*ResultLength > Length) return STATUS_BUFFER_TOO_SMALL;
426
427               kbi->TitleIndex = 0;
428               kbi->Type = req->type;
429               kbi->DataOffset = DataOffset;
430               kbi->DataLength = req->len;
431               kbi->NameLength = NameLength;
432               memcpy(kbi->Name, req->name, kbi->NameLength);
433               memcpy(((LPBYTE)kbi) + DataOffset, req->data, req->len);
434             }
435             break;
436           case KeyValuePartialInformation:
437             {
438               PKEY_VALUE_PARTIAL_INFORMATION kbi = KeyInformation;
439               
440               *ResultLength = sizeof(KEY_VALUE_PARTIAL_INFORMATION) - sizeof(WCHAR) + req->len;
441
442               if (*ResultLength > Length) return STATUS_BUFFER_TOO_SMALL;
443
444               kbi->TitleIndex = 0;
445               kbi->Type = req->type;
446               kbi->DataLength = req->len;
447               memcpy(kbi->Data, req->data, req->len);
448             }
449             break;
450           default:
451             FIXME("not implemented\n");
452         }
453         return STATUS_SUCCESS;
454 }
455
456 /******************************************************************************
457  *  NtFlushKey  [NTDLL] 
458  *  ZwFlushKey
459  */
460 NTSTATUS WINAPI NtFlushKey(HANDLE KeyHandle)
461 {
462         FIXME("(0x%08x) stub!\n",
463         KeyHandle);
464         return 1;
465 }
466
467 /******************************************************************************
468  *  NtLoadKey   [NTDLL] 
469  *  ZwLoadKey
470  */
471 NTSTATUS WINAPI NtLoadKey(
472         PHANDLE KeyHandle,
473         POBJECT_ATTRIBUTES ObjectAttributes)
474 {
475         FIXME("(%p),stub!\n", KeyHandle);
476         dump_ObjectAttributes(ObjectAttributes);
477         return STATUS_SUCCESS;
478 }
479
480 /******************************************************************************
481  *  NtNotifyChangeKey   [NTDLL] 
482  *  ZwNotifyChangeKey
483  */
484 NTSTATUS WINAPI NtNotifyChangeKey(
485         IN HANDLE KeyHandle,
486         IN HANDLE Event,
487         IN PIO_APC_ROUTINE ApcRoutine OPTIONAL,
488         IN PVOID ApcContext OPTIONAL,
489         OUT PIO_STATUS_BLOCK IoStatusBlock,
490         IN ULONG CompletionFilter,
491         IN BOOLEAN Asynchroneous,
492         OUT PVOID ChangeBuffer,
493         IN ULONG Length,
494         IN BOOLEAN WatchSubtree)
495 {
496         FIXME("(0x%08x,0x%08x,%p,%p,%p,0x%08lx, 0x%08x,%p,0x%08lx,0x%08x) stub!\n",
497         KeyHandle, Event, ApcRoutine, ApcContext, IoStatusBlock, CompletionFilter,
498         Asynchroneous, ChangeBuffer, Length, WatchSubtree);
499         return STATUS_SUCCESS;
500 }
501
502 /******************************************************************************
503  * NtQueryMultipleValueKey [NTDLL]
504  * ZwQueryMultipleValueKey
505  */
506
507 NTSTATUS WINAPI NtQueryMultipleValueKey(
508         HANDLE KeyHandle,
509         PVALENTW ListOfValuesToQuery,
510         ULONG NumberOfItems,
511         PVOID MultipleValueInformation,
512         ULONG Length,
513         PULONG  ReturnLength)
514 {
515         FIXME("(0x%08x,%p,0x%08lx,%p,0x%08lx,%p) stub!\n",
516         KeyHandle, ListOfValuesToQuery, NumberOfItems, MultipleValueInformation,
517         Length,ReturnLength);
518         return STATUS_SUCCESS;
519 }
520
521 /******************************************************************************
522  * NtQueryValueKey [NTDLL]
523  * ZwQueryValueKey
524  *
525  * NOTES
526  *  the name in the KeyValueInformation is never set
527  */
528 NTSTATUS WINAPI NtQueryValueKey(
529         IN HANDLE KeyHandle,
530         IN PUNICODE_STRING ValueName,
531         IN KEY_VALUE_INFORMATION_CLASS KeyValueInformationClass,
532         OUT PVOID KeyValueInformation,
533         IN ULONG Length,
534         OUT PULONG ResultLength)
535 {
536         struct get_key_value_request *req = get_req_buffer();
537         NTSTATUS ret;
538
539         TRACE("(0x%08x,%s,0x%08x,%p,0x%08lx,%p)\n",
540         KeyHandle, debugstr_us(ValueName), KeyValueInformationClass, KeyValueInformation, Length, ResultLength);
541
542         req->hkey = KeyHandle;
543         if (copy_nameU(req->name, ValueName, 0) != STATUS_SUCCESS) return STATUS_BUFFER_OVERFLOW;
544         if ((ret = server_call_noerr(REQ_GET_KEY_VALUE)) != STATUS_SUCCESS) return ret;
545
546         switch(KeyValueInformationClass)
547         {
548           case KeyValueBasicInformation:
549             {
550               PKEY_VALUE_BASIC_INFORMATION kbi = (PKEY_VALUE_BASIC_INFORMATION) KeyValueInformation;
551               kbi->Type = req->type;
552
553               *ResultLength = sizeof(KEY_VALUE_BASIC_INFORMATION)-sizeof(WCHAR);
554               if (Length <= *ResultLength) return STATUS_BUFFER_OVERFLOW;
555               kbi->NameLength = 0;
556             }  
557             break;
558           case KeyValueFullInformation:
559             {
560               PKEY_VALUE_FULL_INFORMATION  kfi = (PKEY_VALUE_FULL_INFORMATION) KeyValueInformation;
561               ULONG DataOffset;
562               kfi->Type = req->type;
563
564               DataOffset = sizeof(KEY_VALUE_FULL_INFORMATION)-sizeof(WCHAR);
565               *ResultLength = DataOffset + req->len;
566               if (Length <= *ResultLength) return STATUS_BUFFER_OVERFLOW;
567
568               kfi->NameLength = 0;
569               kfi->DataOffset = DataOffset;
570               kfi->DataLength = req->len;
571               memcpy((char *) KeyValueInformation + DataOffset, req->data, req->len);
572             }  
573             break;
574           case KeyValuePartialInformation:
575             {
576               PKEY_VALUE_PARTIAL_INFORMATION kpi = (PKEY_VALUE_PARTIAL_INFORMATION) KeyValueInformation;
577               kpi->Type = req->type;
578
579               *ResultLength = sizeof(KEY_VALUE_FULL_INFORMATION)-sizeof(UCHAR)+req->len;
580               if (Length <= *ResultLength) return STATUS_BUFFER_OVERFLOW;
581
582               kpi->DataLength = req->len;
583               memcpy(kpi->Data, req->data, req->len);
584             }  
585             break;
586           default:
587             FIXME("KeyValueInformationClass not implemented\n");
588             return STATUS_UNSUCCESSFUL;
589           
590         }
591         return ret;
592 }
593
594 /******************************************************************************
595  * NtReplaceKey [NTDLL]
596  * ZwReplaceKey
597  */
598 NTSTATUS WINAPI NtReplaceKey(
599         IN POBJECT_ATTRIBUTES ObjectAttributes,
600         IN HANDLE Key,
601         IN POBJECT_ATTRIBUTES ReplacedObjectAttributes)
602 {
603         FIXME("(0x%08x),stub!\n", Key);
604         dump_ObjectAttributes(ObjectAttributes);
605         dump_ObjectAttributes(ReplacedObjectAttributes);
606         return STATUS_SUCCESS;
607 }
608 /******************************************************************************
609  * NtRestoreKey [NTDLL]
610  * ZwRestoreKey
611  */
612 NTSTATUS WINAPI NtRestoreKey(
613         HANDLE KeyHandle,
614         HANDLE FileHandle,
615         ULONG RestoreFlags)
616 {
617         FIXME("(0x%08x,0x%08x,0x%08lx) stub\n",
618         KeyHandle, FileHandle, RestoreFlags);
619         return STATUS_SUCCESS;
620 }
621 /******************************************************************************
622  * NtSaveKey [NTDLL]
623  * ZwSaveKey
624  */
625 NTSTATUS WINAPI NtSaveKey(
626         IN HANDLE KeyHandle,
627         IN HANDLE FileHandle)
628 {
629         FIXME("(0x%08x,0x%08x) stub\n",
630         KeyHandle, FileHandle);
631         return STATUS_SUCCESS;
632 }
633 /******************************************************************************
634  * NtSetInformationKey [NTDLL]
635  * ZwSetInformationKey
636  */
637 NTSTATUS WINAPI NtSetInformationKey(
638         IN HANDLE KeyHandle,
639         IN const int KeyInformationClass,
640         IN PVOID KeyInformation,
641         IN ULONG KeyInformationLength)
642 {
643         FIXME("(0x%08x,0x%08x,%p,0x%08lx) stub\n",
644         KeyHandle, KeyInformationClass, KeyInformation, KeyInformationLength);
645         return STATUS_SUCCESS;
646 }
647 /******************************************************************************
648  * NtSetValueKey [NTDLL]
649  * ZwSetValueKey
650  */
651 NTSTATUS WINAPI NtSetValueKey(
652         HANDLE KeyHandle,
653         PUNICODE_STRING ValueName,
654         ULONG TitleIndex,
655         ULONG Type,
656         PVOID Data,
657         ULONG DataSize)
658 {
659         FIXME("(0x%08x,%p(%s), 0x%08lx, 0x%08lx, %p, 0x%08lx) stub!\n",
660         KeyHandle, ValueName,debugstr_us(ValueName), TitleIndex, Type, Data, DataSize);
661         return STATUS_SUCCESS;
662
663 }
664
665 /******************************************************************************
666  * NtUnloadKey [NTDLL]
667  * ZwUnloadKey
668  */
669 NTSTATUS WINAPI NtUnloadKey(
670         IN HANDLE KeyHandle)
671 {
672         FIXME("(0x%08x) stub\n",
673         KeyHandle);
674         return STATUS_SUCCESS;
675 }
676
677 /******************************************************************************
678  *  RtlFormatCurrentUserKeyPath         [NTDLL.371] 
679  */
680 NTSTATUS WINAPI RtlFormatCurrentUserKeyPath(
681         IN OUT PUNICODE_STRING KeyPath)
682 {
683 /*      LPSTR Path = "\\REGISTRY\\USER\\S-1-5-21-0000000000-000000000-0000000000-500";*/
684         LPSTR Path = "\\REGISTRY\\USER\\.DEFAULT";
685         ANSI_STRING AnsiPath;
686
687         FIXME("(%p) stub\n",KeyPath);
688         RtlInitAnsiString(&AnsiPath, Path);
689         return RtlAnsiStringToUnicodeString(KeyPath, &AnsiPath, TRUE);
690 }
691
692 /******************************************************************************
693  *  RtlOpenCurrentUser          [NTDLL] 
694  *
695  * if we return just HKEY_CURRENT_USER the advapi try's to find a remote
696  * registry (odd handle) and fails
697  *
698  */
699 DWORD WINAPI RtlOpenCurrentUser(
700         IN ACCESS_MASK DesiredAccess,
701         OUT PHANDLE KeyHandle)  /* handle of HKEY_CURRENT_USER */
702 {
703         OBJECT_ATTRIBUTES ObjectAttributes;
704         UNICODE_STRING ObjectName;
705         NTSTATUS ret;
706
707         TRACE("(0x%08lx, %p) stub\n",DesiredAccess, KeyHandle);
708
709         RtlFormatCurrentUserKeyPath(&ObjectName);
710         InitializeObjectAttributes(&ObjectAttributes,&ObjectName,OBJ_CASE_INSENSITIVE,0, NULL);
711         ret = NtOpenKey(KeyHandle, DesiredAccess, &ObjectAttributes);
712         RtlFreeUnicodeString(&ObjectName);
713         return ret;
714 }