Moved a bunch of functions out of libwine/kernel/gdi into USER.
[wine/hacks.git] / memory / registry.c
blob30a5f2118e6c171d03f0886f3c2528474dd38039
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/winbase16.h"
23 #include "winversion.h"
24 #include "file.h"
25 #include "heap.h"
26 #include "server.h"
27 #include "debugtools.h"
29 DEFAULT_DEBUG_CHANNEL(reg);
32 /* Ansi->Unicode conversion without string delimiters */
33 static LPWSTR memcpyAtoW( LPWSTR dst, LPCSTR src, INT n )
35 LPWSTR p = dst;
36 while (n-- > 0) *p++ = (WCHAR)*src++;
37 return dst;
40 /* Unicode->Ansi conversion without string delimiters */
41 static LPSTR memcpyWtoA( LPSTR dst, LPCWSTR src, INT n )
43 LPSTR p = dst;
44 while (n-- > 0) *p++ = (CHAR)*src++;
45 return dst;
48 /* check if value type needs string conversion (Ansi<->Unicode) */
49 static inline int is_string( DWORD type )
51 return (type == REG_SZ) || (type == REG_EXPAND_SZ) || (type == REG_MULTI_SZ);
54 /* copy a key name into the request buffer */
55 static inline DWORD copy_nameW( LPWSTR dest, LPCWSTR name )
57 if (name)
59 if (lstrlenW(name) > MAX_PATH) return ERROR_MORE_DATA;
60 lstrcpyW( dest, name );
62 else dest[0] = 0;
63 return ERROR_SUCCESS;
66 /* copy a key name into the request buffer */
67 static inline DWORD copy_nameAtoW( LPWSTR dest, LPCSTR name )
69 if (name)
71 if (strlen(name) > MAX_PATH) return ERROR_MORE_DATA;
72 lstrcpyAtoW( dest, name );
74 else dest[0] = 0;
75 return ERROR_SUCCESS;
78 /* do a server call without setting the last error code */
79 static inline int reg_server_call( enum request req )
81 unsigned int res = server_call_noerr( req );
82 if (res) res = RtlNtStatusToDosError(res);
83 return res;
86 /******************************************************************************
87 * RegCreateKeyExW [ADVAPI32.131]
89 * PARAMS
90 * hkey [I] Handle of an open key
91 * name [I] Address of subkey name
92 * reserved [I] Reserved - must be 0
93 * class [I] Address of class string
94 * options [I] Special options flag
95 * access [I] Desired security access
96 * sa [I] Address of key security structure
97 * retkey [O] Address of buffer for opened handle
98 * dispos [O] Receives REG_CREATED_NEW_KEY or REG_OPENED_EXISTING_KEY
100 * NOTES
101 * in case of failing retkey remains untouched
103 DWORD WINAPI RegCreateKeyExW( HKEY hkey, LPCWSTR name, DWORD reserved, LPWSTR class,
104 DWORD options, REGSAM access, SECURITY_ATTRIBUTES *sa,
105 LPHKEY retkey, LPDWORD dispos )
107 DWORD ret;
108 struct create_key_request *req = get_req_buffer();
110 TRACE( "(0x%x,%s,%ld,%s,%lx,%lx,%p,%p,%p)\n", hkey, debugstr_w(name), reserved,
111 debugstr_w(class), options, access, sa, retkey, dispos );
113 if (reserved) return ERROR_INVALID_PARAMETER;
114 if (!(access & KEY_ALL_ACCESS) || (access & ~KEY_ALL_ACCESS)) return ERROR_ACCESS_DENIED;
116 req->parent = hkey;
117 req->access = access;
118 req->options = options;
119 req->modif = time(NULL);
120 if ((ret = copy_nameW( req->name, name )) != ERROR_SUCCESS) return ret;
121 if (req->name[0] == '\\') return ERROR_BAD_PATHNAME;
122 lstrcpynW( req->class, class ? class : (LPWSTR)"\0\0",
123 server_remaining(req->class) / sizeof(WCHAR) );
124 if ((ret = reg_server_call( REQ_CREATE_KEY )) == ERROR_SUCCESS)
126 *retkey = req->hkey;
127 if (dispos) *dispos = req->created ? REG_CREATED_NEW_KEY : REG_OPENED_EXISTING_KEY;
129 return ret;
133 /******************************************************************************
134 * RegCreateKeyExA [ADVAPI32.130]
136 DWORD WINAPI RegCreateKeyExA( HKEY hkey, LPCSTR name, DWORD reserved, LPSTR class,
137 DWORD options, REGSAM access, SECURITY_ATTRIBUTES *sa,
138 LPHKEY retkey, LPDWORD dispos )
140 DWORD ret;
141 struct create_key_request *req = get_req_buffer();
143 TRACE( "(0x%x,%s,%ld,%s,%lx,%lx,%p,%p,%p)\n", hkey, debugstr_a(name), reserved,
144 debugstr_a(class), options, access, sa, retkey, dispos );
146 if (reserved) return ERROR_INVALID_PARAMETER;
147 if (!(access & KEY_ALL_ACCESS) || (access & ~KEY_ALL_ACCESS)) return ERROR_ACCESS_DENIED;
149 req->parent = hkey;
150 req->access = access;
151 req->options = options;
152 req->modif = time(NULL);
153 if ((ret = copy_nameAtoW( req->name, name )) != ERROR_SUCCESS) return ret;
154 if (req->name[0] == '\\') return ERROR_BAD_PATHNAME;
155 lstrcpynAtoW( req->class, class ? class : "",
156 server_remaining(req->class) / sizeof(WCHAR) );
157 if ((ret = reg_server_call( REQ_CREATE_KEY )) == ERROR_SUCCESS)
159 *retkey = req->hkey;
160 if (dispos) *dispos = req->created ? REG_CREATED_NEW_KEY : REG_OPENED_EXISTING_KEY;
162 return ret;
166 /******************************************************************************
167 * RegCreateKeyW [ADVAPI32.132]
169 DWORD WINAPI RegCreateKeyW( HKEY hkey, LPCWSTR name, LPHKEY retkey )
171 /* FIXME: previous implementation converted ERROR_INVALID_HANDLE to ERROR_BADKEY, */
172 /* but at least my version of NT (4.0 SP5) doesn't do this. -- AJ */
173 return RegCreateKeyExW( hkey, name, 0, NULL, REG_OPTION_NON_VOLATILE,
174 KEY_ALL_ACCESS, NULL, retkey, NULL );
178 /******************************************************************************
179 * RegCreateKeyA [ADVAPI32.129]
181 DWORD WINAPI RegCreateKeyA( HKEY hkey, LPCSTR name, LPHKEY retkey )
183 return RegCreateKeyExA( hkey, name, 0, NULL, REG_OPTION_NON_VOLATILE,
184 KEY_ALL_ACCESS, NULL, retkey, NULL );
189 /******************************************************************************
190 * RegOpenKeyExW [ADVAPI32.150]
192 * Opens the specified key
194 * Unlike RegCreateKeyEx, this does not create the key if it does not exist.
196 * PARAMS
197 * hkey [I] Handle of open key
198 * name [I] Name of subkey to open
199 * reserved [I] Reserved - must be zero
200 * access [I] Security access mask
201 * retkey [O] Handle to open key
203 * RETURNS
204 * Success: ERROR_SUCCESS
205 * Failure: Error code
207 * NOTES
208 * in case of failing is retkey = 0
210 DWORD WINAPI RegOpenKeyExW( HKEY hkey, LPCWSTR name, DWORD reserved, REGSAM access, LPHKEY retkey )
212 DWORD ret;
213 struct open_key_request *req = get_req_buffer();
215 TRACE( "(0x%x,%s,%ld,%lx,%p)\n", hkey, debugstr_w(name), reserved, access, retkey );
217 if (!retkey) return ERROR_INVALID_PARAMETER;
218 *retkey = 0;
220 req->parent = hkey;
221 req->access = access;
222 if ((ret = copy_nameW( req->name, name )) != ERROR_SUCCESS) return ret;
223 if (req->name[0] == '\\') return ERROR_BAD_PATHNAME;
224 if ((ret = reg_server_call( REQ_OPEN_KEY )) == ERROR_SUCCESS) *retkey = req->hkey;
225 return ret;
229 /******************************************************************************
230 * RegOpenKeyExA [ADVAPI32.149]
232 DWORD WINAPI RegOpenKeyExA( HKEY hkey, LPCSTR name, DWORD reserved, REGSAM access, LPHKEY retkey )
234 DWORD ret;
235 struct open_key_request *req = get_req_buffer();
237 TRACE( "(0x%x,%s,%ld,%lx,%p)\n", hkey, debugstr_a(name), reserved, access, retkey );
239 if (!retkey) return ERROR_INVALID_PARAMETER;
240 *retkey = 0;
242 req->parent = hkey;
243 req->access = access;
244 if ((ret = copy_nameAtoW( req->name, name )) != ERROR_SUCCESS) return ret;
245 if (req->name[0] == '\\') return ERROR_BAD_PATHNAME;
246 if ((ret = reg_server_call( REQ_OPEN_KEY )) == ERROR_SUCCESS) *retkey = req->hkey;
247 return ret;
251 /******************************************************************************
252 * RegOpenKeyW [ADVAPI32.151]
254 * PARAMS
255 * hkey [I] Handle of open key
256 * name [I] Address of name of subkey to open
257 * retkey [O] Handle to open key
259 * RETURNS
260 * Success: ERROR_SUCCESS
261 * Failure: Error code
263 * NOTES
264 * in case of failing is retkey = 0
266 DWORD WINAPI RegOpenKeyW( HKEY hkey, LPCWSTR name, LPHKEY retkey )
268 return RegOpenKeyExW( hkey, name, 0, KEY_ALL_ACCESS, retkey );
272 /******************************************************************************
273 * RegOpenKeyA [ADVAPI32.148]
275 DWORD WINAPI RegOpenKeyA( HKEY hkey, LPCSTR name, LPHKEY retkey )
277 return RegOpenKeyExA( hkey, name, 0, KEY_ALL_ACCESS, retkey );
282 /******************************************************************************
283 * RegEnumKeyExW [ADVAPI32.139]
285 * PARAMS
286 * hkey [I] Handle to key to enumerate
287 * index [I] Index of subkey to enumerate
288 * name [O] Buffer for subkey name
289 * name_len [O] Size of subkey buffer
290 * reserved [I] Reserved
291 * class [O] Buffer for class string
292 * class_len [O] Size of class buffer
293 * ft [O] Time key last written to
295 DWORD WINAPI RegEnumKeyExW( HKEY hkey, DWORD index, LPWSTR name, LPDWORD name_len,
296 LPDWORD reserved, LPWSTR class, LPDWORD class_len, FILETIME *ft )
298 DWORD ret, len, cls_len;
299 struct enum_key_request *req = get_req_buffer();
301 TRACE( "(0x%x,%ld,%p,%p(%ld),%p,%p,%p,%p)\n", hkey, index, name, name_len,
302 name_len ? *name_len : -1, reserved, class, class_len, ft );
304 if (reserved) return ERROR_INVALID_PARAMETER;
306 req->hkey = hkey;
307 req->index = index;
308 if ((ret = reg_server_call( REQ_ENUM_KEY )) != ERROR_SUCCESS) return ret;
310 len = lstrlenW( req->name ) + 1;
311 cls_len = lstrlenW( req->class ) + 1;
312 if (len > *name_len) return ERROR_MORE_DATA;
313 if (class_len && (cls_len > *class_len)) return ERROR_MORE_DATA;
315 memcpy( name, req->name, len * sizeof(WCHAR) );
316 *name_len = len - 1;
317 if (class_len)
319 if (class) memcpy( class, req->class, cls_len * sizeof(WCHAR) );
320 *class_len = cls_len - 1;
322 if (ft) DOSFS_UnixTimeToFileTime( req->modif, ft, 0 );
323 return ERROR_SUCCESS;
327 /******************************************************************************
328 * RegEnumKeyExA [ADVAPI32.138]
330 DWORD WINAPI RegEnumKeyExA( HKEY hkey, DWORD index, LPSTR name, LPDWORD name_len,
331 LPDWORD reserved, LPSTR class, LPDWORD class_len, FILETIME *ft )
333 DWORD ret, len, cls_len;
334 struct enum_key_request *req = get_req_buffer();
336 TRACE( "(0x%x,%ld,%p,%p(%ld),%p,%p,%p,%p)\n", hkey, index, name, name_len,
337 name_len ? *name_len : -1, reserved, class, class_len, ft );
339 if (reserved) return ERROR_INVALID_PARAMETER;
341 req->hkey = hkey;
342 req->index = index;
343 if ((ret = reg_server_call( REQ_ENUM_KEY )) != ERROR_SUCCESS) return ret;
345 len = lstrlenW( req->name ) + 1;
346 cls_len = lstrlenW( req->class ) + 1;
347 if (len > *name_len) return ERROR_MORE_DATA;
348 if (class_len && (cls_len > *class_len)) return ERROR_MORE_DATA;
350 memcpyWtoA( name, req->name, len );
351 *name_len = len - 1;
352 if (class_len)
354 if (class) memcpyWtoA( class, req->class, cls_len );
355 *class_len = cls_len - 1;
357 if (ft) DOSFS_UnixTimeToFileTime( req->modif, ft, 0 );
358 return ERROR_SUCCESS;
362 /******************************************************************************
363 * RegEnumKeyW [ADVAPI32.140]
365 DWORD WINAPI RegEnumKeyW( HKEY hkey, DWORD index, LPWSTR name, DWORD name_len )
367 return RegEnumKeyExW( hkey, index, name, &name_len, NULL, NULL, NULL, NULL );
371 /******************************************************************************
372 * RegEnumKeyA [ADVAPI32.137]
374 DWORD WINAPI RegEnumKeyA( HKEY hkey, DWORD index, LPSTR name, DWORD name_len )
376 return RegEnumKeyExA( hkey, index, name, &name_len, NULL, NULL, NULL, NULL );
380 /******************************************************************************
381 * RegQueryInfoKeyW [ADVAPI32.153]
383 * PARAMS
384 * hkey [I] Handle to key to query
385 * class [O] Buffer for class string
386 * class_len [O] Size of class string buffer
387 * reserved [I] Reserved
388 * subkeys [O] Buffer for number of subkeys
389 * max_subkey [O] Buffer for longest subkey name length
390 * max_class [O] Buffer for longest class string length
391 * values [O] Buffer for number of value entries
392 * max_value [O] Buffer for longest value name length
393 * max_data [O] Buffer for longest value data length
394 * security [O] Buffer for security descriptor length
395 * modif [O] Modification time
397 * - win95 allows class to be valid and class_len to be NULL
398 * - winnt returns ERROR_INVALID_PARAMETER if class is valid and class_len is NULL
399 * - both allow class to be NULL and class_len to be NULL
400 * (it's hard to test validity, so test !NULL instead)
402 DWORD WINAPI RegQueryInfoKeyW( HKEY hkey, LPWSTR class, LPDWORD class_len, LPDWORD reserved,
403 LPDWORD subkeys, LPDWORD max_subkey, LPDWORD max_class,
404 LPDWORD values, LPDWORD max_value, LPDWORD max_data,
405 LPDWORD security, FILETIME *modif )
407 DWORD ret;
408 struct query_key_info_request *req = get_req_buffer();
411 TRACE( "(0x%x,%p,%ld,%p,%p,%p,%p,%p,%p,%p,%p)\n", hkey, class, class_len ? *class_len : 0,
412 reserved, subkeys, max_subkey, values, max_value, max_data, security, modif );
414 if (class && !class_len && (VERSION_GetVersion() == NT40))
415 return ERROR_INVALID_PARAMETER;
417 req->hkey = hkey;
418 if ((ret = reg_server_call( REQ_QUERY_KEY_INFO )) != ERROR_SUCCESS) return ret;
420 if (class)
422 if (class_len && (lstrlenW(req->class) + 1 > *class_len))
424 *class_len = lstrlenW(req->class);
425 return ERROR_MORE_DATA;
427 lstrcpyW( class, req->class );
429 if (class_len) *class_len = lstrlenW( req->class );
430 if (subkeys) *subkeys = req->subkeys;
431 if (max_subkey) *max_subkey = req->max_subkey;
432 if (max_class) *max_class = req->max_class;
433 if (values) *values = req->values;
434 if (max_value) *max_value = req->max_value;
435 if (max_data) *max_data = req->max_data;
436 if (modif) DOSFS_UnixTimeToFileTime( req->modif, modif, 0 );
437 return ERROR_SUCCESS;
441 /******************************************************************************
442 * RegQueryInfoKeyA [ADVAPI32.152]
444 DWORD WINAPI RegQueryInfoKeyA( HKEY hkey, LPSTR class, LPDWORD class_len, LPDWORD reserved,
445 LPDWORD subkeys, LPDWORD max_subkey, LPDWORD max_class,
446 LPDWORD values, LPDWORD max_value, LPDWORD max_data,
447 LPDWORD security, FILETIME *modif )
449 DWORD ret;
450 struct query_key_info_request *req = get_req_buffer();
453 TRACE( "(0x%x,%p,%ld,%p,%p,%p,%p,%p,%p,%p,%p)\n", hkey, class, class_len ? *class_len : 0,
454 reserved, subkeys, max_subkey, values, max_value, max_data, security, modif );
456 if (class && !class_len && (VERSION_GetVersion() == NT40))
457 return ERROR_INVALID_PARAMETER;
459 req->hkey = hkey;
460 if ((ret = reg_server_call( REQ_QUERY_KEY_INFO )) != ERROR_SUCCESS) return ret;
462 if (class)
464 if (class_len && (lstrlenW(req->class) + 1 > *class_len))
466 *class_len = lstrlenW(req->class);
467 return ERROR_MORE_DATA;
469 lstrcpyWtoA( class, req->class );
471 if (class_len) *class_len = lstrlenW( req->class );
472 if (subkeys) *subkeys = req->subkeys;
473 if (max_subkey) *max_subkey = req->max_subkey;
474 if (max_class) *max_class = req->max_class;
475 if (values) *values = req->values;
476 if (max_value) *max_value = req->max_value;
477 if (max_data) *max_data = req->max_data;
478 if (modif) DOSFS_UnixTimeToFileTime( req->modif, modif, 0 );
479 return ERROR_SUCCESS;
483 /******************************************************************************
484 * RegCloseKey [ADVAPI32.126]
486 * Releases the handle of the specified key
488 * PARAMS
489 * hkey [I] Handle of key to close
491 * RETURNS
492 * Success: ERROR_SUCCESS
493 * Failure: Error code
495 DWORD WINAPI RegCloseKey( HKEY hkey )
497 struct close_key_request *req = get_req_buffer();
498 TRACE( "(0x%x)\n", hkey );
499 req->hkey = hkey;
500 return reg_server_call( REQ_CLOSE_KEY );
504 /******************************************************************************
505 * RegDeleteKeyW [ADVAPI32.134]
507 * PARAMS
508 * hkey [I] Handle to open key
509 * name [I] Name of subkey to delete
511 * RETURNS
512 * Success: ERROR_SUCCESS
513 * Failure: Error code
515 DWORD WINAPI RegDeleteKeyW( HKEY hkey, LPCWSTR name )
517 DWORD ret;
518 struct delete_key_request *req = get_req_buffer();
520 TRACE( "(0x%x,%s)\n", hkey, debugstr_w(name) );
522 req->hkey = hkey;
523 if ((ret = copy_nameW( req->name, name )) != ERROR_SUCCESS) return ret;
524 if (req->name[0] == '\\') return ERROR_BAD_PATHNAME;
525 return reg_server_call( REQ_DELETE_KEY );
529 /******************************************************************************
530 * RegDeleteKeyA [ADVAPI32.133]
532 DWORD WINAPI RegDeleteKeyA( HKEY hkey, LPCSTR name )
534 DWORD ret;
535 struct delete_key_request *req = get_req_buffer();
537 TRACE( "(0x%x,%s)\n", hkey, debugstr_a(name) );
539 req->hkey = hkey;
540 if ((ret = copy_nameAtoW( req->name, name )) != ERROR_SUCCESS) return ret;
541 if (req->name[0] == '\\') return ERROR_BAD_PATHNAME;
542 return reg_server_call( REQ_DELETE_KEY );
547 /******************************************************************************
548 * RegSetValueExW [ADVAPI32.170]
550 * Sets the data and type of a value under a register key
552 * PARAMS
553 * hkey [I] Handle of key to set value for
554 * name [I] Name of value to set
555 * reserved [I] Reserved - must be zero
556 * type [I] Flag for value type
557 * data [I] Address of value data
558 * count [I] Size of value data
560 * RETURNS
561 * Success: ERROR_SUCCESS
562 * Failure: Error code
564 * NOTES
565 * win95 does not care about count for REG_SZ and finds out the len by itself (js)
566 * NT does definitely care (aj)
568 DWORD WINAPI RegSetValueExW( HKEY hkey, LPCWSTR name, DWORD reserved,
569 DWORD type, CONST BYTE *data, DWORD count )
571 DWORD ret;
572 struct set_key_value_request *req = get_req_buffer();
573 unsigned int max, pos;
575 TRACE( "(0x%x,%s,%ld,%ld,%p,%ld)\n", hkey, debugstr_w(name), reserved, type, data, count );
577 if (reserved) return ERROR_INVALID_PARAMETER;
579 if (count && type == REG_SZ)
581 LPCWSTR str = (LPCWSTR)data;
582 /* if user forgot to count terminating null, add it (yes NT does this) */
583 if (str[count / sizeof(WCHAR) - 1] && !str[count / sizeof(WCHAR)])
584 count += sizeof(WCHAR);
587 req->hkey = hkey;
588 req->type = type;
589 req->total = count;
590 if ((ret = copy_nameW( req->name, name )) != ERROR_SUCCESS) return ret;
592 max = server_remaining( req->data );
593 pos = 0;
594 while (pos < count)
596 unsigned int len = count - pos;
597 if (len > max) len = max;
598 req->offset = pos;
599 req->len = len;
600 memcpy( req->data, data + pos, len );
601 if ((ret = reg_server_call( REQ_SET_KEY_VALUE )) != ERROR_SUCCESS) break;
602 pos += len;
604 return ret;
608 /******************************************************************************
609 * RegSetValueExA [ADVAPI32.169]
611 DWORD WINAPI RegSetValueExA( HKEY hkey, LPCSTR name, DWORD reserved, DWORD type,
612 CONST BYTE *data, DWORD count )
614 DWORD ret;
615 struct set_key_value_request *req = get_req_buffer();
616 unsigned int max, pos;
618 TRACE( "(0x%x,%s,%ld,%ld,%p,%ld)\n", hkey, debugstr_a(name), reserved, type, data, count );
620 if (reserved) return ERROR_INVALID_PARAMETER;
622 if (count && type == REG_SZ)
624 /* if user forgot to count terminating null, add it (yes NT does this) */
625 if (data[count-1] && !data[count]) count++;
627 if (is_string( type )) /* need to convert to Unicode */
628 count *= sizeof(WCHAR);
630 req->hkey = hkey;
631 req->type = type;
632 req->total = count;
633 if ((ret = copy_nameAtoW( req->name, name )) != ERROR_SUCCESS) return ret;
635 max = server_remaining( req->data );
636 pos = 0;
637 while (pos < count)
639 unsigned int len = count - pos;
640 if (len > max) len = max;
641 req->offset = pos;
642 req->len = len;
644 if (is_string( type ))
645 memcpyAtoW( (LPWSTR)req->data, data + pos/sizeof(WCHAR), len/sizeof(WCHAR) );
646 else
647 memcpy( req->data, data + pos, len );
648 if ((ret = reg_server_call( REQ_SET_KEY_VALUE )) != ERROR_SUCCESS) break;
649 pos += len;
651 return ret;
655 /******************************************************************************
656 * RegSetValueW [ADVAPI32.171]
658 DWORD WINAPI RegSetValueW( HKEY hkey, LPCWSTR name, DWORD type, LPCWSTR data, DWORD count )
660 HKEY subkey = hkey;
661 DWORD ret;
663 TRACE("(0x%x,%s,%ld,%s,%ld)\n", hkey, debugstr_w(name), type, debugstr_w(data), count );
665 if (type != REG_SZ) return ERROR_INVALID_PARAMETER;
667 if (name && name[0]) /* need to create the subkey */
669 if ((ret = RegCreateKeyW( hkey, name, &subkey )) != ERROR_SUCCESS) return ret;
672 ret = RegSetValueExW( subkey, NULL, 0, REG_SZ, (LPBYTE)data,
673 (lstrlenW( data ) + 1) * sizeof(WCHAR) );
674 if (subkey != hkey) RegCloseKey( subkey );
675 return ret;
679 /******************************************************************************
680 * RegSetValueA [ADVAPI32.168]
682 DWORD WINAPI RegSetValueA( HKEY hkey, LPCSTR name, DWORD type, LPCSTR data, DWORD count )
684 HKEY subkey = hkey;
685 DWORD ret;
687 TRACE("(0x%x,%s,%ld,%s,%ld)\n", hkey, debugstr_a(name), type, debugstr_a(data), count );
689 if (type != REG_SZ) return ERROR_INVALID_PARAMETER;
691 if (name && name[0]) /* need to create the subkey */
693 if ((ret = RegCreateKeyA( hkey, name, &subkey )) != ERROR_SUCCESS) return ret;
695 ret = RegSetValueExA( subkey, NULL, 0, REG_SZ, (LPBYTE)data, strlen(data)+1 );
696 if (subkey != hkey) RegCloseKey( subkey );
697 return ret;
702 /******************************************************************************
703 * RegQueryValueExW [ADVAPI32.158]
705 * Retrieves type and data for a specified name associated with an open key
707 * PARAMS
708 * hkey [I] Handle of key to query
709 * name [I] Name of value to query
710 * reserved [I] Reserved - must be NULL
711 * type [O] Address of buffer for value type. If NULL, the type
712 * is not required.
713 * data [O] Address of data buffer. If NULL, the actual data is
714 * not required.
715 * count [I/O] Address of data buffer size
717 * RETURNS
718 * ERROR_SUCCESS: Success
719 * ERROR_MORE_DATA: !!! if the specified buffer is not big enough to hold the data
720 * buffer is left untouched. The MS-documentation is wrong (js) !!!
722 DWORD WINAPI RegQueryValueExW( HKEY hkey, LPCWSTR name, LPDWORD reserved, LPDWORD type,
723 LPBYTE data, LPDWORD count )
725 DWORD ret;
726 struct get_key_value_request *req = get_req_buffer();
728 TRACE("(0x%x,%s,%p,%p,%p,%p=%ld)\n",
729 hkey, debugstr_w(name), reserved, type, data, count, count ? *count : 0 );
731 if ((data && !count) || reserved) return ERROR_INVALID_PARAMETER;
733 req->hkey = hkey;
734 req->offset = 0;
735 if ((ret = copy_nameW( req->name, name )) != ERROR_SUCCESS) return ret;
736 if ((ret = reg_server_call( REQ_GET_KEY_VALUE )) != ERROR_SUCCESS) return ret;
738 if (data)
740 if (*count < req->len) ret = ERROR_MORE_DATA;
741 else
743 /* copy the data */
744 unsigned int max = server_remaining( req->data );
745 unsigned int pos = 0;
746 while (pos < req->len)
748 unsigned int len = min( req->len - pos, max );
749 memcpy( data + pos, req->data, len );
750 if ((pos += len) >= req->len) break;
751 req->offset = pos;
752 if ((ret = copy_nameW( req->name, name )) != ERROR_SUCCESS) return ret;
753 if ((ret = reg_server_call( REQ_GET_KEY_VALUE )) != ERROR_SUCCESS) return ret;
756 /* if the type is REG_SZ and data is not 0-terminated
757 * and there is enough space in the buffer NT appends a \0 */
758 if (req->len && is_string(req->type) &&
759 (req->len < *count) && ((WCHAR *)data)[req->len-1]) ((WCHAR *)data)[req->len] = 0;
761 if (type) *type = req->type;
762 if (count) *count = req->len;
763 return ret;
767 /******************************************************************************
768 * RegQueryValueExA [ADVAPI32.157]
770 * NOTES:
771 * the documentation is wrong: if the buffer is to small it remains untouched
773 DWORD WINAPI RegQueryValueExA( HKEY hkey, LPCSTR name, LPDWORD reserved, LPDWORD type,
774 LPBYTE data, LPDWORD count )
776 DWORD ret, total_len;
777 struct get_key_value_request *req = get_req_buffer();
779 TRACE("(0x%x,%s,%p,%p,%p,%p=%ld)\n",
780 hkey, debugstr_a(name), reserved, type, data, count, count ? *count : 0 );
782 if ((data && !count) || reserved) return ERROR_INVALID_PARAMETER;
784 req->hkey = hkey;
785 req->offset = 0;
786 if ((ret = copy_nameAtoW( req->name, name )) != ERROR_SUCCESS) return ret;
787 if ((ret = reg_server_call( REQ_GET_KEY_VALUE )) != ERROR_SUCCESS) return ret;
789 total_len = is_string( req->type ) ? req->len/sizeof(WCHAR) : req->len;
791 if (data)
793 if (*count < total_len) ret = ERROR_MORE_DATA;
794 else
796 /* copy the data */
797 unsigned int max = server_remaining( req->data );
798 unsigned int pos = 0;
799 while (pos < req->len)
801 unsigned int len = min( req->len - pos, max );
802 if (is_string( req->type ))
803 memcpyWtoA( data + pos/sizeof(WCHAR), (WCHAR *)req->data, len/sizeof(WCHAR) );
804 else
805 memcpy( data + pos, req->data, len );
806 if ((pos += len) >= req->len) break;
807 req->offset = pos;
808 if ((ret = copy_nameAtoW( req->name, name )) != ERROR_SUCCESS) return ret;
809 if ((ret = reg_server_call( REQ_GET_KEY_VALUE )) != ERROR_SUCCESS) return ret;
812 /* if the type is REG_SZ and data is not 0-terminated
813 * and there is enough space in the buffer NT appends a \0 */
814 if (total_len && is_string(req->type) && (total_len < *count) && data[total_len-1])
815 data[total_len] = 0;
818 if (count) *count = total_len;
819 if (type) *type = req->type;
820 return ret;
824 /******************************************************************************
825 * RegQueryValueW [ADVAPI32.159]
827 DWORD WINAPI RegQueryValueW( HKEY hkey, LPCWSTR name, LPWSTR data, LPLONG count )
829 DWORD ret;
830 HKEY subkey = hkey;
832 TRACE("(%x,%s,%p,%ld)\n", hkey, debugstr_w(name), data, count ? *count : 0 );
834 if (name && name[0])
836 if ((ret = RegOpenKeyW( hkey, name, &subkey )) != ERROR_SUCCESS) return ret;
838 ret = RegQueryValueExW( subkey, NULL, NULL, NULL, (LPBYTE)data, count );
839 if (subkey != hkey) RegCloseKey( subkey );
840 if (ret == ERROR_FILE_NOT_FOUND)
842 /* return empty string if default value not found */
843 if (data) *data = 0;
844 if (count) *count = 1;
845 ret = ERROR_SUCCESS;
847 return ret;
851 /******************************************************************************
852 * RegQueryValueA [ADVAPI32.156]
854 DWORD WINAPI RegQueryValueA( HKEY hkey, LPCSTR name, LPSTR data, LPLONG count )
856 DWORD ret;
857 HKEY subkey = hkey;
859 TRACE("(%x,%s,%p,%ld)\n", hkey, debugstr_a(name), data, count ? *count : 0 );
861 if (name && name[0])
863 if ((ret = RegOpenKeyA( hkey, name, &subkey )) != ERROR_SUCCESS) return ret;
865 ret = RegQueryValueExA( subkey, NULL, NULL, NULL, (LPBYTE)data, count );
866 if (subkey != hkey) RegCloseKey( subkey );
867 if (ret == ERROR_FILE_NOT_FOUND)
869 /* return empty string if default value not found */
870 if (data) *data = 0;
871 if (count) *count = 1;
872 ret = ERROR_SUCCESS;
874 return ret;
878 /******************************************************************************
879 * RegEnumValueW [ADVAPI32.142]
881 * PARAMS
882 * hkey [I] Handle to key to query
883 * index [I] Index of value to query
884 * value [O] Value string
885 * val_count [I/O] Size of value buffer (in wchars)
886 * reserved [I] Reserved
887 * type [O] Type code
888 * data [O] Value data
889 * count [I/O] Size of data buffer (in bytes)
892 DWORD WINAPI RegEnumValueW( HKEY hkey, DWORD index, LPWSTR value, LPDWORD val_count,
893 LPDWORD reserved, LPDWORD type, LPBYTE data, LPDWORD count )
895 DWORD ret, len;
896 struct enum_key_value_request *req = get_req_buffer();
898 TRACE("(%x,%ld,%p,%p,%p,%p,%p,%p)\n",
899 hkey, index, value, val_count, reserved, type, data, count );
901 /* NT only checks count, not val_count */
902 if ((data && !count) || reserved) return ERROR_INVALID_PARAMETER;
904 req->hkey = hkey;
905 req->index = index;
906 req->offset = 0;
907 if ((ret = reg_server_call( REQ_ENUM_KEY_VALUE )) != ERROR_SUCCESS) return ret;
909 len = lstrlenW( req->name ) + 1;
910 if (len > *val_count) return ERROR_MORE_DATA;
911 memcpy( value, req->name, len * sizeof(WCHAR) );
912 *val_count = len - 1;
914 if (data)
916 if (*count < req->len) ret = ERROR_MORE_DATA;
917 else
919 /* copy the data */
920 unsigned int max = server_remaining( req->data );
921 unsigned int pos = 0;
922 while (pos < req->len)
924 unsigned int len = min( req->len - pos, max );
925 memcpy( data + pos, req->data, len );
926 if ((pos += len) >= req->len) break;
927 req->offset = pos;
928 if ((ret = reg_server_call( REQ_ENUM_KEY_VALUE )) != ERROR_SUCCESS) return ret;
931 /* if the type is REG_SZ and data is not 0-terminated
932 * and there is enough space in the buffer NT appends a \0 */
933 if (req->len && is_string(req->type) &&
934 (req->len < *count) && ((WCHAR *)data)[req->len-1]) ((WCHAR *)data)[req->len] = 0;
936 if (type) *type = req->type;
937 if (count) *count = req->len;
938 return ret;
942 /******************************************************************************
943 * RegEnumValueA [ADVAPI32.141]
945 DWORD WINAPI RegEnumValueA( HKEY hkey, DWORD index, LPSTR value, LPDWORD val_count,
946 LPDWORD reserved, LPDWORD type, LPBYTE data, LPDWORD count )
948 DWORD ret, len, total_len;
949 struct enum_key_value_request *req = get_req_buffer();
951 TRACE("(%x,%ld,%p,%p,%p,%p,%p,%p)\n",
952 hkey, index, value, val_count, reserved, type, data, count );
954 /* NT only checks count, not val_count */
955 if ((data && !count) || reserved) return ERROR_INVALID_PARAMETER;
957 req->hkey = hkey;
958 req->index = index;
959 req->offset = 0;
960 if ((ret = reg_server_call( REQ_ENUM_KEY_VALUE )) != ERROR_SUCCESS) return ret;
962 len = lstrlenW( req->name ) + 1;
963 if (len > *val_count) return ERROR_MORE_DATA;
964 memcpyWtoA( value, req->name, len );
965 *val_count = len - 1;
967 total_len = is_string( req->type ) ? req->len/sizeof(WCHAR) : req->len;
969 if (data)
971 if (*count < total_len) ret = ERROR_MORE_DATA;
972 else
974 /* copy the data */
975 unsigned int max = server_remaining( req->data );
976 unsigned int pos = 0;
977 while (pos < req->len)
979 unsigned int len = min( req->len - pos, max );
980 if (is_string( req->type ))
981 memcpyWtoA( data + pos/sizeof(WCHAR), (WCHAR *)req->data, len/sizeof(WCHAR) );
982 else
983 memcpy( data + pos, req->data, len );
984 if ((pos += len) >= req->len) break;
985 req->offset = pos;
986 if ((ret = reg_server_call( REQ_ENUM_KEY_VALUE )) != ERROR_SUCCESS) return ret;
989 /* if the type is REG_SZ and data is not 0-terminated
990 * and there is enough space in the buffer NT appends a \0 */
991 if (total_len && is_string(req->type) && (total_len < *count) && data[total_len-1])
992 data[total_len] = 0;
995 if (count) *count = total_len;
996 if (type) *type = req->type;
997 return ret;
1002 /******************************************************************************
1003 * RegDeleteValueW [ADVAPI32.136]
1005 * PARAMS
1006 * hkey [I] handle to key
1007 * name [I] name of value to delete
1009 * RETURNS
1010 * error status
1012 DWORD WINAPI RegDeleteValueW( HKEY hkey, LPCWSTR name )
1014 DWORD ret;
1015 struct delete_key_value_request *req = get_req_buffer();
1017 TRACE( "(0x%x,%s)\n", hkey, debugstr_w(name) );
1019 req->hkey = hkey;
1020 if ((ret = copy_nameW( req->name, name )) != ERROR_SUCCESS) return ret;
1021 return reg_server_call( REQ_DELETE_KEY_VALUE );
1025 /******************************************************************************
1026 * RegDeleteValueA [ADVAPI32.135]
1028 DWORD WINAPI RegDeleteValueA( HKEY hkey, LPCSTR name )
1030 DWORD ret;
1031 struct delete_key_value_request *req = get_req_buffer();
1033 TRACE( "(0x%x,%s)\n", hkey, debugstr_a(name) );
1035 req->hkey = hkey;
1036 if ((ret = copy_nameAtoW( req->name, name )) != ERROR_SUCCESS) return ret;
1037 return reg_server_call( REQ_DELETE_KEY_VALUE );
1041 /******************************************************************************
1042 * RegLoadKeyW [ADVAPI32.185]
1044 * PARAMS
1045 * hkey [I] Handle of open key
1046 * subkey [I] Address of name of subkey
1047 * filename [I] Address of filename for registry information
1049 LONG WINAPI RegLoadKeyW( HKEY hkey, LPCWSTR subkey, LPCWSTR filename )
1051 struct load_registry_request *req = get_req_buffer();
1052 HANDLE file;
1053 DWORD ret, err = GetLastError();
1055 TRACE( "(%x,%s,%s)\n", hkey, debugstr_w(subkey), debugstr_w(filename) );
1057 if (!filename || !*filename) return ERROR_INVALID_PARAMETER;
1058 if (!subkey || !*subkey) return ERROR_INVALID_PARAMETER;
1060 if ((file = CreateFileW( filename, GENERIC_READ, 0, NULL, OPEN_EXISTING,
1061 FILE_ATTRIBUTE_NORMAL, -1 )) == INVALID_HANDLE_VALUE)
1063 ret = GetLastError();
1064 goto done;
1066 req->hkey = hkey;
1067 req->file = file;
1068 if ((ret = copy_nameW( req->name, subkey )) != ERROR_SUCCESS) goto done;
1069 ret = reg_server_call( REQ_LOAD_REGISTRY );
1070 CloseHandle( file );
1072 done:
1073 SetLastError( err ); /* restore the last error code */
1074 return ret;
1078 /******************************************************************************
1079 * RegLoadKeyA [ADVAPI32.184]
1081 LONG WINAPI RegLoadKeyA( HKEY hkey, LPCSTR subkey, LPCSTR filename )
1083 struct load_registry_request *req = get_req_buffer();
1084 HANDLE file;
1085 DWORD ret, err = GetLastError();
1087 TRACE( "(%x,%s,%s)\n", hkey, debugstr_a(subkey), debugstr_a(filename) );
1089 if (!filename || !*filename) return ERROR_INVALID_PARAMETER;
1090 if (!subkey || !*subkey) return ERROR_INVALID_PARAMETER;
1092 if ((file = CreateFileA( filename, GENERIC_READ, 0, NULL, OPEN_EXISTING,
1093 FILE_ATTRIBUTE_NORMAL, -1 )) == INVALID_HANDLE_VALUE)
1095 ret = GetLastError();
1096 goto done;
1098 req->hkey = hkey;
1099 req->file = file;
1100 if ((ret = copy_nameAtoW( req->name, subkey )) != ERROR_SUCCESS) goto done;
1101 ret = reg_server_call( REQ_LOAD_REGISTRY );
1102 CloseHandle( file );
1104 done:
1105 SetLastError( err ); /* restore the last error code */
1106 return ret;
1110 /******************************************************************************
1111 * RegSaveKeyA [ADVAPI32.165]
1113 * PARAMS
1114 * hkey [I] Handle of key where save begins
1115 * lpFile [I] Address of filename to save to
1116 * sa [I] Address of security structure
1118 LONG WINAPI RegSaveKeyA( HKEY hkey, LPCSTR file, LPSECURITY_ATTRIBUTES sa )
1120 struct save_registry_request *req = get_req_buffer();
1121 char buffer[1024];
1122 int count = 0;
1123 LPSTR name;
1124 DWORD ret, err;
1125 HFILE handle;
1127 TRACE( "(%x,%s,%p)\n", hkey, debugstr_a(file), sa );
1129 if (!file || !*file) return ERROR_INVALID_PARAMETER;
1131 err = GetLastError();
1132 GetFullPathNameA( file, sizeof(buffer), buffer, &name );
1133 for (;;)
1135 sprintf( name, "reg%04x.tmp", count++ );
1136 handle = CreateFileA( buffer, GENERIC_WRITE, 0, NULL,
1137 CREATE_NEW, FILE_ATTRIBUTE_NORMAL, -1 );
1138 if (handle != INVALID_HANDLE_VALUE) break;
1139 if ((ret = GetLastError()) != ERROR_ALREADY_EXISTS) goto done;
1141 /* Something gone haywire ? Please report if this happens abnormally */
1142 if (count >= 100)
1143 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);
1146 req->hkey = hkey;
1147 req->file = handle;
1148 ret = reg_server_call( REQ_SAVE_REGISTRY );
1149 CloseHandle( handle );
1150 if (!ret)
1152 if (!MoveFileExA( buffer, file, MOVEFILE_REPLACE_EXISTING ))
1154 ERR( "Failed to move %s to %s\n", buffer, file );
1155 ret = GetLastError();
1158 if (ret) DeleteFileA( buffer );
1160 done:
1161 SetLastError( err ); /* restore last error code */
1162 return ret;
1166 /******************************************************************************
1167 * RegSaveKeyW [ADVAPI32.166]
1169 LONG WINAPI RegSaveKeyW( HKEY hkey, LPCWSTR file, LPSECURITY_ATTRIBUTES sa )
1171 LPSTR fileA = HEAP_strdupWtoA( GetProcessHeap(), 0, file );
1172 DWORD ret = RegSaveKeyA( hkey, fileA, sa );
1173 if (fileA) HeapFree( GetProcessHeap(), 0, fileA );
1174 return ret;