New set of macros for server calls; makes requests without variable
[wine/multimedia.git] / dlls / advapi32 / registry.c
blobd327a4e6aef9528cbfdaf70e9fbefee027b55635
1 /*
2 * Registry management
4 * Copyright (C) 1999 Alexandre Julliard
6 * Based on misc/registry.c code
7 * Copyright (C) 1996 Marcus Meissner
8 * Copyright (C) 1998 Matthew Becker
9 * Copyright (C) 1999 Sylvain St-Germain
11 * This file is concerned about handle management and interaction with the Wine server.
12 * Registry file I/O is in misc/registry.c.
15 #include <stdlib.h>
16 #include <stdio.h>
17 #include <unistd.h>
19 #include "winbase.h"
20 #include "winreg.h"
21 #include "winerror.h"
22 #include "wine/unicode.h"
23 #include "heap.h"
24 #include "server.h"
25 #include "debugtools.h"
27 DEFAULT_DEBUG_CHANNEL(reg);
30 /* check if value type needs string conversion (Ansi<->Unicode) */
31 static inline int is_string( DWORD type )
33 return (type == REG_SZ) || (type == REG_EXPAND_SZ) || (type == REG_MULTI_SZ);
37 /******************************************************************************
38 * RegCreateKeyExW [ADVAPI32.@]
40 * PARAMS
41 * hkey [I] Handle of an open key
42 * name [I] Address of subkey name
43 * reserved [I] Reserved - must be 0
44 * class [I] Address of class string
45 * options [I] Special options flag
46 * access [I] Desired security access
47 * sa [I] Address of key security structure
48 * retkey [O] Address of buffer for opened handle
49 * dispos [O] Receives REG_CREATED_NEW_KEY or REG_OPENED_EXISTING_KEY
51 * NOTES
52 * in case of failing retkey remains untouched
54 DWORD WINAPI RegCreateKeyExW( HKEY hkey, LPCWSTR name, DWORD reserved, LPWSTR class,
55 DWORD options, REGSAM access, SECURITY_ATTRIBUTES *sa,
56 LPHKEY retkey, LPDWORD dispos )
58 OBJECT_ATTRIBUTES attr;
59 UNICODE_STRING nameW, classW;
61 if (reserved) return ERROR_INVALID_PARAMETER;
62 if (!(access & KEY_ALL_ACCESS) || (access & ~KEY_ALL_ACCESS)) return ERROR_ACCESS_DENIED;
64 attr.Length = sizeof(attr);
65 attr.RootDirectory = hkey;
66 attr.ObjectName = &nameW;
67 attr.Attributes = 0;
68 attr.SecurityDescriptor = NULL;
69 attr.SecurityQualityOfService = NULL;
70 RtlInitUnicodeString( &nameW, name );
71 RtlInitUnicodeString( &classW, class );
73 return RtlNtStatusToDosError( NtCreateKey( retkey, access, &attr, 0,
74 &classW, options, dispos ) );
78 /******************************************************************************
79 * RegCreateKeyExA [ADVAPI32.@]
81 DWORD WINAPI RegCreateKeyExA( HKEY hkey, LPCSTR name, DWORD reserved, LPSTR class,
82 DWORD options, REGSAM access, SECURITY_ATTRIBUTES *sa,
83 LPHKEY retkey, LPDWORD dispos )
85 OBJECT_ATTRIBUTES attr;
86 UNICODE_STRING nameW, classW;
87 ANSI_STRING nameA, classA;
88 NTSTATUS status;
90 if (reserved) return ERROR_INVALID_PARAMETER;
91 if (!(access & KEY_ALL_ACCESS) || (access & ~KEY_ALL_ACCESS)) return ERROR_ACCESS_DENIED;
93 attr.Length = sizeof(attr);
94 attr.RootDirectory = hkey;
95 attr.ObjectName = &nameW;
96 attr.Attributes = 0;
97 attr.SecurityDescriptor = NULL;
98 attr.SecurityQualityOfService = NULL;
99 RtlInitAnsiString( &nameA, name );
100 RtlInitAnsiString( &classA, class );
102 /* FIXME: should use Unicode buffer in TEB */
103 if (!(status = RtlAnsiStringToUnicodeString( &nameW, &nameA, TRUE )))
105 if (!(status = RtlAnsiStringToUnicodeString( &classW, &classA, TRUE )))
107 status = NtCreateKey( retkey, access, &attr, 0, &classW, options, dispos );
108 RtlFreeUnicodeString( &classW );
110 RtlFreeUnicodeString( &nameW );
112 return RtlNtStatusToDosError( status );
116 /******************************************************************************
117 * RegCreateKeyW [ADVAPI32.@]
119 DWORD WINAPI RegCreateKeyW( HKEY hkey, LPCWSTR name, LPHKEY retkey )
121 /* FIXME: previous implementation converted ERROR_INVALID_HANDLE to ERROR_BADKEY, */
122 /* but at least my version of NT (4.0 SP5) doesn't do this. -- AJ */
123 return RegCreateKeyExW( hkey, name, 0, NULL, REG_OPTION_NON_VOLATILE,
124 KEY_ALL_ACCESS, NULL, retkey, NULL );
128 /******************************************************************************
129 * RegCreateKeyA [ADVAPI32.@]
131 DWORD WINAPI RegCreateKeyA( HKEY hkey, LPCSTR name, LPHKEY retkey )
133 return RegCreateKeyExA( hkey, name, 0, NULL, REG_OPTION_NON_VOLATILE,
134 KEY_ALL_ACCESS, NULL, retkey, NULL );
139 /******************************************************************************
140 * RegOpenKeyExW [ADVAPI32.@]
142 * Opens the specified key
144 * Unlike RegCreateKeyEx, this does not create the key if it does not exist.
146 * PARAMS
147 * hkey [I] Handle of open key
148 * name [I] Name of subkey to open
149 * reserved [I] Reserved - must be zero
150 * access [I] Security access mask
151 * retkey [O] Handle to open key
153 * RETURNS
154 * Success: ERROR_SUCCESS
155 * Failure: Error code
157 * NOTES
158 * in case of failing is retkey = 0
160 DWORD WINAPI RegOpenKeyExW( HKEY hkey, LPCWSTR name, DWORD reserved, REGSAM access, LPHKEY retkey )
162 OBJECT_ATTRIBUTES attr;
163 UNICODE_STRING nameW;
165 attr.Length = sizeof(attr);
166 attr.RootDirectory = hkey;
167 attr.ObjectName = &nameW;
168 attr.Attributes = 0;
169 attr.SecurityDescriptor = NULL;
170 attr.SecurityQualityOfService = NULL;
171 RtlInitUnicodeString( &nameW, name );
172 return RtlNtStatusToDosError( NtOpenKey( retkey, access, &attr ) );
176 /******************************************************************************
177 * RegOpenKeyExA [ADVAPI32.@]
179 DWORD WINAPI RegOpenKeyExA( HKEY hkey, LPCSTR name, DWORD reserved, REGSAM access, LPHKEY retkey )
181 OBJECT_ATTRIBUTES attr;
182 UNICODE_STRING nameW;
183 STRING nameA;
184 NTSTATUS status;
186 attr.Length = sizeof(attr);
187 attr.RootDirectory = hkey;
188 attr.ObjectName = &nameW;
189 attr.Attributes = 0;
190 attr.SecurityDescriptor = NULL;
191 attr.SecurityQualityOfService = NULL;
193 RtlInitAnsiString( &nameA, name );
194 /* FIXME: should use Unicode buffer in TEB */
195 if (!(status = RtlAnsiStringToUnicodeString( &nameW, &nameA, TRUE )))
197 status = NtOpenKey( retkey, access, &attr );
198 RtlFreeUnicodeString( &nameW );
200 return RtlNtStatusToDosError( status );
204 /******************************************************************************
205 * RegOpenKeyW [ADVAPI32.@]
207 * PARAMS
208 * hkey [I] Handle of open key
209 * name [I] Address of name of subkey to open
210 * retkey [O] Handle to open key
212 * RETURNS
213 * Success: ERROR_SUCCESS
214 * Failure: Error code
216 * NOTES
217 * in case of failing is retkey = 0
219 DWORD WINAPI RegOpenKeyW( HKEY hkey, LPCWSTR name, LPHKEY retkey )
221 return RegOpenKeyExW( hkey, name, 0, KEY_ALL_ACCESS, retkey );
225 /******************************************************************************
226 * RegOpenKeyA [ADVAPI32.@]
228 DWORD WINAPI RegOpenKeyA( HKEY hkey, LPCSTR name, LPHKEY retkey )
230 return RegOpenKeyExA( hkey, name, 0, KEY_ALL_ACCESS, retkey );
234 /******************************************************************************
235 * RegOpenCurrentUser [ADVAPI32.@]
236 * FIXME: This function is supposed to retrieve a handle to the
237 * HKEY_CURRENT_USER for the user the current thread is impersonating.
238 * Since Wine does not currently allow threads to impersonate other users,
239 * this stub should work fine.
241 DWORD WINAPI RegOpenCurrentUser( REGSAM access, PHKEY retkey )
243 return RegOpenKeyExA( HKEY_CURRENT_USER, "", 0, access, retkey );
248 /******************************************************************************
249 * RegEnumKeyExW [ADVAPI32.@]
251 * PARAMS
252 * hkey [I] Handle to key to enumerate
253 * index [I] Index of subkey to enumerate
254 * name [O] Buffer for subkey name
255 * name_len [O] Size of subkey buffer
256 * reserved [I] Reserved
257 * class [O] Buffer for class string
258 * class_len [O] Size of class buffer
259 * ft [O] Time key last written to
261 DWORD WINAPI RegEnumKeyExW( HKEY hkey, DWORD index, LPWSTR name, LPDWORD name_len,
262 LPDWORD reserved, LPWSTR class, LPDWORD class_len, FILETIME *ft )
264 NTSTATUS status;
265 char buffer[256], *buf_ptr = buffer;
266 KEY_NODE_INFORMATION *info = (KEY_NODE_INFORMATION *)buffer;
267 DWORD total_size;
269 TRACE( "(0x%x,%ld,%p,%p(%ld),%p,%p,%p,%p)\n", hkey, index, name, name_len,
270 name_len ? *name_len : -1, reserved, class, class_len, ft );
272 if (reserved) return ERROR_INVALID_PARAMETER;
274 status = NtEnumerateKey( hkey, index, KeyNodeInformation,
275 buffer, sizeof(buffer), &total_size );
277 while (status == STATUS_BUFFER_OVERFLOW)
279 /* retry with a dynamically allocated buffer */
280 if (buf_ptr != buffer) HeapFree( GetProcessHeap(), 0, buf_ptr );
281 if (!(buf_ptr = HeapAlloc( GetProcessHeap(), 0, total_size )))
282 return ERROR_NOT_ENOUGH_MEMORY;
283 info = (KEY_NODE_INFORMATION *)buf_ptr;
284 status = NtEnumerateKey( hkey, index, KeyNodeInformation,
285 buf_ptr, total_size, &total_size );
288 if (!status)
290 DWORD len = info->NameLength / sizeof(WCHAR);
291 DWORD cls_len = info->ClassLength / sizeof(WCHAR);
293 if (ft) *ft = info->LastWriteTime;
295 if (len >= *name_len || (class_len && (cls_len >= *class_len)))
296 status = STATUS_BUFFER_OVERFLOW;
297 else
299 *name_len = len;
300 memcpy( name, info->Name, info->NameLength );
301 name[len] = 0;
302 if (class_len)
304 *class_len = cls_len;
305 if (class)
307 memcpy( class, buf_ptr + info->ClassOffset, info->ClassLength );
308 class[cls_len] = 0;
314 if (buf_ptr != buffer) HeapFree( GetProcessHeap(), 0, buf_ptr );
315 return RtlNtStatusToDosError( status );
319 /******************************************************************************
320 * RegEnumKeyExA [ADVAPI32.@]
322 DWORD WINAPI RegEnumKeyExA( HKEY hkey, DWORD index, LPSTR name, LPDWORD name_len,
323 LPDWORD reserved, LPSTR class, LPDWORD class_len, FILETIME *ft )
325 NTSTATUS status;
326 char buffer[256], *buf_ptr = buffer;
327 KEY_NODE_INFORMATION *info = (KEY_NODE_INFORMATION *)buffer;
328 DWORD total_size;
330 TRACE( "(0x%x,%ld,%p,%p(%ld),%p,%p,%p,%p)\n", hkey, index, name, name_len,
331 name_len ? *name_len : -1, reserved, class, class_len, ft );
333 if (reserved) return ERROR_INVALID_PARAMETER;
335 status = NtEnumerateKey( hkey, index, KeyNodeInformation,
336 buffer, sizeof(buffer), &total_size );
338 while (status == STATUS_BUFFER_OVERFLOW)
340 /* retry with a dynamically allocated buffer */
341 if (buf_ptr != buffer) HeapFree( GetProcessHeap(), 0, buf_ptr );
342 if (!(buf_ptr = HeapAlloc( GetProcessHeap(), 0, total_size )))
343 return ERROR_NOT_ENOUGH_MEMORY;
344 info = (KEY_NODE_INFORMATION *)buf_ptr;
345 status = NtEnumerateKey( hkey, index, KeyNodeInformation,
346 buf_ptr, total_size, &total_size );
349 if (!status)
351 DWORD len = WideCharToMultiByte( CP_ACP, 0, info->Name, info->NameLength/sizeof(WCHAR),
352 NULL, 0, NULL, NULL );
353 DWORD cls_len = WideCharToMultiByte( CP_ACP, 0, (WCHAR *)(buf_ptr + info->ClassOffset),
354 info->ClassLength / sizeof(WCHAR),
355 NULL, 0, NULL, NULL );
357 if (ft) *ft = info->LastWriteTime;
359 if (len >= *name_len || (class_len && (cls_len >= *class_len)))
360 status = STATUS_BUFFER_OVERFLOW;
361 else
363 *name_len = len;
364 WideCharToMultiByte( CP_ACP, 0, info->Name, info->NameLength/sizeof(WCHAR),
365 name, len, NULL, NULL );
366 name[len] = 0;
367 if (class_len)
369 *class_len = cls_len;
370 if (class)
372 WideCharToMultiByte( CP_ACP, 0, (WCHAR *)(buf_ptr + info->ClassOffset),
373 info->ClassLength / sizeof(WCHAR),
374 class, cls_len, NULL, NULL );
375 class[cls_len] = 0;
381 if (buf_ptr != buffer) HeapFree( GetProcessHeap(), 0, buf_ptr );
382 return RtlNtStatusToDosError( status );
386 /******************************************************************************
387 * RegEnumKeyW [ADVAPI32.@]
389 DWORD WINAPI RegEnumKeyW( HKEY hkey, DWORD index, LPWSTR name, DWORD name_len )
391 return RegEnumKeyExW( hkey, index, name, &name_len, NULL, NULL, NULL, NULL );
395 /******************************************************************************
396 * RegEnumKeyA [ADVAPI32.@]
398 DWORD WINAPI RegEnumKeyA( HKEY hkey, DWORD index, LPSTR name, DWORD name_len )
400 return RegEnumKeyExA( hkey, index, name, &name_len, NULL, NULL, NULL, NULL );
404 /******************************************************************************
405 * RegQueryInfoKeyW [ADVAPI32.@]
407 * PARAMS
408 * hkey [I] Handle to key to query
409 * class [O] Buffer for class string
410 * class_len [O] Size of class string buffer
411 * reserved [I] Reserved
412 * subkeys [O] Buffer for number of subkeys
413 * max_subkey [O] Buffer for longest subkey name length
414 * max_class [O] Buffer for longest class string length
415 * values [O] Buffer for number of value entries
416 * max_value [O] Buffer for longest value name length
417 * max_data [O] Buffer for longest value data length
418 * security [O] Buffer for security descriptor length
419 * modif [O] Modification time
421 * - win95 allows class to be valid and class_len to be NULL
422 * - winnt returns ERROR_INVALID_PARAMETER if class is valid and class_len is NULL
423 * - both allow class to be NULL and class_len to be NULL
424 * (it's hard to test validity, so test !NULL instead)
426 DWORD WINAPI RegQueryInfoKeyW( HKEY hkey, LPWSTR class, LPDWORD class_len, LPDWORD reserved,
427 LPDWORD subkeys, LPDWORD max_subkey, LPDWORD max_class,
428 LPDWORD values, LPDWORD max_value, LPDWORD max_data,
429 LPDWORD security, FILETIME *modif )
431 NTSTATUS status;
432 char buffer[256], *buf_ptr = buffer;
433 KEY_FULL_INFORMATION *info = (KEY_FULL_INFORMATION *)buffer;
434 DWORD total_size;
436 TRACE( "(0x%x,%p,%ld,%p,%p,%p,%p,%p,%p,%p,%p)\n", hkey, class, class_len ? *class_len : 0,
437 reserved, subkeys, max_subkey, values, max_value, max_data, security, modif );
439 if (class && !class_len && !(GetVersion() & 0x80000000 /*NT*/))
440 return ERROR_INVALID_PARAMETER;
442 status = NtQueryKey( hkey, KeyFullInformation, buffer, sizeof(buffer), &total_size );
443 if (status && status != STATUS_BUFFER_OVERFLOW) goto done;
445 if (class)
447 /* retry with a dynamically allocated buffer */
448 while (status == STATUS_BUFFER_OVERFLOW)
450 if (buf_ptr != buffer) HeapFree( GetProcessHeap(), 0, buf_ptr );
451 if (!(buf_ptr = HeapAlloc( GetProcessHeap(), 0, total_size )))
452 return ERROR_NOT_ENOUGH_MEMORY;
453 info = (KEY_FULL_INFORMATION *)buf_ptr;
454 status = NtQueryKey( hkey, KeyFullInformation, buf_ptr, total_size, &total_size );
457 if (status) goto done;
459 if (class_len && (info->ClassLength/sizeof(WCHAR) + 1 > *class_len))
461 status = STATUS_BUFFER_OVERFLOW;
463 else
465 memcpy( class, buf_ptr + info->ClassOffset, info->ClassLength );
466 class[info->ClassLength/sizeof(WCHAR)] = 0;
469 else status = STATUS_SUCCESS;
471 if (class_len) *class_len = info->ClassLength / sizeof(WCHAR);
472 if (subkeys) *subkeys = info->SubKeys;
473 if (max_subkey) *max_subkey = info->MaxNameLen;
474 if (max_class) *max_class = info->MaxClassLen;
475 if (values) *values = info->Values;
476 if (max_value) *max_value = info->MaxValueNameLen;
477 if (max_data) *max_data = info->MaxValueDataLen;
478 if (modif) *modif = info->LastWriteTime;
480 done:
481 if (buf_ptr != buffer) HeapFree( GetProcessHeap(), 0, buf_ptr );
482 return RtlNtStatusToDosError( status );
486 /******************************************************************************
487 * RegQueryInfoKeyA [ADVAPI32.@]
489 DWORD WINAPI RegQueryInfoKeyA( HKEY hkey, LPSTR class, LPDWORD class_len, LPDWORD reserved,
490 LPDWORD subkeys, LPDWORD max_subkey, LPDWORD max_class,
491 LPDWORD values, LPDWORD max_value, LPDWORD max_data,
492 LPDWORD security, FILETIME *modif )
494 NTSTATUS status;
495 char buffer[256], *buf_ptr = buffer;
496 KEY_FULL_INFORMATION *info = (KEY_FULL_INFORMATION *)buffer;
497 DWORD total_size, len;
499 TRACE( "(0x%x,%p,%ld,%p,%p,%p,%p,%p,%p,%p,%p)\n", hkey, class, class_len ? *class_len : 0,
500 reserved, subkeys, max_subkey, values, max_value, max_data, security, modif );
502 if (class && !class_len && !(GetVersion() & 0x80000000 /*NT*/))
503 return ERROR_INVALID_PARAMETER;
505 status = NtQueryKey( hkey, KeyFullInformation, buffer, sizeof(buffer), &total_size );
506 if (status && status != STATUS_BUFFER_OVERFLOW) goto done;
508 if (class || class_len)
510 /* retry with a dynamically allocated buffer */
511 while (status == STATUS_BUFFER_OVERFLOW)
513 if (buf_ptr != buffer) HeapFree( GetProcessHeap(), 0, buf_ptr );
514 if (!(buf_ptr = HeapAlloc( GetProcessHeap(), 0, total_size )))
515 return ERROR_NOT_ENOUGH_MEMORY;
516 info = (KEY_FULL_INFORMATION *)buf_ptr;
517 status = NtQueryKey( hkey, KeyFullInformation, buf_ptr, total_size, &total_size );
520 if (status) goto done;
522 len = WideCharToMultiByte( CP_ACP, 0,
523 (WCHAR *)(buf_ptr + info->ClassOffset),
524 info->ClassLength/sizeof(WCHAR),
525 NULL, 0, NULL, NULL );
526 if (class_len)
528 if (len + 1 > *class_len) status = STATUS_BUFFER_OVERFLOW;
529 *class_len = len;
531 if (class && !status)
533 WideCharToMultiByte( CP_ACP, 0,
534 (WCHAR *)(buf_ptr + info->ClassOffset),
535 info->ClassLength/sizeof(WCHAR),
536 class, len, NULL, NULL );
537 class[len] = 0;
540 else status = STATUS_SUCCESS;
542 if (subkeys) *subkeys = info->SubKeys;
543 if (max_subkey) *max_subkey = info->MaxNameLen;
544 if (max_class) *max_class = info->MaxClassLen;
545 if (values) *values = info->Values;
546 if (max_value) *max_value = info->MaxValueNameLen;
547 if (max_data) *max_data = info->MaxValueDataLen;
548 if (modif) *modif = info->LastWriteTime;
550 done:
551 if (buf_ptr != buffer) HeapFree( GetProcessHeap(), 0, buf_ptr );
552 return RtlNtStatusToDosError( status );
556 /******************************************************************************
557 * RegCloseKey [ADVAPI32.@]
559 * Releases the handle of the specified key
561 * PARAMS
562 * hkey [I] Handle of key to close
564 * RETURNS
565 * Success: ERROR_SUCCESS
566 * Failure: Error code
568 DWORD WINAPI RegCloseKey( HKEY hkey )
570 if (!hkey || hkey >= 0x80000000) return ERROR_SUCCESS;
571 return RtlNtStatusToDosError( NtClose( hkey ) );
575 /******************************************************************************
576 * RegDeleteKeyW [ADVAPI32.@]
578 * PARAMS
579 * hkey [I] Handle to open key
580 * name [I] Name of subkey to delete
582 * RETURNS
583 * Success: ERROR_SUCCESS
584 * Failure: Error code
586 DWORD WINAPI RegDeleteKeyW( HKEY hkey, LPCWSTR name )
588 DWORD ret;
589 HKEY tmp;
591 if (!name || !*name) return NtDeleteKey( hkey );
592 if (!(ret = RegOpenKeyExW( hkey, name, 0, 0, &tmp )))
594 ret = RtlNtStatusToDosError( NtDeleteKey( tmp ) );
595 RegCloseKey( tmp );
597 return ret;
601 /******************************************************************************
602 * RegDeleteKeyA [ADVAPI32.@]
604 DWORD WINAPI RegDeleteKeyA( HKEY hkey, LPCSTR name )
606 DWORD ret;
607 HKEY tmp;
609 if (!name || !*name) return NtDeleteKey( hkey );
610 if (!(ret = RegOpenKeyExA( hkey, name, 0, 0, &tmp )))
612 ret = RtlNtStatusToDosError( NtDeleteKey( tmp ) );
613 RegCloseKey( tmp );
615 return ret;
620 /******************************************************************************
621 * RegSetValueExW [ADVAPI32.@]
623 * Sets the data and type of a value under a register key
625 * PARAMS
626 * hkey [I] Handle of key to set value for
627 * name [I] Name of value to set
628 * reserved [I] Reserved - must be zero
629 * type [I] Flag for value type
630 * data [I] Address of value data
631 * count [I] Size of value data
633 * RETURNS
634 * Success: ERROR_SUCCESS
635 * Failure: Error code
637 * NOTES
638 * win95 does not care about count for REG_SZ and finds out the len by itself (js)
639 * NT does definitely care (aj)
641 DWORD WINAPI RegSetValueExW( HKEY hkey, LPCWSTR name, DWORD reserved,
642 DWORD type, CONST BYTE *data, DWORD count )
644 UNICODE_STRING nameW;
646 if (count && is_string(type))
648 LPCWSTR str = (LPCWSTR)data;
649 /* if user forgot to count terminating null, add it (yes NT does this) */
650 if (str[count / sizeof(WCHAR) - 1] && !str[count / sizeof(WCHAR)])
651 count += sizeof(WCHAR);
654 RtlInitUnicodeString( &nameW, name );
655 return RtlNtStatusToDosError( NtSetValueKey( hkey, &nameW, 0, type, data, count ) );
659 /******************************************************************************
660 * RegSetValueExA [ADVAPI32.@]
662 DWORD WINAPI RegSetValueExA( HKEY hkey, LPCSTR name, DWORD reserved, DWORD type,
663 CONST BYTE *data, DWORD count )
665 UNICODE_STRING nameW;
666 ANSI_STRING nameA;
667 WCHAR *dataW = NULL;
668 NTSTATUS status;
670 if (count && is_string(type))
672 /* if user forgot to count terminating null, add it (yes NT does this) */
673 if (data[count-1] && !data[count]) count++;
676 if (is_string( type )) /* need to convert to Unicode */
678 DWORD lenW = MultiByteToWideChar( CP_ACP, 0, data, count, NULL, 0 );
679 if (!(dataW = HeapAlloc( GetProcessHeap(), 0, lenW*sizeof(WCHAR) )))
680 return ERROR_OUTOFMEMORY;
681 MultiByteToWideChar( CP_ACP, 0, data, count, dataW, lenW );
682 count = lenW * sizeof(WCHAR);
683 data = (BYTE *)dataW;
686 RtlInitAnsiString( &nameA, name );
687 /* FIXME: should use Unicode buffer in TEB */
688 if (!(status = RtlAnsiStringToUnicodeString( &nameW, &nameA, TRUE )))
690 status = NtSetValueKey( hkey, &nameW, 0, type, data, count );
691 RtlFreeUnicodeString( &nameW );
693 if (dataW) HeapFree( GetProcessHeap(), 0, dataW );
694 return RtlNtStatusToDosError( status );
698 /******************************************************************************
699 * RegSetValueW [ADVAPI32.@]
701 DWORD WINAPI RegSetValueW( HKEY hkey, LPCWSTR name, DWORD type, LPCWSTR data, DWORD count )
703 HKEY subkey = hkey;
704 DWORD ret;
706 TRACE("(0x%x,%s,%ld,%s,%ld)\n", hkey, debugstr_w(name), type, debugstr_w(data), count );
708 if (type != REG_SZ) return ERROR_INVALID_PARAMETER;
710 if (name && name[0]) /* need to create the subkey */
712 if ((ret = RegCreateKeyW( hkey, name, &subkey )) != ERROR_SUCCESS) return ret;
715 ret = RegSetValueExW( subkey, NULL, 0, REG_SZ, (LPBYTE)data,
716 (strlenW( data ) + 1) * sizeof(WCHAR) );
717 if (subkey != hkey) RegCloseKey( subkey );
718 return ret;
722 /******************************************************************************
723 * RegSetValueA [ADVAPI32.@]
725 DWORD WINAPI RegSetValueA( HKEY hkey, LPCSTR name, DWORD type, LPCSTR data, DWORD count )
727 HKEY subkey = hkey;
728 DWORD ret;
730 TRACE("(0x%x,%s,%ld,%s,%ld)\n", hkey, debugstr_a(name), type, debugstr_a(data), count );
732 if (type != REG_SZ) return ERROR_INVALID_PARAMETER;
734 if (name && name[0]) /* need to create the subkey */
736 if ((ret = RegCreateKeyA( hkey, name, &subkey )) != ERROR_SUCCESS) return ret;
738 ret = RegSetValueExA( subkey, NULL, 0, REG_SZ, (LPBYTE)data, strlen(data)+1 );
739 if (subkey != hkey) RegCloseKey( subkey );
740 return ret;
745 /******************************************************************************
746 * RegQueryValueExW [ADVAPI32.@]
748 * Retrieves type and data for a specified name associated with an open key
750 * PARAMS
751 * hkey [I] Handle of key to query
752 * name [I] Name of value to query
753 * reserved [I] Reserved - must be NULL
754 * type [O] Address of buffer for value type. If NULL, the type
755 * is not required.
756 * data [O] Address of data buffer. If NULL, the actual data is
757 * not required.
758 * count [I/O] Address of data buffer size
760 * RETURNS
761 * ERROR_SUCCESS: Success
762 * ERROR_MORE_DATA: !!! if the specified buffer is not big enough to hold the data
763 * buffer is left untouched. The MS-documentation is wrong (js) !!!
765 DWORD WINAPI RegQueryValueExW( HKEY hkey, LPCWSTR name, LPDWORD reserved, LPDWORD type,
766 LPBYTE data, LPDWORD count )
768 NTSTATUS status;
769 UNICODE_STRING name_str;
770 DWORD total_size;
771 char buffer[256], *buf_ptr = buffer;
772 KEY_VALUE_PARTIAL_INFORMATION *info = (KEY_VALUE_PARTIAL_INFORMATION *)buffer;
773 static const int info_size = sizeof(*info) - sizeof(info->Data);
775 TRACE("(0x%x,%s,%p,%p,%p,%p=%ld)\n",
776 hkey, debugstr_w(name), reserved, type, data, count, count ? *count : 0 );
778 if ((data && !count) || reserved) return ERROR_INVALID_PARAMETER;
780 RtlInitUnicodeString( &name_str, name );
782 if (data) total_size = min( sizeof(buffer), *count + info_size );
783 else total_size = info_size;
785 status = NtQueryValueKey( hkey, &name_str, KeyValuePartialInformation,
786 buffer, total_size, &total_size );
787 if (status && status != STATUS_BUFFER_OVERFLOW) goto done;
789 if (data)
791 /* retry with a dynamically allocated buffer */
792 while (status == STATUS_BUFFER_OVERFLOW && total_size - info_size <= *count)
794 if (buf_ptr != buffer) HeapFree( GetProcessHeap(), 0, buf_ptr );
795 if (!(buf_ptr = HeapAlloc( GetProcessHeap(), 0, total_size )))
796 return ERROR_NOT_ENOUGH_MEMORY;
797 info = (KEY_VALUE_PARTIAL_INFORMATION *)buf_ptr;
798 status = NtQueryValueKey( hkey, &name_str, KeyValuePartialInformation,
799 buf_ptr, total_size, &total_size );
802 if (!status)
804 memcpy( data, buf_ptr + info_size, total_size - info_size );
805 /* if the type is REG_SZ and data is not 0-terminated
806 * and there is enough space in the buffer NT appends a \0 */
807 if (total_size - info_size <= *count-sizeof(WCHAR) && is_string(info->Type))
809 WCHAR *ptr = (WCHAR *)(data + total_size - info_size);
810 if (ptr > (WCHAR *)data && ptr[-1]) *ptr = 0;
813 else if (status != STATUS_BUFFER_OVERFLOW) goto done;
815 else status = STATUS_SUCCESS;
817 if (type) *type = info->Type;
818 if (count) *count = total_size - info_size;
820 done:
821 if (buf_ptr != buffer) HeapFree( GetProcessHeap(), 0, buf_ptr );
822 return RtlNtStatusToDosError(status);
826 /******************************************************************************
827 * RegQueryValueExA [ADVAPI32.@]
829 * NOTES:
830 * the documentation is wrong: if the buffer is too small it remains untouched
832 DWORD WINAPI RegQueryValueExA( HKEY hkey, LPCSTR name, LPDWORD reserved, LPDWORD type,
833 LPBYTE data, LPDWORD count )
835 NTSTATUS status;
836 ANSI_STRING nameA;
837 UNICODE_STRING nameW;
838 DWORD total_size;
839 char buffer[256], *buf_ptr = buffer;
840 KEY_VALUE_PARTIAL_INFORMATION *info = (KEY_VALUE_PARTIAL_INFORMATION *)buffer;
841 static const int info_size = sizeof(*info) - sizeof(info->Data);
843 TRACE("(0x%x,%s,%p,%p,%p,%p=%ld)\n",
844 hkey, debugstr_a(name), reserved, type, data, count, count ? *count : 0 );
846 if ((data && !count) || reserved) return ERROR_INVALID_PARAMETER;
848 RtlInitAnsiString( &nameA, name );
849 /* FIXME: should use Unicode buffer in TEB */
850 if ((status = RtlAnsiStringToUnicodeString( &nameW, &nameA, TRUE )))
851 return RtlNtStatusToDosError(status);
853 status = NtQueryValueKey( hkey, &nameW, KeyValuePartialInformation,
854 buffer, sizeof(buffer), &total_size );
855 if (status && status != STATUS_BUFFER_OVERFLOW) goto done;
857 /* we need to fetch the contents for a string type even if not requested,
858 * because we need to compute the length of the ASCII string. */
859 if (data || is_string(info->Type))
861 /* retry with a dynamically allocated buffer */
862 while (status == STATUS_BUFFER_OVERFLOW)
864 if (buf_ptr != buffer) HeapFree( GetProcessHeap(), 0, buf_ptr );
865 if (!(buf_ptr = HeapAlloc( GetProcessHeap(), 0, total_size )))
867 status = STATUS_NO_MEMORY;
868 goto done;
870 info = (KEY_VALUE_PARTIAL_INFORMATION *)buf_ptr;
871 status = NtQueryValueKey( hkey, &nameW, KeyValuePartialInformation,
872 buf_ptr, total_size, &total_size );
875 if (status) goto done;
877 if (is_string(info->Type))
879 DWORD len = WideCharToMultiByte( CP_ACP, 0, (WCHAR *)(buf_ptr + info_size),
880 (total_size - info_size) /sizeof(WCHAR),
881 NULL, 0, NULL, NULL );
882 if (data && len)
884 if (len > *count) status = STATUS_BUFFER_OVERFLOW;
885 else
887 WideCharToMultiByte( CP_ACP, 0, (WCHAR *)(buf_ptr + info_size),
888 (total_size - info_size) /sizeof(WCHAR),
889 data, len, NULL, NULL );
890 /* if the type is REG_SZ and data is not 0-terminated
891 * and there is enough space in the buffer NT appends a \0 */
892 if (len < *count && data[len-1]) data[len] = 0;
895 total_size = len + info_size;
897 else if (data)
899 if (total_size - info_size > *count) status = STATUS_BUFFER_OVERFLOW;
900 else memcpy( data, buf_ptr + info_size, total_size - info_size );
903 else status = STATUS_SUCCESS;
905 if (type) *type = info->Type;
906 if (count) *count = total_size - info_size;
908 done:
909 if (buf_ptr != buffer) HeapFree( GetProcessHeap(), 0, buf_ptr );
910 RtlFreeUnicodeString( &nameW );
911 return RtlNtStatusToDosError(status);
915 /******************************************************************************
916 * RegQueryValueW [ADVAPI32.@]
918 DWORD WINAPI RegQueryValueW( HKEY hkey, LPCWSTR name, LPWSTR data, LPLONG count )
920 DWORD ret;
921 HKEY subkey = hkey;
923 TRACE("(%x,%s,%p,%ld)\n", hkey, debugstr_w(name), data, count ? *count : 0 );
925 if (name && name[0])
927 if ((ret = RegOpenKeyW( hkey, name, &subkey )) != ERROR_SUCCESS) return ret;
929 ret = RegQueryValueExW( subkey, NULL, NULL, NULL, (LPBYTE)data, count );
930 if (subkey != hkey) RegCloseKey( subkey );
931 if (ret == ERROR_FILE_NOT_FOUND)
933 /* return empty string if default value not found */
934 if (data) *data = 0;
935 if (count) *count = 1;
936 ret = ERROR_SUCCESS;
938 return ret;
942 /******************************************************************************
943 * RegQueryValueA [ADVAPI32.@]
945 DWORD WINAPI RegQueryValueA( HKEY hkey, LPCSTR name, LPSTR data, LPLONG count )
947 DWORD ret;
948 HKEY subkey = hkey;
950 TRACE("(%x,%s,%p,%ld)\n", hkey, debugstr_a(name), data, count ? *count : 0 );
952 if (name && name[0])
954 if ((ret = RegOpenKeyA( hkey, name, &subkey )) != ERROR_SUCCESS) return ret;
956 ret = RegQueryValueExA( subkey, NULL, NULL, NULL, (LPBYTE)data, count );
957 if (subkey != hkey) RegCloseKey( subkey );
958 if (ret == ERROR_FILE_NOT_FOUND)
960 /* return empty string if default value not found */
961 if (data) *data = 0;
962 if (count) *count = 1;
963 ret = ERROR_SUCCESS;
965 return ret;
969 /******************************************************************************
970 * RegEnumValueW [ADVAPI32.@]
972 * PARAMS
973 * hkey [I] Handle to key to query
974 * index [I] Index of value to query
975 * value [O] Value string
976 * val_count [I/O] Size of value buffer (in wchars)
977 * reserved [I] Reserved
978 * type [O] Type code
979 * data [O] Value data
980 * count [I/O] Size of data buffer (in bytes)
983 DWORD WINAPI RegEnumValueW( HKEY hkey, DWORD index, LPWSTR value, LPDWORD val_count,
984 LPDWORD reserved, LPDWORD type, LPBYTE data, LPDWORD count )
986 NTSTATUS status;
987 DWORD total_size;
988 char buffer[256], *buf_ptr = buffer;
989 KEY_VALUE_FULL_INFORMATION *info = (KEY_VALUE_FULL_INFORMATION *)buffer;
990 static const int info_size = sizeof(*info) - sizeof(info->Name);
992 TRACE("(%x,%ld,%p,%p,%p,%p,%p,%p)\n",
993 hkey, index, value, val_count, reserved, type, data, count );
995 /* NT only checks count, not val_count */
996 if ((data && !count) || reserved) return ERROR_INVALID_PARAMETER;
998 total_size = info_size + (MAX_PATH + 1) * sizeof(WCHAR);
999 if (data) total_size += *count;
1000 total_size = min( sizeof(buffer), total_size );
1002 status = NtEnumerateValueKey( hkey, index, KeyValueFullInformation,
1003 buffer, total_size, &total_size );
1004 if (status && status != STATUS_BUFFER_OVERFLOW) goto done;
1006 if (value || data)
1008 /* retry with a dynamically allocated buffer */
1009 while (status == STATUS_BUFFER_OVERFLOW)
1011 if (buf_ptr != buffer) HeapFree( GetProcessHeap(), 0, buf_ptr );
1012 if (!(buf_ptr = HeapAlloc( GetProcessHeap(), 0, total_size )))
1013 return ERROR_NOT_ENOUGH_MEMORY;
1014 info = (KEY_VALUE_FULL_INFORMATION *)buf_ptr;
1015 status = NtEnumerateValueKey( hkey, index, KeyValueFullInformation,
1016 buf_ptr, total_size, &total_size );
1019 if (status) goto done;
1021 if (value)
1023 if (info->NameLength/sizeof(WCHAR) >= *val_count)
1025 status = STATUS_BUFFER_OVERFLOW;
1026 goto done;
1028 memcpy( value, info->Name, info->NameLength );
1029 *val_count = info->NameLength / sizeof(WCHAR);
1030 value[*val_count] = 0;
1033 if (data)
1035 if (total_size - info->DataOffset > *count)
1037 status = STATUS_BUFFER_OVERFLOW;
1038 goto done;
1040 memcpy( data, buf_ptr + info->DataOffset, total_size - info->DataOffset );
1041 if (total_size - info->DataOffset <= *count-sizeof(WCHAR) && is_string(info->Type))
1043 /* if the type is REG_SZ and data is not 0-terminated
1044 * and there is enough space in the buffer NT appends a \0 */
1045 WCHAR *ptr = (WCHAR *)(data + total_size - info->DataOffset);
1046 if (ptr > (WCHAR *)data && ptr[-1]) *ptr = 0;
1050 else status = STATUS_SUCCESS;
1052 if (type) *type = info->Type;
1053 if (count) *count = info->DataLength;
1055 done:
1056 if (buf_ptr != buffer) HeapFree( GetProcessHeap(), 0, buf_ptr );
1057 return RtlNtStatusToDosError(status);
1061 /******************************************************************************
1062 * RegEnumValueA [ADVAPI32.@]
1064 DWORD WINAPI RegEnumValueA( HKEY hkey, DWORD index, LPSTR value, LPDWORD val_count,
1065 LPDWORD reserved, LPDWORD type, LPBYTE data, LPDWORD count )
1067 NTSTATUS status;
1068 DWORD total_size;
1069 char buffer[256], *buf_ptr = buffer;
1070 KEY_VALUE_FULL_INFORMATION *info = (KEY_VALUE_FULL_INFORMATION *)buffer;
1071 static const int info_size = sizeof(*info) - sizeof(info->Name);
1073 TRACE("(%x,%ld,%p,%p,%p,%p,%p,%p)\n",
1074 hkey, index, value, val_count, reserved, type, data, count );
1076 /* NT only checks count, not val_count */
1077 if ((data && !count) || reserved) return ERROR_INVALID_PARAMETER;
1079 total_size = info_size + (MAX_PATH + 1) * sizeof(WCHAR);
1080 if (data) total_size += *count;
1081 total_size = min( sizeof(buffer), total_size );
1083 status = NtEnumerateValueKey( hkey, index, KeyValueFullInformation,
1084 buffer, total_size, &total_size );
1085 if (status && status != STATUS_BUFFER_OVERFLOW) goto done;
1087 /* we need to fetch the contents for a string type even if not requested,
1088 * because we need to compute the length of the ASCII string. */
1089 if (value || data || is_string(info->Type))
1091 /* retry with a dynamically allocated buffer */
1092 while (status == STATUS_BUFFER_OVERFLOW)
1094 if (buf_ptr != buffer) HeapFree( GetProcessHeap(), 0, buf_ptr );
1095 if (!(buf_ptr = HeapAlloc( GetProcessHeap(), 0, total_size )))
1096 return ERROR_NOT_ENOUGH_MEMORY;
1097 info = (KEY_VALUE_FULL_INFORMATION *)buf_ptr;
1098 status = NtEnumerateValueKey( hkey, index, KeyValueFullInformation,
1099 buf_ptr, total_size, &total_size );
1102 if (status) goto done;
1104 if (value)
1106 DWORD len = WideCharToMultiByte( CP_ACP, 0, info->Name, info->NameLength/sizeof(WCHAR),
1107 NULL, 0, NULL, NULL );
1108 if (len >= *val_count)
1110 status = STATUS_BUFFER_OVERFLOW;
1111 goto done;
1113 WideCharToMultiByte( CP_ACP, 0, info->Name, info->NameLength/sizeof(WCHAR),
1114 value, len, NULL, NULL );
1115 value[len] = 0;
1116 *val_count = len;
1119 if (is_string(info->Type))
1121 DWORD len = WideCharToMultiByte( CP_ACP, 0, (WCHAR *)(buf_ptr + info->DataOffset),
1122 (total_size - info->DataOffset) / sizeof(WCHAR),
1123 NULL, 0, NULL, NULL );
1124 if (data && len)
1126 if (len > *count)
1128 status = STATUS_BUFFER_OVERFLOW;
1129 goto done;
1131 WideCharToMultiByte( CP_ACP, 0, (WCHAR *)(buf_ptr + info->DataOffset),
1132 (total_size - info->DataOffset) / sizeof(WCHAR),
1133 data, len, NULL, NULL );
1134 /* if the type is REG_SZ and data is not 0-terminated
1135 * and there is enough space in the buffer NT appends a \0 */
1136 if (len < *count && data[len-1]) data[len] = 0;
1138 info->DataLength = len;
1140 else if (data)
1142 if (total_size - info->DataOffset > *count) status = STATUS_BUFFER_OVERFLOW;
1143 else memcpy( data, buf_ptr + info->DataOffset, total_size - info->DataOffset );
1146 else status = STATUS_SUCCESS;
1148 if (type) *type = info->Type;
1149 if (count) *count = info->DataLength;
1151 done:
1152 if (buf_ptr != buffer) HeapFree( GetProcessHeap(), 0, buf_ptr );
1153 return RtlNtStatusToDosError(status);
1158 /******************************************************************************
1159 * RegDeleteValueW [ADVAPI32.@]
1161 * PARAMS
1162 * hkey [I] handle to key
1163 * name [I] name of value to delete
1165 * RETURNS
1166 * error status
1168 DWORD WINAPI RegDeleteValueW( HKEY hkey, LPCWSTR name )
1170 UNICODE_STRING nameW;
1171 RtlInitUnicodeString( &nameW, name );
1172 return RtlNtStatusToDosError( NtDeleteValueKey( hkey, &nameW ) );
1176 /******************************************************************************
1177 * RegDeleteValueA [ADVAPI32.@]
1179 DWORD WINAPI RegDeleteValueA( HKEY hkey, LPCSTR name )
1181 UNICODE_STRING nameW;
1182 STRING nameA;
1183 NTSTATUS status;
1185 RtlInitAnsiString( &nameA, name );
1186 /* FIXME: should use Unicode buffer in TEB */
1187 if (!(status = RtlAnsiStringToUnicodeString( &nameW, &nameA, TRUE )))
1189 status = NtDeleteValueKey( hkey, &nameW );
1190 RtlFreeUnicodeString( &nameW );
1192 return RtlNtStatusToDosError( status );
1196 /******************************************************************************
1197 * RegLoadKeyW [ADVAPI32.@]
1199 * PARAMS
1200 * hkey [I] Handle of open key
1201 * subkey [I] Address of name of subkey
1202 * filename [I] Address of filename for registry information
1204 LONG WINAPI RegLoadKeyW( HKEY hkey, LPCWSTR subkey, LPCWSTR filename )
1206 HANDLE file;
1207 DWORD ret, len, err = GetLastError();
1209 TRACE( "(%x,%s,%s)\n", hkey, debugstr_w(subkey), debugstr_w(filename) );
1211 if (!filename || !*filename) return ERROR_INVALID_PARAMETER;
1212 if (!subkey || !*subkey) return ERROR_INVALID_PARAMETER;
1214 len = strlenW( subkey ) * sizeof(WCHAR);
1215 if (len > MAX_PATH*sizeof(WCHAR)) return ERROR_INVALID_PARAMETER;
1217 if ((file = CreateFileW( filename, GENERIC_READ, 0, NULL, OPEN_EXISTING,
1218 FILE_ATTRIBUTE_NORMAL, 0 )) == INVALID_HANDLE_VALUE)
1220 ret = GetLastError();
1221 goto done;
1224 SERVER_START_VAR_REQ( load_registry, len )
1226 req->hkey = hkey;
1227 req->file = file;
1228 memcpy( server_data_ptr(req), subkey, len );
1229 ret = RtlNtStatusToDosError( SERVER_CALL() );
1231 SERVER_END_VAR_REQ;
1232 CloseHandle( file );
1234 done:
1235 SetLastError( err ); /* restore the last error code */
1236 return ret;
1240 /******************************************************************************
1241 * RegLoadKeyA [ADVAPI32.@]
1243 LONG WINAPI RegLoadKeyA( HKEY hkey, LPCSTR subkey, LPCSTR filename )
1245 HANDLE file;
1246 DWORD ret, len, err = GetLastError();
1248 TRACE( "(%x,%s,%s)\n", hkey, debugstr_a(subkey), debugstr_a(filename) );
1250 if (!filename || !*filename) return ERROR_INVALID_PARAMETER;
1251 if (!subkey || !*subkey) return ERROR_INVALID_PARAMETER;
1253 len = MultiByteToWideChar( CP_ACP, 0, subkey, strlen(subkey), NULL, 0 ) * sizeof(WCHAR);
1254 if (len > MAX_PATH*sizeof(WCHAR)) return ERROR_INVALID_PARAMETER;
1256 if ((file = CreateFileA( filename, GENERIC_READ, 0, NULL, OPEN_EXISTING,
1257 FILE_ATTRIBUTE_NORMAL, 0 )) == INVALID_HANDLE_VALUE)
1259 ret = GetLastError();
1260 goto done;
1263 SERVER_START_VAR_REQ( load_registry, len )
1265 req->hkey = hkey;
1266 req->file = file;
1267 MultiByteToWideChar( CP_ACP, 0, subkey, strlen(subkey),
1268 server_data_ptr(req), len/sizeof(WCHAR) );
1269 ret = RtlNtStatusToDosError( SERVER_CALL() );
1271 SERVER_END_VAR_REQ;
1272 CloseHandle( file );
1274 done:
1275 SetLastError( err ); /* restore the last error code */
1276 return ret;
1280 /******************************************************************************
1281 * RegSaveKeyA [ADVAPI32.@]
1283 * PARAMS
1284 * hkey [I] Handle of key where save begins
1285 * lpFile [I] Address of filename to save to
1286 * sa [I] Address of security structure
1288 LONG WINAPI RegSaveKeyA( HKEY hkey, LPCSTR file, LPSECURITY_ATTRIBUTES sa )
1290 char buffer[1024];
1291 int count = 0;
1292 LPSTR name;
1293 DWORD ret, err;
1294 HFILE handle;
1296 TRACE( "(%x,%s,%p)\n", hkey, debugstr_a(file), sa );
1298 if (!file || !*file) return ERROR_INVALID_PARAMETER;
1300 err = GetLastError();
1301 GetFullPathNameA( file, sizeof(buffer), buffer, &name );
1302 for (;;)
1304 sprintf( name, "reg%04x.tmp", count++ );
1305 handle = CreateFileA( buffer, GENERIC_WRITE, 0, NULL,
1306 CREATE_NEW, FILE_ATTRIBUTE_NORMAL, 0 );
1307 if (handle != INVALID_HANDLE_VALUE) break;
1308 if ((ret = GetLastError()) != ERROR_ALREADY_EXISTS) goto done;
1310 /* Something gone haywire ? Please report if this happens abnormally */
1311 if (count >= 100)
1312 MESSAGE("Wow, we are already fiddling with a temp file %s with an ordinal as high as %d !\nYou might want to delete all corresponding temp files in that directory.\n", buffer, count);
1315 SERVER_START_REQ( save_registry )
1317 req->hkey = hkey;
1318 req->file = handle;
1319 ret = RtlNtStatusToDosError( SERVER_CALL() );
1321 SERVER_END_REQ;
1323 CloseHandle( handle );
1324 if (!ret)
1326 if (!MoveFileExA( buffer, file, MOVEFILE_REPLACE_EXISTING ))
1328 ERR( "Failed to move %s to %s\n", buffer, file );
1329 ret = GetLastError();
1332 if (ret) DeleteFileA( buffer );
1334 done:
1335 SetLastError( err ); /* restore last error code */
1336 return ret;
1340 /******************************************************************************
1341 * RegSaveKeyW [ADVAPI32.@]
1343 LONG WINAPI RegSaveKeyW( HKEY hkey, LPCWSTR file, LPSECURITY_ATTRIBUTES sa )
1345 LPSTR fileA = HEAP_strdupWtoA( GetProcessHeap(), 0, file );
1346 DWORD ret = RegSaveKeyA( hkey, fileA, sa );
1347 if (fileA) HeapFree( GetProcessHeap(), 0, fileA );
1348 return ret;
1352 /******************************************************************************
1353 * RegRestoreKeyW [ADVAPI32.@]
1355 * PARAMS
1356 * hkey [I] Handle of key where restore begins
1357 * lpFile [I] Address of filename containing saved tree
1358 * dwFlags [I] Optional flags
1360 LONG WINAPI RegRestoreKeyW( HKEY hkey, LPCWSTR lpFile, DWORD dwFlags )
1362 TRACE("(%x,%s,%ld)\n",hkey,debugstr_w(lpFile),dwFlags);
1364 /* It seems to do this check before the hkey check */
1365 if (!lpFile || !*lpFile)
1366 return ERROR_INVALID_PARAMETER;
1368 FIXME("(%x,%s,%ld): stub\n",hkey,debugstr_w(lpFile),dwFlags);
1370 /* Check for file existence */
1372 return ERROR_SUCCESS;
1376 /******************************************************************************
1377 * RegRestoreKeyA [ADVAPI32.@]
1379 LONG WINAPI RegRestoreKeyA( HKEY hkey, LPCSTR lpFile, DWORD dwFlags )
1381 LPWSTR lpFileW = HEAP_strdupAtoW( GetProcessHeap(), 0, lpFile );
1382 LONG ret = RegRestoreKeyW( hkey, lpFileW, dwFlags );
1383 HeapFree( GetProcessHeap(), 0, lpFileW );
1384 return ret;
1388 /******************************************************************************
1389 * RegUnLoadKeyW [ADVAPI32.@]
1391 * PARAMS
1392 * hkey [I] Handle of open key
1393 * lpSubKey [I] Address of name of subkey to unload
1395 LONG WINAPI RegUnLoadKeyW( HKEY hkey, LPCWSTR lpSubKey )
1397 FIXME("(%x,%s): stub\n",hkey, debugstr_w(lpSubKey));
1398 return ERROR_SUCCESS;
1402 /******************************************************************************
1403 * RegUnLoadKeyA [ADVAPI32.@]
1405 LONG WINAPI RegUnLoadKeyA( HKEY hkey, LPCSTR lpSubKey )
1407 LPWSTR lpSubKeyW = HEAP_strdupAtoW( GetProcessHeap(), 0, lpSubKey );
1408 LONG ret = RegUnLoadKeyW( hkey, lpSubKeyW );
1409 if(lpSubKeyW) HeapFree( GetProcessHeap(), 0, lpSubKeyW);
1410 return ret;
1414 /******************************************************************************
1415 * RegReplaceKeyW [ADVAPI32.@]
1417 * PARAMS
1418 * hkey [I] Handle of open key
1419 * lpSubKey [I] Address of name of subkey
1420 * lpNewFile [I] Address of filename for file with new data
1421 * lpOldFile [I] Address of filename for backup file
1423 LONG WINAPI RegReplaceKeyW( HKEY hkey, LPCWSTR lpSubKey, LPCWSTR lpNewFile,
1424 LPCWSTR lpOldFile )
1426 FIXME("(%x,%s,%s,%s): stub\n", hkey, debugstr_w(lpSubKey),
1427 debugstr_w(lpNewFile),debugstr_w(lpOldFile));
1428 return ERROR_SUCCESS;
1432 /******************************************************************************
1433 * RegReplaceKeyA [ADVAPI32.@]
1435 LONG WINAPI RegReplaceKeyA( HKEY hkey, LPCSTR lpSubKey, LPCSTR lpNewFile,
1436 LPCSTR lpOldFile )
1438 LPWSTR lpSubKeyW = HEAP_strdupAtoW( GetProcessHeap(), 0, lpSubKey );
1439 LPWSTR lpNewFileW = HEAP_strdupAtoW( GetProcessHeap(), 0, lpNewFile );
1440 LPWSTR lpOldFileW = HEAP_strdupAtoW( GetProcessHeap(), 0, lpOldFile );
1441 LONG ret = RegReplaceKeyW( hkey, lpSubKeyW, lpNewFileW, lpOldFileW );
1442 HeapFree( GetProcessHeap(), 0, lpOldFileW );
1443 HeapFree( GetProcessHeap(), 0, lpNewFileW );
1444 HeapFree( GetProcessHeap(), 0, lpSubKeyW );
1445 return ret;
1449 /******************************************************************************
1450 * RegSetKeySecurity [ADVAPI32.@]
1452 * PARAMS
1453 * hkey [I] Open handle of key to set
1454 * SecurityInfo [I] Descriptor contents
1455 * pSecurityDesc [I] Address of descriptor for key
1457 LONG WINAPI RegSetKeySecurity( HKEY hkey, SECURITY_INFORMATION SecurityInfo,
1458 PSECURITY_DESCRIPTOR pSecurityDesc )
1460 TRACE("(%x,%ld,%p)\n",hkey,SecurityInfo,pSecurityDesc);
1462 /* It seems to perform this check before the hkey check */
1463 if ((SecurityInfo & OWNER_SECURITY_INFORMATION) ||
1464 (SecurityInfo & GROUP_SECURITY_INFORMATION) ||
1465 (SecurityInfo & DACL_SECURITY_INFORMATION) ||
1466 (SecurityInfo & SACL_SECURITY_INFORMATION)) {
1467 /* Param OK */
1468 } else
1469 return ERROR_INVALID_PARAMETER;
1471 if (!pSecurityDesc)
1472 return ERROR_INVALID_PARAMETER;
1474 FIXME(":(%x,%ld,%p): stub\n",hkey,SecurityInfo,pSecurityDesc);
1476 return ERROR_SUCCESS;
1480 /******************************************************************************
1481 * RegGetKeySecurity [ADVAPI32.@]
1482 * Retrieves a copy of security descriptor protecting the registry key
1484 * PARAMS
1485 * hkey [I] Open handle of key to set
1486 * SecurityInformation [I] Descriptor contents
1487 * pSecurityDescriptor [O] Address of descriptor for key
1488 * lpcbSecurityDescriptor [I/O] Address of size of buffer and description
1490 * RETURNS
1491 * Success: ERROR_SUCCESS
1492 * Failure: Error code
1494 LONG WINAPI RegGetKeySecurity( HKEY hkey, SECURITY_INFORMATION SecurityInformation,
1495 PSECURITY_DESCRIPTOR pSecurityDescriptor,
1496 LPDWORD lpcbSecurityDescriptor )
1498 TRACE("(%x,%ld,%p,%ld)\n",hkey,SecurityInformation,pSecurityDescriptor,
1499 lpcbSecurityDescriptor?*lpcbSecurityDescriptor:0);
1501 /* FIXME: Check for valid SecurityInformation values */
1503 if (*lpcbSecurityDescriptor < sizeof(SECURITY_DESCRIPTOR))
1504 return ERROR_INSUFFICIENT_BUFFER;
1506 FIXME("(%x,%ld,%p,%ld): stub\n",hkey,SecurityInformation,
1507 pSecurityDescriptor,lpcbSecurityDescriptor?*lpcbSecurityDescriptor:0);
1509 return ERROR_SUCCESS;
1513 /******************************************************************************
1514 * RegFlushKey [ADVAPI32.@]
1515 * Immediately writes key to registry.
1516 * Only returns after data has been written to disk.
1518 * FIXME: does it really wait until data is written ?
1520 * PARAMS
1521 * hkey [I] Handle of key to write
1523 * RETURNS
1524 * Success: ERROR_SUCCESS
1525 * Failure: Error code
1527 DWORD WINAPI RegFlushKey( HKEY hkey )
1529 FIXME( "(%x): stub\n", hkey );
1530 return ERROR_SUCCESS;
1534 /******************************************************************************
1535 * RegConnectRegistryW [ADVAPI32.@]
1537 * PARAMS
1538 * lpMachineName [I] Address of name of remote computer
1539 * hHey [I] Predefined registry handle
1540 * phkResult [I] Address of buffer for remote registry handle
1542 LONG WINAPI RegConnectRegistryW( LPCWSTR lpMachineName, HKEY hKey,
1543 LPHKEY phkResult )
1545 TRACE("(%s,%x,%p): stub\n",debugstr_w(lpMachineName),hKey,phkResult);
1547 if (!lpMachineName || !*lpMachineName) {
1548 /* Use the local machine name */
1549 return RegOpenKeyA( hKey, "", phkResult );
1552 FIXME("Cannot connect to %s\n",debugstr_w(lpMachineName));
1553 return ERROR_BAD_NETPATH;
1557 /******************************************************************************
1558 * RegConnectRegistryA [ADVAPI32.@]
1560 LONG WINAPI RegConnectRegistryA( LPCSTR machine, HKEY hkey, LPHKEY reskey )
1562 LPWSTR machineW = HEAP_strdupAtoW( GetProcessHeap(), 0, machine );
1563 DWORD ret = RegConnectRegistryW( machineW, hkey, reskey );
1564 HeapFree( GetProcessHeap(), 0, machineW );
1565 return ret;
1569 /******************************************************************************
1570 * RegNotifyChangeKeyValue [ADVAPI32.@]
1572 * PARAMS
1573 * hkey [I] Handle of key to watch
1574 * fWatchSubTree [I] Flag for subkey notification
1575 * fdwNotifyFilter [I] Changes to be reported
1576 * hEvent [I] Handle of signaled event
1577 * fAsync [I] Flag for asynchronous reporting
1579 LONG WINAPI RegNotifyChangeKeyValue( HKEY hkey, BOOL fWatchSubTree,
1580 DWORD fdwNotifyFilter, HANDLE hEvent,
1581 BOOL fAsync )
1583 FIXME("(%x,%i,%ld,%x,%i): stub\n",hkey,fWatchSubTree,fdwNotifyFilter,
1584 hEvent,fAsync);
1585 return ERROR_SUCCESS;