Merged the two serializer and unserializer functions into one, cleaned
[wine.git] / dlls / ntdll / reg.c
blob740fe0dd66df795459d3360d6eba106eb3b4b6dd
1 /*
2 * Registry functions
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
21 * NOTES:
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
28 #include "config.h"
29 #include "wine/port.h"
31 #include <string.h>
32 #include "wine/debug.h"
33 #include "winreg.h"
34 #include "winerror.h"
35 #include "wine/unicode.h"
36 #include "wine/server.h"
37 #include "ntddk.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,
52 PULONG dispos )
54 NTSTATUS ret;
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;
65 req->access = access;
66 req->options = options;
67 req->modif = 0;
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;
77 SERVER_END_REQ;
78 TRACE("<- 0x%04x\n", *retkey);
79 return ret;
83 /******************************************************************************
84 * NtOpenKey [NTDLL.@]
85 * ZwOpenKey [NTDLL.@]
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 )
93 NTSTATUS ret;
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;
110 SERVER_END_REQ;
111 TRACE("<- 0x%04x\n", *retkey);
112 return ret;
116 /******************************************************************************
117 * NtDeleteKey [NTDLL.@]
118 * ZwDeleteKey [NTDLL.@]
120 NTSTATUS WINAPI NtDeleteKey( HANDLE hkey )
122 NTSTATUS ret;
124 TRACE( "(%x)\n", hkey );
126 SERVER_START_REQ( delete_key )
128 req->hkey = hkey;
129 ret = wine_server_call( req );
131 SERVER_END_REQ;
132 return ret;
136 /******************************************************************************
137 * NtDeleteValueKey [NTDLL.@]
138 * ZwDeleteValueKey [NTDLL.@]
140 NTSTATUS WINAPI NtDeleteValueKey( HANDLE hkey, const UNICODE_STRING *name )
142 NTSTATUS ret;
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 )
149 req->hkey = hkey;
150 wine_server_add_data( req, name->Buffer, name->Length );
151 ret = wine_server_call( req );
153 SERVER_END_REQ;
154 return ret;
158 /******************************************************************************
159 * enumerate_key
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 )
167 NTSTATUS ret;
168 void *data_ptr;
169 size_t fixed_size;
171 switch(info_class)
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;
176 default:
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 )
184 req->hkey = handle;
185 req->index = index;
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 )))
190 LARGE_INTEGER modif;
192 RtlSecondsSince1970ToTime( reply->modif, (FILETIME *)&modif );
194 switch(info_class)
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 ) );
205 break;
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 ) );
222 break;
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 ) );
234 break;
236 *result_len = fixed_size + reply->total;
237 if (length < *result_len) ret = STATUS_BUFFER_OVERFLOW;
240 SERVER_END_REQ;
241 return ret;
246 /******************************************************************************
247 * NtEnumerateKey [NTDLL.@]
248 * ZwEnumerateKey [NTDLL.@]
250 * NOTES
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 )
277 switch(info_class)
279 case KeyValueBasicInformation:
281 KEY_VALUE_BASIC_INFORMATION keyinfo;
282 keyinfo.TitleIndex = 0;
283 keyinfo.Type = type;
284 keyinfo.NameLength = name_len;
285 length = min( length, (char *)keyinfo.Name - (char *)&keyinfo );
286 memcpy( info, &keyinfo, length );
287 break;
289 case KeyValueFullInformation:
291 KEY_VALUE_FULL_INFORMATION keyinfo;
292 keyinfo.TitleIndex = 0;
293 keyinfo.Type = type;
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 );
299 break;
301 case KeyValuePartialInformation:
303 KEY_VALUE_PARTIAL_INFORMATION keyinfo;
304 keyinfo.TitleIndex = 0;
305 keyinfo.Type = type;
306 keyinfo.DataLength = data_len;
307 length = min( length, (char *)keyinfo.Data - (char *)&keyinfo );
308 memcpy( info, &keyinfo, length );
309 break;
311 default:
312 break;
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 )
325 NTSTATUS ret;
326 void *ptr;
327 size_t fixed_size;
329 TRACE( "(0x%x,%lu,%d,%p,%ld)\n", handle, index, info_class, info, length );
331 /* compute the length we want to retrieve */
332 switch(info_class)
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;
337 default:
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 )
345 req->hkey = handle;
346 req->index = index;
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;
357 SERVER_END_REQ;
358 return ret;
362 /******************************************************************************
363 * NtQueryValueKey [NTDLL.@]
364 * ZwQueryValueKey [NTDLL.@]
366 * NOTES
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 )
373 NTSTATUS ret;
374 UCHAR *data_ptr;
375 int fixed_size = 0;
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 */
382 switch(info_class)
384 case KeyValueBasicInformation:
385 fixed_size = (char *)((KEY_VALUE_BASIC_INFORMATION *)info)->Name - (char *)info;
386 data_ptr = NULL;
387 break;
388 case KeyValueFullInformation:
389 data_ptr = (UCHAR *)((KEY_VALUE_FULL_INFORMATION *)info)->Name;
390 fixed_size = (char *)data_ptr - (char *)info;
391 break;
392 case KeyValuePartialInformation:
393 data_ptr = ((KEY_VALUE_PARTIAL_INFORMATION *)info)->Data;
394 fixed_size = (char *)data_ptr - (char *)info;
395 break;
396 default:
397 FIXME( "Information class %d not implemented\n", info_class );
398 return STATUS_INVALID_PARAMETER;
401 SERVER_START_REQ( get_key_value )
403 req->hkey = handle;
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;
414 SERVER_END_REQ;
415 return ret;
419 /******************************************************************************
420 * NtFlushKey [NTDLL.@]
421 * ZwFlushKey [NTDLL.@]
423 NTSTATUS WINAPI NtFlushKey(HANDLE KeyHandle)
425 FIXME("(0x%08x) stub!\n",
426 KeyHandle);
427 return 1;
430 /******************************************************************************
431 * NtLoadKey [NTDLL.@]
432 * ZwLoadKey [NTDLL.@]
434 NTSTATUS WINAPI NtLoadKey( const OBJECT_ATTRIBUTES *attr, const OBJECT_ATTRIBUTES *file )
436 FIXME("stub!\n");
437 dump_ObjectAttributes(attr);
438 dump_ObjectAttributes(file);
439 return STATUS_SUCCESS;
442 /******************************************************************************
443 * NtNotifyChangeKey [NTDLL.@]
444 * ZwNotifyChangeKey [NTDLL.@]
446 NTSTATUS WINAPI NtNotifyChangeKey(
447 IN HANDLE KeyHandle,
448 IN HANDLE Event,
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,
455 IN ULONG Length,
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(
470 HANDLE KeyHandle,
471 PVALENTW ListOfValuesToQuery,
472 ULONG NumberOfItems,
473 PVOID MultipleValueInformation,
474 ULONG Length,
475 PULONG ReturnLength)
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,
489 IN HANDLE Key,
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(
502 HANDLE KeyHandle,
503 HANDLE FileHandle,
504 ULONG RestoreFlags)
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(
515 IN HANDLE KeyHandle,
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(
527 IN HANDLE KeyHandle,
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.@]
542 * NOTES
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 )
549 NTSTATUS ret;
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 )
557 req->hkey = hkey;
558 req->type = type;
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 );
564 SERVER_END_REQ;
565 return ret;
568 /******************************************************************************
569 * NtUnloadKey [NTDLL.@]
570 * ZwUnloadKey [NTDLL.@]
572 NTSTATUS WINAPI NtUnloadKey(
573 IN HANDLE KeyHandle)
575 FIXME("(0x%08x) stub\n",
576 KeyHandle);
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;
608 NTSTATUS ret;
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);
616 return ret;