- add documentation section to README
[wine/dcerpc.git] / dlls / ntdll / reg.c
blobf271c0f71a77016c67181e15ffb0f41854cf875c
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 "wine/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 [NTDLL.@]
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;
39 TRACE( "(0x%x,%s,%s,%lx,%lx,%p)\n", attr->RootDirectory, debugstr_us(attr->ObjectName),
40 debugstr_us(class), options, access, retkey );
42 if (attr->ObjectName->Length > MAX_NAME_LENGTH) return STATUS_BUFFER_OVERFLOW;
43 if (!retkey) return STATUS_INVALID_PARAMETER;
45 SERVER_START_REQ( create_key )
47 req->parent = attr->RootDirectory;
48 req->access = access;
49 req->options = options;
50 req->modif = 0;
51 req->namelen = attr->ObjectName->Length;
52 wine_server_add_data( req, attr->ObjectName->Buffer, attr->ObjectName->Length );
53 if (class) wine_server_add_data( req, class->Buffer, class->Length );
54 if (!(ret = wine_server_call( req )))
56 *retkey = reply->hkey;
57 if (dispos) *dispos = reply->created ? REG_CREATED_NEW_KEY : REG_OPENED_EXISTING_KEY;
60 SERVER_END_REQ;
61 TRACE("<- 0x%04x\n", *retkey);
62 return ret;
66 /******************************************************************************
67 * NtOpenKey [NTDLL.@]
68 * ZwOpenKey [NTDLL.@]
70 * OUT PHANDLE retkey (returns 0 when failure)
71 * IN ACCESS_MASK access
72 * IN POBJECT_ATTRIBUTES attr
74 NTSTATUS WINAPI NtOpenKey( PHANDLE retkey, ACCESS_MASK access, const OBJECT_ATTRIBUTES *attr )
76 NTSTATUS ret;
77 DWORD len = attr->ObjectName->Length;
79 TRACE( "(0x%x,%s,%lx,%p)\n", attr->RootDirectory,
80 debugstr_us(attr->ObjectName), access, retkey );
82 if (len > MAX_NAME_LENGTH) return STATUS_BUFFER_OVERFLOW;
83 if (!retkey) return STATUS_INVALID_PARAMETER;
85 SERVER_START_REQ( open_key )
87 req->parent = attr->RootDirectory;
88 req->access = access;
89 wine_server_add_data( req, attr->ObjectName->Buffer, len );
90 ret = wine_server_call( req );
91 *retkey = reply->hkey;
93 SERVER_END_REQ;
94 TRACE("<- 0x%04x\n", *retkey);
95 return ret;
99 /******************************************************************************
100 * NtDeleteKey [NTDLL.@]
101 * ZwDeleteKey [NTDLL.@]
103 NTSTATUS WINAPI NtDeleteKey( HANDLE hkey )
105 NTSTATUS ret;
107 TRACE( "(%x)\n", hkey );
109 SERVER_START_REQ( delete_key )
111 req->hkey = hkey;
112 ret = wine_server_call( req );
114 SERVER_END_REQ;
115 return ret;
119 /******************************************************************************
120 * NtDeleteValueKey [NTDLL.@]
121 * ZwDeleteValueKey [NTDLL.@]
123 NTSTATUS WINAPI NtDeleteValueKey( HANDLE hkey, const UNICODE_STRING *name )
125 NTSTATUS ret;
127 TRACE( "(0x%x,%s)\n", hkey, debugstr_us(name) );
128 if (name->Length > MAX_NAME_LENGTH) return STATUS_BUFFER_OVERFLOW;
130 SERVER_START_REQ( delete_key_value )
132 req->hkey = hkey;
133 wine_server_add_data( req, name->Buffer, name->Length );
134 ret = wine_server_call( req );
136 SERVER_END_REQ;
137 return ret;
141 /******************************************************************************
142 * enumerate_key
144 * Implementation of NtQueryKey and NtEnumerateKey
146 static NTSTATUS enumerate_key( HANDLE handle, int index, KEY_INFORMATION_CLASS info_class,
147 void *info, DWORD length, DWORD *result_len )
150 NTSTATUS ret;
151 void *data_ptr;
152 size_t fixed_size;
154 switch(info_class)
156 case KeyBasicInformation: data_ptr = ((KEY_BASIC_INFORMATION *)info)->Name; break;
157 case KeyFullInformation: data_ptr = ((KEY_FULL_INFORMATION *)info)->Class; break;
158 case KeyNodeInformation: data_ptr = ((KEY_NODE_INFORMATION *)info)->Name; break;
159 default:
160 FIXME( "Information class %d not implemented\n", info_class );
161 return STATUS_INVALID_PARAMETER;
163 fixed_size = (char *)data_ptr - (char *)info;
165 SERVER_START_REQ( enum_key )
167 req->hkey = handle;
168 req->index = index;
169 req->info_class = info_class;
170 if (length > fixed_size) wine_server_set_reply( req, data_ptr, length - fixed_size );
171 if (!(ret = wine_server_call( req )))
173 LARGE_INTEGER modif;
175 RtlSecondsSince1970ToTime( reply->modif, (FILETIME *)&modif );
177 switch(info_class)
179 case KeyBasicInformation:
181 KEY_BASIC_INFORMATION keyinfo;
182 fixed_size = (char *)keyinfo.Name - (char *)&keyinfo;
183 keyinfo.LastWriteTime = modif;
184 keyinfo.TitleIndex = 0;
185 keyinfo.NameLength = reply->namelen;
186 memcpy( info, &keyinfo, min( length, fixed_size ) );
188 break;
189 case KeyFullInformation:
191 KEY_FULL_INFORMATION keyinfo;
192 fixed_size = (char *)keyinfo.Class - (char *)&keyinfo;
193 keyinfo.LastWriteTime = modif;
194 keyinfo.TitleIndex = 0;
195 keyinfo.ClassLength = wine_server_reply_size(reply);
196 keyinfo.ClassOffset = keyinfo.ClassLength ? fixed_size : -1;
197 keyinfo.SubKeys = reply->subkeys;
198 keyinfo.MaxNameLen = reply->max_subkey;
199 keyinfo.MaxClassLen = reply->max_class;
200 keyinfo.Values = reply->values;
201 keyinfo.MaxValueNameLen = reply->max_value;
202 keyinfo.MaxValueDataLen = reply->max_data;
203 memcpy( info, &keyinfo, min( length, fixed_size ) );
205 break;
206 case KeyNodeInformation:
208 KEY_NODE_INFORMATION keyinfo;
209 fixed_size = (char *)keyinfo.Name - (char *)&keyinfo;
210 keyinfo.LastWriteTime = modif;
211 keyinfo.TitleIndex = 0;
212 keyinfo.ClassLength = max( 0, wine_server_reply_size(reply) - reply->namelen );
213 keyinfo.ClassOffset = keyinfo.ClassLength ? fixed_size + reply->namelen : -1;
214 keyinfo.NameLength = reply->namelen;
215 memcpy( info, &keyinfo, min( length, fixed_size ) );
217 break;
219 *result_len = fixed_size + reply->total;
220 if (length < *result_len) ret = STATUS_BUFFER_OVERFLOW;
223 SERVER_END_REQ;
224 return ret;
229 /******************************************************************************
230 * NtEnumerateKey [NTDLL.@]
231 * ZwEnumerateKey [NTDLL.@]
233 * NOTES
234 * the name copied into the buffer is NOT 0-terminated
236 NTSTATUS WINAPI NtEnumerateKey( HANDLE handle, ULONG index, KEY_INFORMATION_CLASS info_class,
237 void *info, DWORD length, DWORD *result_len )
239 /* -1 means query key, so avoid it here */
240 if (index == (ULONG)-1) return STATUS_NO_MORE_ENTRIES;
241 return enumerate_key( handle, index, info_class, info, length, result_len );
245 /******************************************************************************
246 * NtQueryKey [NTDLL.@]
247 * ZwQueryKey [NTDLL.@]
249 NTSTATUS WINAPI NtQueryKey( HANDLE handle, KEY_INFORMATION_CLASS info_class,
250 void *info, DWORD length, DWORD *result_len )
252 return enumerate_key( handle, -1, info_class, info, length, result_len );
256 /* fill the key value info structure for a specific info class */
257 static void copy_key_value_info( KEY_VALUE_INFORMATION_CLASS info_class, void *info,
258 DWORD length, int type, int name_len, int data_len )
260 switch(info_class)
262 case KeyValueBasicInformation:
264 KEY_VALUE_BASIC_INFORMATION keyinfo;
265 keyinfo.TitleIndex = 0;
266 keyinfo.Type = type;
267 keyinfo.NameLength = name_len;
268 length = min( length, (char *)keyinfo.Name - (char *)&keyinfo );
269 memcpy( info, &keyinfo, length );
270 break;
272 case KeyValueFullInformation:
274 KEY_VALUE_FULL_INFORMATION keyinfo;
275 keyinfo.TitleIndex = 0;
276 keyinfo.Type = type;
277 keyinfo.DataOffset = (char *)keyinfo.Name - (char *)&keyinfo + name_len;
278 keyinfo.DataLength = data_len;
279 keyinfo.NameLength = name_len;
280 length = min( length, (char *)keyinfo.Name - (char *)&keyinfo );
281 memcpy( info, &keyinfo, length );
282 break;
284 case KeyValuePartialInformation:
286 KEY_VALUE_PARTIAL_INFORMATION keyinfo;
287 keyinfo.TitleIndex = 0;
288 keyinfo.Type = type;
289 keyinfo.DataLength = data_len;
290 length = min( length, (char *)keyinfo.Data - (char *)&keyinfo );
291 memcpy( info, &keyinfo, length );
292 break;
294 default:
295 break;
300 /******************************************************************************
301 * NtEnumerateValueKey [NTDLL.@]
302 * ZwEnumerateValueKey [NTDLL.@]
304 NTSTATUS WINAPI NtEnumerateValueKey( HANDLE handle, ULONG index,
305 KEY_VALUE_INFORMATION_CLASS info_class,
306 void *info, DWORD length, DWORD *result_len )
308 NTSTATUS ret;
309 void *ptr;
310 size_t fixed_size;
312 TRACE( "(0x%x,%lu,%d,%p,%ld)\n", handle, index, info_class, info, length );
314 /* compute the length we want to retrieve */
315 switch(info_class)
317 case KeyValueBasicInformation: ptr = ((KEY_VALUE_BASIC_INFORMATION *)info)->Name; break;
318 case KeyValueFullInformation: ptr = ((KEY_VALUE_FULL_INFORMATION *)info)->Name; break;
319 case KeyValuePartialInformation: ptr = ((KEY_VALUE_PARTIAL_INFORMATION *)info)->Data; break;
320 default:
321 FIXME( "Information class %d not implemented\n", info_class );
322 return STATUS_INVALID_PARAMETER;
324 fixed_size = (char *)ptr - (char *)info;
326 SERVER_START_REQ( enum_key_value )
328 req->hkey = handle;
329 req->index = index;
330 req->info_class = info_class;
331 if (length > fixed_size) wine_server_set_reply( req, ptr, length - fixed_size );
332 if (!(ret = wine_server_call( req )))
334 copy_key_value_info( info_class, info, length, reply->type, reply->namelen,
335 wine_server_reply_size(reply) - reply->namelen );
336 *result_len = fixed_size + reply->total;
337 if (length < *result_len) ret = STATUS_BUFFER_OVERFLOW;
340 SERVER_END_REQ;
341 return ret;
345 /******************************************************************************
346 * NtQueryValueKey [NTDLL.@]
347 * ZwQueryValueKey [NTDLL.@]
349 * NOTES
350 * the name in the KeyValueInformation is never set
352 NTSTATUS WINAPI NtQueryValueKey( HANDLE handle, const UNICODE_STRING *name,
353 KEY_VALUE_INFORMATION_CLASS info_class,
354 void *info, DWORD length, DWORD *result_len )
356 NTSTATUS ret;
357 UCHAR *data_ptr;
358 int fixed_size = 0;
360 TRACE( "(0x%x,%s,%d,%p,%ld)\n", handle, debugstr_us(name), info_class, info, length );
362 if (name->Length > MAX_NAME_LENGTH) return STATUS_BUFFER_OVERFLOW;
364 /* compute the length we want to retrieve */
365 switch(info_class)
367 case KeyValueBasicInformation:
368 fixed_size = (char *)((KEY_VALUE_BASIC_INFORMATION *)info)->Name - (char *)info;
369 data_ptr = NULL;
370 break;
371 case KeyValueFullInformation:
372 data_ptr = (UCHAR *)((KEY_VALUE_FULL_INFORMATION *)info)->Name;
373 fixed_size = (char *)data_ptr - (char *)info;
374 break;
375 case KeyValuePartialInformation:
376 data_ptr = ((KEY_VALUE_PARTIAL_INFORMATION *)info)->Data;
377 fixed_size = (char *)data_ptr - (char *)info;
378 break;
379 default:
380 FIXME( "Information class %d not implemented\n", info_class );
381 return STATUS_INVALID_PARAMETER;
384 SERVER_START_REQ( get_key_value )
386 req->hkey = handle;
387 wine_server_add_data( req, name->Buffer, name->Length );
388 if (length > fixed_size) wine_server_set_reply( req, data_ptr, length - fixed_size );
389 if (!(ret = wine_server_call( req )))
391 copy_key_value_info( info_class, info, length, reply->type,
392 0, wine_server_reply_size(reply) );
393 *result_len = fixed_size + reply->total;
394 if (length < *result_len) ret = STATUS_BUFFER_OVERFLOW;
397 SERVER_END_REQ;
398 return ret;
402 /******************************************************************************
403 * NtFlushKey [NTDLL.@]
404 * ZwFlushKey [NTDLL.@]
406 NTSTATUS WINAPI NtFlushKey(HANDLE KeyHandle)
408 FIXME("(0x%08x) stub!\n",
409 KeyHandle);
410 return 1;
413 /******************************************************************************
414 * NtLoadKey [NTDLL.@]
415 * ZwLoadKey [NTDLL.@]
417 NTSTATUS WINAPI NtLoadKey( const OBJECT_ATTRIBUTES *attr, const OBJECT_ATTRIBUTES *file )
419 FIXME("stub!\n");
420 dump_ObjectAttributes(attr);
421 dump_ObjectAttributes(file);
422 return STATUS_SUCCESS;
425 /******************************************************************************
426 * NtNotifyChangeKey [NTDLL.@]
427 * ZwNotifyChangeKey [NTDLL.@]
429 NTSTATUS WINAPI NtNotifyChangeKey(
430 IN HANDLE KeyHandle,
431 IN HANDLE Event,
432 IN PIO_APC_ROUTINE ApcRoutine OPTIONAL,
433 IN PVOID ApcContext OPTIONAL,
434 OUT PIO_STATUS_BLOCK IoStatusBlock,
435 IN ULONG CompletionFilter,
436 IN BOOLEAN Asynchroneous,
437 OUT PVOID ChangeBuffer,
438 IN ULONG Length,
439 IN BOOLEAN WatchSubtree)
441 FIXME("(0x%08x,0x%08x,%p,%p,%p,0x%08lx, 0x%08x,%p,0x%08lx,0x%08x) stub!\n",
442 KeyHandle, Event, ApcRoutine, ApcContext, IoStatusBlock, CompletionFilter,
443 Asynchroneous, ChangeBuffer, Length, WatchSubtree);
444 return STATUS_SUCCESS;
447 /******************************************************************************
448 * NtQueryMultipleValueKey [NTDLL]
449 * ZwQueryMultipleValueKey
452 NTSTATUS WINAPI NtQueryMultipleValueKey(
453 HANDLE KeyHandle,
454 PVALENTW ListOfValuesToQuery,
455 ULONG NumberOfItems,
456 PVOID MultipleValueInformation,
457 ULONG Length,
458 PULONG ReturnLength)
460 FIXME("(0x%08x,%p,0x%08lx,%p,0x%08lx,%p) stub!\n",
461 KeyHandle, ListOfValuesToQuery, NumberOfItems, MultipleValueInformation,
462 Length,ReturnLength);
463 return STATUS_SUCCESS;
466 /******************************************************************************
467 * NtReplaceKey [NTDLL.@]
468 * ZwReplaceKey [NTDLL.@]
470 NTSTATUS WINAPI NtReplaceKey(
471 IN POBJECT_ATTRIBUTES ObjectAttributes,
472 IN HANDLE Key,
473 IN POBJECT_ATTRIBUTES ReplacedObjectAttributes)
475 FIXME("(0x%08x),stub!\n", Key);
476 dump_ObjectAttributes(ObjectAttributes);
477 dump_ObjectAttributes(ReplacedObjectAttributes);
478 return STATUS_SUCCESS;
480 /******************************************************************************
481 * NtRestoreKey [NTDLL.@]
482 * ZwRestoreKey [NTDLL.@]
484 NTSTATUS WINAPI NtRestoreKey(
485 HANDLE KeyHandle,
486 HANDLE FileHandle,
487 ULONG RestoreFlags)
489 FIXME("(0x%08x,0x%08x,0x%08lx) stub\n",
490 KeyHandle, FileHandle, RestoreFlags);
491 return STATUS_SUCCESS;
493 /******************************************************************************
494 * NtSaveKey [NTDLL.@]
495 * ZwSaveKey [NTDLL.@]
497 NTSTATUS WINAPI NtSaveKey(
498 IN HANDLE KeyHandle,
499 IN HANDLE FileHandle)
501 FIXME("(0x%08x,0x%08x) stub\n",
502 KeyHandle, FileHandle);
503 return STATUS_SUCCESS;
505 /******************************************************************************
506 * NtSetInformationKey [NTDLL.@]
507 * ZwSetInformationKey [NTDLL.@]
509 NTSTATUS WINAPI NtSetInformationKey(
510 IN HANDLE KeyHandle,
511 IN const int KeyInformationClass,
512 IN PVOID KeyInformation,
513 IN ULONG KeyInformationLength)
515 FIXME("(0x%08x,0x%08x,%p,0x%08lx) stub\n",
516 KeyHandle, KeyInformationClass, KeyInformation, KeyInformationLength);
517 return STATUS_SUCCESS;
521 /******************************************************************************
522 * NtSetValueKey [NTDLL.@]
523 * ZwSetValueKey [NTDLL.@]
525 * NOTES
526 * win95 does not care about count for REG_SZ and finds out the len by itself (js)
527 * NT does definitely care (aj)
529 NTSTATUS WINAPI NtSetValueKey( HANDLE hkey, const UNICODE_STRING *name, ULONG TitleIndex,
530 ULONG type, const void *data, ULONG count )
532 NTSTATUS ret;
534 TRACE( "(0x%x,%s,%ld,%p,%ld)\n", hkey, debugstr_us(name), type, data, count );
536 if (name->Length > MAX_NAME_LENGTH) return STATUS_BUFFER_OVERFLOW;
538 SERVER_START_REQ( set_key_value )
540 req->hkey = hkey;
541 req->type = type;
542 req->namelen = name->Length;
543 wine_server_add_data( req, name->Buffer, name->Length );
544 wine_server_add_data( req, data, count );
545 ret = wine_server_call( req );
547 SERVER_END_REQ;
548 return ret;
551 /******************************************************************************
552 * NtUnloadKey [NTDLL.@]
553 * ZwUnloadKey [NTDLL.@]
555 NTSTATUS WINAPI NtUnloadKey(
556 IN HANDLE KeyHandle)
558 FIXME("(0x%08x) stub\n",
559 KeyHandle);
560 return STATUS_SUCCESS;
563 /******************************************************************************
564 * RtlFormatCurrentUserKeyPath [NTDLL.@]
566 NTSTATUS WINAPI RtlFormatCurrentUserKeyPath(
567 IN OUT PUNICODE_STRING KeyPath)
569 /* LPSTR Path = "\\REGISTRY\\USER\\S-1-5-21-0000000000-000000000-0000000000-500";*/
570 LPSTR Path = "\\REGISTRY\\USER\\.DEFAULT";
571 ANSI_STRING AnsiPath;
573 FIXME("(%p) stub\n",KeyPath);
574 RtlInitAnsiString(&AnsiPath, Path);
575 return RtlAnsiStringToUnicodeString(KeyPath, &AnsiPath, TRUE);
578 /******************************************************************************
579 * RtlOpenCurrentUser [NTDLL.@]
581 * if we return just HKEY_CURRENT_USER the advapi tries to find a remote
582 * registry (odd handle) and fails
585 DWORD WINAPI RtlOpenCurrentUser(
586 IN ACCESS_MASK DesiredAccess, /* [in] */
587 OUT PHANDLE KeyHandle) /* [out] handle of HKEY_CURRENT_USER */
589 OBJECT_ATTRIBUTES ObjectAttributes;
590 UNICODE_STRING ObjectName;
591 NTSTATUS ret;
593 TRACE("(0x%08lx, %p) stub\n",DesiredAccess, KeyHandle);
595 RtlFormatCurrentUserKeyPath(&ObjectName);
596 InitializeObjectAttributes(&ObjectAttributes,&ObjectName,OBJ_CASE_INSENSITIVE,0, NULL);
597 ret = NtOpenKey(KeyHandle, DesiredAccess, &ObjectAttributes);
598 RtlFreeUnicodeString(&ObjectName);
599 return ret;