blob: a51e8e927dac4f66fe727dfa7832111847eec091 [file] [log] [blame]
Alexandre Julliard2fab2ef1999-11-23 19:41:34 +00001/*
2 * Registry management
3 *
4 * Copyright (C) 1999 Alexandre Julliard
5 *
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
10 *
11 * This file is concerned about handle management and interaction with the Wine server.
12 * Registry file I/O is in misc/registry.c.
Alexandre Julliard0799c1a2002-03-09 23:29:33 +000013 *
14 * This library is free software; you can redistribute it and/or
15 * modify it under the terms of the GNU Lesser General Public
16 * License as published by the Free Software Foundation; either
17 * version 2.1 of the License, or (at your option) any later version.
18 *
19 * This library is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
22 * Lesser General Public License for more details.
23 *
24 * You should have received a copy of the GNU Lesser General Public
25 * License along with this library; if not, write to the Free Software
26 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Alexandre Julliard2fab2ef1999-11-23 19:41:34 +000027 */
28
29#include <stdlib.h>
Alexandre Julliarde37c6e12003-09-05 23:08:26 +000030#include <stdarg.h>
Alexandre Julliard383da682000-02-10 22:15:21 +000031#include <stdio.h>
Alexandre Julliard2fab2ef1999-11-23 19:41:34 +000032
Ge van Geldorp1a1583a2005-11-28 17:32:54 +010033#include "ntstatus.h"
34#define WIN32_NO_STATUS
Alexandre Julliarde37c6e12003-09-05 23:08:26 +000035#include "windef.h"
Alexandre Julliard2fab2ef1999-11-23 19:41:34 +000036#include "winbase.h"
37#include "winreg.h"
38#include "winerror.h"
Matthew Davison6f2a0712003-01-20 23:23:12 +000039#include "winternl.h"
Michael Jungac615ce2006-02-14 10:41:18 +010040#include "winuser.h"
Alexandre Julliard2fab2ef1999-11-23 19:41:34 +000041
Robert Shearmanefbea2e2005-05-16 14:08:11 +000042#include "wine/unicode.h"
43#include "wine/debug.h"
44
Alexandre Julliard0799c1a2002-03-09 23:29:33 +000045WINE_DEFAULT_DEBUG_CHANNEL(reg);
Alexandre Julliard2fab2ef1999-11-23 19:41:34 +000046
Alexandre Julliardf2ef2c22002-09-13 21:42:28 +000047/* allowed bits for access mask */
48#define KEY_ACCESS_MASK (KEY_ALL_ACCESS | MAXIMUM_ALLOWED)
49
50#define HKEY_SPECIAL_ROOT_FIRST HKEY_CLASSES_ROOT
51#define HKEY_SPECIAL_ROOT_LAST HKEY_DYN_DATA
52#define NB_SPECIAL_ROOT_KEYS ((UINT)HKEY_SPECIAL_ROOT_LAST - (UINT)HKEY_SPECIAL_ROOT_FIRST + 1)
53
54static HKEY special_root_keys[NB_SPECIAL_ROOT_KEYS];
55
56static const WCHAR name_CLASSES_ROOT[] =
57 {'M','a','c','h','i','n','e','\\',
58 'S','o','f','t','w','a','r','e','\\',
59 'C','l','a','s','s','e','s',0};
60static const WCHAR name_LOCAL_MACHINE[] =
61 {'M','a','c','h','i','n','e',0};
62static const WCHAR name_USERS[] =
63 {'U','s','e','r',0};
64static const WCHAR name_PERFORMANCE_DATA[] =
65 {'P','e','r','f','D','a','t','a',0};
66static const WCHAR name_CURRENT_CONFIG[] =
67 {'M','a','c','h','i','n','e','\\',
68 'S','y','s','t','e','m','\\',
69 'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\',
Huw Davies8e9d88c12004-08-26 18:22:58 +000070 'H','a','r','d','w','a','r','e',' ','P','r','o','f','i','l','e','s','\\',
Alexandre Julliardf2ef2c22002-09-13 21:42:28 +000071 'C','u','r','r','e','n','t',0};
72static const WCHAR name_DYN_DATA[] =
73 {'D','y','n','D','a','t','a',0};
74
75#define DECL_STR(key) { sizeof(name_##key)-sizeof(WCHAR), sizeof(name_##key), (LPWSTR)name_##key }
76static UNICODE_STRING root_key_names[NB_SPECIAL_ROOT_KEYS] =
77{
78 DECL_STR(CLASSES_ROOT),
79 { 0, 0, NULL }, /* HKEY_CURRENT_USER is determined dynamically */
80 DECL_STR(LOCAL_MACHINE),
81 DECL_STR(USERS),
82 DECL_STR(PERFORMANCE_DATA),
83 DECL_STR(CURRENT_CONFIG),
84 DECL_STR(DYN_DATA)
85};
86#undef DECL_STR
87
Alexandre Julliard2fab2ef1999-11-23 19:41:34 +000088
Alexandre Julliard2fab2ef1999-11-23 19:41:34 +000089/* check if value type needs string conversion (Ansi<->Unicode) */
Michael Cardenas7dbce652002-03-21 01:24:52 +000090inline static int is_string( DWORD type )
Alexandre Julliard2fab2ef1999-11-23 19:41:34 +000091{
92 return (type == REG_SZ) || (type == REG_EXPAND_SZ) || (type == REG_MULTI_SZ);
93}
94
Michael Cardenas7dbce652002-03-21 01:24:52 +000095/* check if current version is NT or Win95 */
96inline static int is_version_nt(void)
97{
98 return !(GetVersion() & 0x80000000);
99}
Alexandre Julliard2fab2ef1999-11-23 19:41:34 +0000100
Alexandre Julliardf2ef2c22002-09-13 21:42:28 +0000101/* create one of the HKEY_* special root keys */
Mike McCormack5b2d5fd2005-06-17 13:58:33 +0000102static HKEY create_special_root_hkey( HANDLE hkey, DWORD access )
Alexandre Julliardf2ef2c22002-09-13 21:42:28 +0000103{
104 HKEY ret = 0;
Alexandre Julliard261e3762005-09-12 15:14:06 +0000105 int idx = (UINT_PTR)hkey - (UINT_PTR)HKEY_SPECIAL_ROOT_FIRST;
Alexandre Julliardf2ef2c22002-09-13 21:42:28 +0000106
107 if (hkey == HKEY_CURRENT_USER)
108 {
109 if (RtlOpenCurrentUser( access, &hkey )) return 0;
Michael Stefaniuccbacde52002-10-25 19:17:33 +0000110 TRACE( "HKEY_CURRENT_USER -> %p\n", hkey );
Alexandre Julliardf2ef2c22002-09-13 21:42:28 +0000111 }
112 else
113 {
114 OBJECT_ATTRIBUTES attr;
115
116 attr.Length = sizeof(attr);
117 attr.RootDirectory = 0;
118 attr.ObjectName = &root_key_names[idx];
119 attr.Attributes = 0;
120 attr.SecurityDescriptor = NULL;
121 attr.SecurityQualityOfService = NULL;
122 if (NtCreateKey( &hkey, access, &attr, 0, NULL, 0, NULL )) return 0;
Michael Stefaniuccbacde52002-10-25 19:17:33 +0000123 TRACE( "%s -> %p\n", debugstr_w(attr.ObjectName->Buffer), hkey );
Alexandre Julliardf2ef2c22002-09-13 21:42:28 +0000124 }
125
Michael Stefaniuccbacde52002-10-25 19:17:33 +0000126 if (!(ret = InterlockedCompareExchangePointer( (void **)&special_root_keys[idx], hkey, 0 )))
Alexandre Julliardf2ef2c22002-09-13 21:42:28 +0000127 ret = hkey;
128 else
129 NtClose( hkey ); /* somebody beat us to it */
130 return ret;
131}
132
133/* map the hkey from special root to normal key if necessary */
134inline static HKEY get_special_root_hkey( HKEY hkey )
135{
136 HKEY ret = hkey;
137
138 if ((hkey >= HKEY_SPECIAL_ROOT_FIRST) && (hkey <= HKEY_SPECIAL_ROOT_LAST))
139 {
Alexandre Julliard261e3762005-09-12 15:14:06 +0000140 if (!(ret = special_root_keys[(UINT_PTR)hkey - (UINT_PTR)HKEY_SPECIAL_ROOT_FIRST]))
Alexandre Julliardf2ef2c22002-09-13 21:42:28 +0000141 ret = create_special_root_hkey( hkey, KEY_ALL_ACCESS );
142 }
143 return ret;
144}
145
Juergen Schmieda44e0b02002-05-09 19:39:10 +0000146
Alexandre Julliard2fab2ef1999-11-23 19:41:34 +0000147/******************************************************************************
James Hawkins6a358c42004-07-13 23:33:14 +0000148 * RegCreateKeyExW [ADVAPI32.@]
Alexandre Julliard2fab2ef1999-11-23 19:41:34 +0000149 *
Jon Griffiths50ce0842004-04-23 21:32:34 +0000150 * See RegCreateKeyExA.
Alexandre Julliard2fab2ef1999-11-23 19:41:34 +0000151 */
Steven Edwardse14569d2005-07-28 10:18:23 +0000152DWORD WINAPI RegCreateKeyExW( HKEY hkey, LPCWSTR name, DWORD reserved, LPWSTR class,
Vincent Béron9a624912002-05-31 23:06:46 +0000153 DWORD options, REGSAM access, SECURITY_ATTRIBUTES *sa,
Alexandre Julliard5cf56a32002-10-03 19:46:27 +0000154 PHKEY retkey, LPDWORD dispos )
Alexandre Julliard2fab2ef1999-11-23 19:41:34 +0000155{
Alexandre Julliardbcf393a2000-10-01 01:44:50 +0000156 OBJECT_ATTRIBUTES attr;
157 UNICODE_STRING nameW, classW;
Alexandre Julliard2fab2ef1999-11-23 19:41:34 +0000158
159 if (reserved) return ERROR_INVALID_PARAMETER;
Juergen Schmieda44e0b02002-05-09 19:39:10 +0000160 if (!(access & KEY_ACCESS_MASK) || (access & ~KEY_ACCESS_MASK)) return ERROR_ACCESS_DENIED;
Alexandre Julliardf2ef2c22002-09-13 21:42:28 +0000161 if (!(hkey = get_special_root_hkey( hkey ))) return ERROR_INVALID_HANDLE;
Alexandre Julliard2fab2ef1999-11-23 19:41:34 +0000162
Alexandre Julliardbcf393a2000-10-01 01:44:50 +0000163 attr.Length = sizeof(attr);
164 attr.RootDirectory = hkey;
165 attr.ObjectName = &nameW;
166 attr.Attributes = 0;
167 attr.SecurityDescriptor = NULL;
168 attr.SecurityQualityOfService = NULL;
169 RtlInitUnicodeString( &nameW, name );
170 RtlInitUnicodeString( &classW, class );
171
Mike McCormack5b2d5fd2005-06-17 13:58:33 +0000172 return RtlNtStatusToDosError( NtCreateKey( (PHANDLE)retkey, access, &attr, 0,
Alexandre Julliardbcf393a2000-10-01 01:44:50 +0000173 &classW, options, dispos ) );
Alexandre Julliard2fab2ef1999-11-23 19:41:34 +0000174}
175
176
177/******************************************************************************
James Hawkins6a358c42004-07-13 23:33:14 +0000178 * RegCreateKeyExA [ADVAPI32.@]
Juergen Schmieda44e0b02002-05-09 19:39:10 +0000179 *
Jon Griffiths50ce0842004-04-23 21:32:34 +0000180 * Open a registry key, creating it if it doesn't exist.
181 *
182 * PARAMS
James Hawkins6a358c42004-07-13 23:33:14 +0000183 * hkey [I] Handle of the parent registry key
184 * name [I] Name of the new key to open or create
185 * reserved [I] Reserved, pass 0
186 * class [I] The object type of the new key
187 * options [I] Flags controlling the key creation (REG_OPTION_* flags from "winnt.h")
188 * access [I] Access level desired
189 * sa [I] Security attributes for the key
190 * retkey [O] Destination for the resulting handle
191 * dispos [O] Receives REG_CREATED_NEW_KEY or REG_OPENED_EXISTING_KEY
Jon Griffiths50ce0842004-04-23 21:32:34 +0000192 *
193 * RETURNS
James Hawkins6a358c42004-07-13 23:33:14 +0000194 * Success: ERROR_SUCCESS.
195 * Failure: A standard Win32 error code. retkey remains untouched.
Jon Griffiths50ce0842004-04-23 21:32:34 +0000196 *
197 * FIXME
James Hawkins6a358c42004-07-13 23:33:14 +0000198 * MAXIMUM_ALLOWED in access mask not supported by server
Alexandre Julliard2fab2ef1999-11-23 19:41:34 +0000199 */
Steven Edwardse14569d2005-07-28 10:18:23 +0000200DWORD WINAPI RegCreateKeyExA( HKEY hkey, LPCSTR name, DWORD reserved, LPSTR class,
Vincent Béron9a624912002-05-31 23:06:46 +0000201 DWORD options, REGSAM access, SECURITY_ATTRIBUTES *sa,
Alexandre Julliard5cf56a32002-10-03 19:46:27 +0000202 PHKEY retkey, LPDWORD dispos )
Alexandre Julliard2fab2ef1999-11-23 19:41:34 +0000203{
Alexandre Julliardbcf393a2000-10-01 01:44:50 +0000204 OBJECT_ATTRIBUTES attr;
Alexandre Julliardab5e9752001-03-23 19:12:01 +0000205 UNICODE_STRING classW;
Alexandre Julliardbcf393a2000-10-01 01:44:50 +0000206 ANSI_STRING nameA, classA;
207 NTSTATUS status;
Alexandre Julliard2fab2ef1999-11-23 19:41:34 +0000208
209 if (reserved) return ERROR_INVALID_PARAMETER;
Rein Klazes62b69d62005-12-08 13:49:02 +0100210 if (!is_version_nt())
211 {
212 access = KEY_ALL_ACCESS; /* Win95 ignores the access mask */
213 if (name && *name == '\\') name++; /* win9x,ME ignores one (and only one) beginning backslash */
214 }
Juergen Schmieda44e0b02002-05-09 19:39:10 +0000215 else if (!(access & KEY_ACCESS_MASK) || (access & ~KEY_ACCESS_MASK)) return ERROR_ACCESS_DENIED;
Alexandre Julliardf2ef2c22002-09-13 21:42:28 +0000216 if (!(hkey = get_special_root_hkey( hkey ))) return ERROR_INVALID_HANDLE;
Alexandre Julliard2fab2ef1999-11-23 19:41:34 +0000217
Alexandre Julliardbcf393a2000-10-01 01:44:50 +0000218 attr.Length = sizeof(attr);
219 attr.RootDirectory = hkey;
Alexandre Julliardab5e9752001-03-23 19:12:01 +0000220 attr.ObjectName = &NtCurrentTeb()->StaticUnicodeString;
Alexandre Julliardbcf393a2000-10-01 01:44:50 +0000221 attr.Attributes = 0;
222 attr.SecurityDescriptor = NULL;
223 attr.SecurityQualityOfService = NULL;
224 RtlInitAnsiString( &nameA, name );
225 RtlInitAnsiString( &classA, class );
226
Alexandre Julliardab5e9752001-03-23 19:12:01 +0000227 if (!(status = RtlAnsiStringToUnicodeString( &NtCurrentTeb()->StaticUnicodeString,
228 &nameA, FALSE )))
Alexandre Julliard2fab2ef1999-11-23 19:41:34 +0000229 {
Alexandre Julliardbcf393a2000-10-01 01:44:50 +0000230 if (!(status = RtlAnsiStringToUnicodeString( &classW, &classA, TRUE )))
231 {
Mike McCormack5b2d5fd2005-06-17 13:58:33 +0000232 status = NtCreateKey( (PHANDLE)retkey, access, &attr, 0, &classW, options, dispos );
Alexandre Julliardbcf393a2000-10-01 01:44:50 +0000233 RtlFreeUnicodeString( &classW );
234 }
Alexandre Julliard2fab2ef1999-11-23 19:41:34 +0000235 }
Alexandre Julliardbcf393a2000-10-01 01:44:50 +0000236 return RtlNtStatusToDosError( status );
Alexandre Julliard2fab2ef1999-11-23 19:41:34 +0000237}
238
239
240/******************************************************************************
James Hawkins6a358c42004-07-13 23:33:14 +0000241 * RegCreateKeyW [ADVAPI32.@]
242 *
243 * Creates the specified reg key.
244 *
245 * PARAMS
246 * hKey [I] Handle to an open key.
247 * lpSubKey [I] Name of a key that will be opened or created.
248 * phkResult [O] Receives a handle to the opened or created key.
249 *
250 * RETURNS
251 * Success: ERROR_SUCCESS
252 * Failure: nonzero error code defined in Winerror.h
Alexandre Julliard2fab2ef1999-11-23 19:41:34 +0000253 */
James Hawkins6a358c42004-07-13 23:33:14 +0000254DWORD WINAPI RegCreateKeyW( HKEY hkey, LPCWSTR lpSubKey, PHKEY phkResult )
Alexandre Julliard2fab2ef1999-11-23 19:41:34 +0000255{
256 /* FIXME: previous implementation converted ERROR_INVALID_HANDLE to ERROR_BADKEY, */
257 /* but at least my version of NT (4.0 SP5) doesn't do this. -- AJ */
James Hawkins6a358c42004-07-13 23:33:14 +0000258 return RegCreateKeyExW( hkey, lpSubKey, 0, NULL, REG_OPTION_NON_VOLATILE,
259 KEY_ALL_ACCESS, NULL, phkResult, NULL );
Alexandre Julliard2fab2ef1999-11-23 19:41:34 +0000260}
261
262
263/******************************************************************************
James Hawkins6a358c42004-07-13 23:33:14 +0000264 * RegCreateKeyA [ADVAPI32.@]
Alexandre Julliard2fab2ef1999-11-23 19:41:34 +0000265 *
Markus Amslerd45811c2005-11-04 11:43:27 +0000266 * See RegCreateKeyW.
James Hawkins6a358c42004-07-13 23:33:14 +0000267 */
268DWORD WINAPI RegCreateKeyA( HKEY hkey, LPCSTR lpSubKey, PHKEY phkResult )
269{
270 return RegCreateKeyExA( hkey, lpSubKey, 0, NULL, REG_OPTION_NON_VOLATILE,
271 KEY_ALL_ACCESS, NULL, phkResult, NULL );
272}
273
274
275
276/******************************************************************************
277 * RegOpenKeyExW [ADVAPI32.@]
278 *
Jon Griffiths50ce0842004-04-23 21:32:34 +0000279 * See RegOpenKeyExA.
Alexandre Julliard2fab2ef1999-11-23 19:41:34 +0000280 */
Alexandre Julliard5cf56a32002-10-03 19:46:27 +0000281DWORD WINAPI RegOpenKeyExW( HKEY hkey, LPCWSTR name, DWORD reserved, REGSAM access, PHKEY retkey )
Alexandre Julliard2fab2ef1999-11-23 19:41:34 +0000282{
Alexandre Julliardbcf393a2000-10-01 01:44:50 +0000283 OBJECT_ATTRIBUTES attr;
284 UNICODE_STRING nameW;
Alexandre Julliard2fab2ef1999-11-23 19:41:34 +0000285
Alexandre Julliardf2ef2c22002-09-13 21:42:28 +0000286 if (!(hkey = get_special_root_hkey( hkey ))) return ERROR_INVALID_HANDLE;
287
Alexandre Julliardbcf393a2000-10-01 01:44:50 +0000288 attr.Length = sizeof(attr);
289 attr.RootDirectory = hkey;
290 attr.ObjectName = &nameW;
291 attr.Attributes = 0;
292 attr.SecurityDescriptor = NULL;
293 attr.SecurityQualityOfService = NULL;
294 RtlInitUnicodeString( &nameW, name );
Mike McCormack5b2d5fd2005-06-17 13:58:33 +0000295 return RtlNtStatusToDosError( NtOpenKey( (PHANDLE)retkey, access, &attr ) );
Alexandre Julliard2fab2ef1999-11-23 19:41:34 +0000296}
297
298
299/******************************************************************************
James Hawkins6a358c42004-07-13 23:33:14 +0000300 * RegOpenKeyExA [ADVAPI32.@]
Jon Griffiths50ce0842004-04-23 21:32:34 +0000301 *
302 * Open a registry key.
303 *
304 * PARAMS
James Hawkins6a358c42004-07-13 23:33:14 +0000305 * hkey [I] Handle of open key
306 * name [I] Name of subkey to open
307 * reserved [I] Reserved - must be zero
308 * access [I] Security access mask
309 * retkey [O] Handle to open key
Jon Griffiths50ce0842004-04-23 21:32:34 +0000310 *
311 * RETURNS
James Hawkins6a358c42004-07-13 23:33:14 +0000312 * Success: ERROR_SUCCESS
313 * Failure: A standard Win32 error code. retkey is set to 0.
Jon Griffiths50ce0842004-04-23 21:32:34 +0000314 *
315 * NOTES
James Hawkins6a358c42004-07-13 23:33:14 +0000316 * Unlike RegCreateKeyExA(), this function will not create the key if it
317 * does not exist.
Alexandre Julliard2fab2ef1999-11-23 19:41:34 +0000318 */
Alexandre Julliard5cf56a32002-10-03 19:46:27 +0000319DWORD WINAPI RegOpenKeyExA( HKEY hkey, LPCSTR name, DWORD reserved, REGSAM access, PHKEY retkey )
Alexandre Julliard2fab2ef1999-11-23 19:41:34 +0000320{
Alexandre Julliardbcf393a2000-10-01 01:44:50 +0000321 OBJECT_ATTRIBUTES attr;
Alexandre Julliardbcf393a2000-10-01 01:44:50 +0000322 STRING nameA;
323 NTSTATUS status;
Alexandre Julliard2fab2ef1999-11-23 19:41:34 +0000324
Michael Cardenas7dbce652002-03-21 01:24:52 +0000325 if (!is_version_nt()) access = KEY_ALL_ACCESS; /* Win95 ignores the access mask */
326
Alexandre Julliardf2ef2c22002-09-13 21:42:28 +0000327 if (!(hkey = get_special_root_hkey( hkey ))) return ERROR_INVALID_HANDLE;
328
Alexandre Julliardbcf393a2000-10-01 01:44:50 +0000329 attr.Length = sizeof(attr);
330 attr.RootDirectory = hkey;
Alexandre Julliardab5e9752001-03-23 19:12:01 +0000331 attr.ObjectName = &NtCurrentTeb()->StaticUnicodeString;
Alexandre Julliardbcf393a2000-10-01 01:44:50 +0000332 attr.Attributes = 0;
333 attr.SecurityDescriptor = NULL;
334 attr.SecurityQualityOfService = NULL;
Alexandre Julliard2fab2ef1999-11-23 19:41:34 +0000335
Alexandre Julliardbcf393a2000-10-01 01:44:50 +0000336 RtlInitAnsiString( &nameA, name );
Alexandre Julliardab5e9752001-03-23 19:12:01 +0000337 if (!(status = RtlAnsiStringToUnicodeString( &NtCurrentTeb()->StaticUnicodeString,
338 &nameA, FALSE )))
Alexandre Julliardbcf393a2000-10-01 01:44:50 +0000339 {
Mike McCormack5b2d5fd2005-06-17 13:58:33 +0000340 status = NtOpenKey( (PHANDLE)retkey, access, &attr );
Alexandre Julliardbcf393a2000-10-01 01:44:50 +0000341 }
342 return RtlNtStatusToDosError( status );
Alexandre Julliard2fab2ef1999-11-23 19:41:34 +0000343}
344
345
346/******************************************************************************
James Hawkins6a358c42004-07-13 23:33:14 +0000347 * RegOpenKeyW [ADVAPI32.@]
Alexandre Julliard2fab2ef1999-11-23 19:41:34 +0000348 *
Jon Griffiths50ce0842004-04-23 21:32:34 +0000349 * See RegOpenKeyA.
Alexandre Julliard2fab2ef1999-11-23 19:41:34 +0000350 */
Alexandre Julliard5cf56a32002-10-03 19:46:27 +0000351DWORD WINAPI RegOpenKeyW( HKEY hkey, LPCWSTR name, PHKEY retkey )
Alexandre Julliard2fab2ef1999-11-23 19:41:34 +0000352{
James Hawkinse8d1e2f2005-02-25 16:52:10 +0000353 if (!name || !*name)
354 {
355 *retkey = hkey;
356 return ERROR_SUCCESS;
357 }
Alexandre Julliard2fab2ef1999-11-23 19:41:34 +0000358 return RegOpenKeyExW( hkey, name, 0, KEY_ALL_ACCESS, retkey );
359}
360
361
362/******************************************************************************
James Hawkins6a358c42004-07-13 23:33:14 +0000363 * RegOpenKeyA [ADVAPI32.@]
Jon Griffiths50ce0842004-04-23 21:32:34 +0000364 *
365 * Open a registry key.
366 *
367 * PARAMS
James Hawkins6a358c42004-07-13 23:33:14 +0000368 * hkey [I] Handle of parent key to open the new key under
369 * name [I] Name of the key under hkey to open
370 * retkey [O] Destination for the resulting Handle
Jon Griffiths50ce0842004-04-23 21:32:34 +0000371 *
372 * RETURNS
James Hawkins6a358c42004-07-13 23:33:14 +0000373 * Success: ERROR_SUCCESS
374 * Failure: A standard Win32 error code. retkey is set to 0.
Alexandre Julliard2fab2ef1999-11-23 19:41:34 +0000375 */
Alexandre Julliard5cf56a32002-10-03 19:46:27 +0000376DWORD WINAPI RegOpenKeyA( HKEY hkey, LPCSTR name, PHKEY retkey )
Alexandre Julliard2fab2ef1999-11-23 19:41:34 +0000377{
James Hawkinse8d1e2f2005-02-25 16:52:10 +0000378 if (!name || !*name)
379 {
380 *retkey = hkey;
381 return ERROR_SUCCESS;
382 }
Alexandre Julliard2fab2ef1999-11-23 19:41:34 +0000383 return RegOpenKeyExA( hkey, name, 0, KEY_ALL_ACCESS, retkey );
384}
385
386
David Elliott44f84b52000-10-29 01:24:54 +0000387/******************************************************************************
James Hawkins6a358c42004-07-13 23:33:14 +0000388 * RegOpenCurrentUser [ADVAPI32.@]
Markus Amslerec350522005-11-12 19:12:03 +0000389 *
390 * Get a handle to the HKEY_CURRENT_USER key for the user
391 * the current thread is impersonating.
392 *
393 * PARAMS
394 * access [I] Desired access rights to the key
395 * retkey [O] Handle to the opened key
396 *
397 * RETURNS
398 * Success: ERROR_SUCCESS
399 * Failure: nonzero error code from Winerror.h
400 *
401 * FIXME
402 * This function is supposed to retrieve a handle to the
403 * HKEY_CURRENT_USER for the user the current thread is impersonating.
404 * Since Wine does not currently allow threads to impersonate other users,
405 * this stub should work fine.
David Elliott44f84b52000-10-29 01:24:54 +0000406 */
407DWORD WINAPI RegOpenCurrentUser( REGSAM access, PHKEY retkey )
408{
409 return RegOpenKeyExA( HKEY_CURRENT_USER, "", 0, access, retkey );
410}
411
412
Alexandre Julliard2fab2ef1999-11-23 19:41:34 +0000413
414/******************************************************************************
James Hawkins6a358c42004-07-13 23:33:14 +0000415 * RegEnumKeyExW [ADVAPI32.@]
Alexandre Julliard2fab2ef1999-11-23 19:41:34 +0000416 *
Markus Amslerec350522005-11-12 19:12:03 +0000417 * Enumerate subkeys of the specified open registry key.
418 *
Alexandre Julliard2fab2ef1999-11-23 19:41:34 +0000419 * PARAMS
James Hawkins6a358c42004-07-13 23:33:14 +0000420 * hkey [I] Handle to key to enumerate
421 * index [I] Index of subkey to enumerate
422 * name [O] Buffer for subkey name
423 * name_len [O] Size of subkey buffer
424 * reserved [I] Reserved
425 * class [O] Buffer for class string
426 * class_len [O] Size of class buffer
427 * ft [O] Time key last written to
428 *
429 * RETURNS
430 * Success: ERROR_SUCCESS
431 * Failure: System error code. If there are no more subkeys available, the
432 * function returns ERROR_NO_MORE_ITEMS.
Alexandre Julliard2fab2ef1999-11-23 19:41:34 +0000433 */
434DWORD WINAPI RegEnumKeyExW( HKEY hkey, DWORD index, LPWSTR name, LPDWORD name_len,
435 LPDWORD reserved, LPWSTR class, LPDWORD class_len, FILETIME *ft )
436{
Alexandre Julliard454355e2000-10-02 03:46:58 +0000437 NTSTATUS status;
438 char buffer[256], *buf_ptr = buffer;
439 KEY_NODE_INFORMATION *info = (KEY_NODE_INFORMATION *)buffer;
440 DWORD total_size;
Alexandre Julliard2fab2ef1999-11-23 19:41:34 +0000441
Michael Stefaniuccbacde52002-10-25 19:17:33 +0000442 TRACE( "(%p,%ld,%p,%p(%ld),%p,%p,%p,%p)\n", hkey, index, name, name_len,
Alexandre Julliard2fab2ef1999-11-23 19:41:34 +0000443 name_len ? *name_len : -1, reserved, class, class_len, ft );
444
445 if (reserved) return ERROR_INVALID_PARAMETER;
Alexandre Julliardf2ef2c22002-09-13 21:42:28 +0000446 if (!(hkey = get_special_root_hkey( hkey ))) return ERROR_INVALID_HANDLE;
Rein Klazes0bb6fdd2002-07-05 01:21:13 +0000447
Alexandre Julliard454355e2000-10-02 03:46:58 +0000448 status = NtEnumerateKey( hkey, index, KeyNodeInformation,
449 buffer, sizeof(buffer), &total_size );
Alexandre Julliard2fab2ef1999-11-23 19:41:34 +0000450
Alexandre Julliard454355e2000-10-02 03:46:58 +0000451 while (status == STATUS_BUFFER_OVERFLOW)
Alexandre Julliard2fab2ef1999-11-23 19:41:34 +0000452 {
Alexandre Julliard454355e2000-10-02 03:46:58 +0000453 /* retry with a dynamically allocated buffer */
454 if (buf_ptr != buffer) HeapFree( GetProcessHeap(), 0, buf_ptr );
455 if (!(buf_ptr = HeapAlloc( GetProcessHeap(), 0, total_size )))
456 return ERROR_NOT_ENOUGH_MEMORY;
457 info = (KEY_NODE_INFORMATION *)buf_ptr;
458 status = NtEnumerateKey( hkey, index, KeyNodeInformation,
459 buf_ptr, total_size, &total_size );
Alexandre Julliard2fab2ef1999-11-23 19:41:34 +0000460 }
Alexandre Julliard454355e2000-10-02 03:46:58 +0000461
462 if (!status)
463 {
464 DWORD len = info->NameLength / sizeof(WCHAR);
465 DWORD cls_len = info->ClassLength / sizeof(WCHAR);
466
Dmitry Timoshkov6b6596a2001-11-23 18:44:43 +0000467 if (ft) *ft = *(FILETIME *)&info->LastWriteTime;
Alexandre Julliard454355e2000-10-02 03:46:58 +0000468
Aric Stewart20a4cc32002-02-05 19:45:55 +0000469 if (len >= *name_len || (class && class_len && (cls_len >= *class_len)))
Alexandre Julliard454355e2000-10-02 03:46:58 +0000470 status = STATUS_BUFFER_OVERFLOW;
471 else
472 {
473 *name_len = len;
474 memcpy( name, info->Name, info->NameLength );
475 name[len] = 0;
476 if (class_len)
477 {
478 *class_len = cls_len;
479 if (class)
480 {
481 memcpy( class, buf_ptr + info->ClassOffset, info->ClassLength );
482 class[cls_len] = 0;
483 }
484 }
485 }
486 }
487
488 if (buf_ptr != buffer) HeapFree( GetProcessHeap(), 0, buf_ptr );
489 return RtlNtStatusToDosError( status );
Alexandre Julliard2fab2ef1999-11-23 19:41:34 +0000490}
491
492
493/******************************************************************************
James Hawkins6a358c42004-07-13 23:33:14 +0000494 * RegEnumKeyExA [ADVAPI32.@]
495 *
Markus Amslerd45811c2005-11-04 11:43:27 +0000496 * See RegEnumKeyExW.
Alexandre Julliard2fab2ef1999-11-23 19:41:34 +0000497 */
498DWORD WINAPI RegEnumKeyExA( HKEY hkey, DWORD index, LPSTR name, LPDWORD name_len,
499 LPDWORD reserved, LPSTR class, LPDWORD class_len, FILETIME *ft )
500{
Alexandre Julliard454355e2000-10-02 03:46:58 +0000501 NTSTATUS status;
502 char buffer[256], *buf_ptr = buffer;
503 KEY_NODE_INFORMATION *info = (KEY_NODE_INFORMATION *)buffer;
504 DWORD total_size;
Alexandre Julliard2fab2ef1999-11-23 19:41:34 +0000505
Michael Stefaniuccbacde52002-10-25 19:17:33 +0000506 TRACE( "(%p,%ld,%p,%p(%ld),%p,%p,%p,%p)\n", hkey, index, name, name_len,
Alexandre Julliard2fab2ef1999-11-23 19:41:34 +0000507 name_len ? *name_len : -1, reserved, class, class_len, ft );
508
509 if (reserved) return ERROR_INVALID_PARAMETER;
Alexandre Julliardf2ef2c22002-09-13 21:42:28 +0000510 if (!(hkey = get_special_root_hkey( hkey ))) return ERROR_INVALID_HANDLE;
Rein Klazes0bb6fdd2002-07-05 01:21:13 +0000511
Alexandre Julliard454355e2000-10-02 03:46:58 +0000512 status = NtEnumerateKey( hkey, index, KeyNodeInformation,
513 buffer, sizeof(buffer), &total_size );
Alexandre Julliard2fab2ef1999-11-23 19:41:34 +0000514
Alexandre Julliard454355e2000-10-02 03:46:58 +0000515 while (status == STATUS_BUFFER_OVERFLOW)
Alexandre Julliard2fab2ef1999-11-23 19:41:34 +0000516 {
Alexandre Julliard454355e2000-10-02 03:46:58 +0000517 /* retry with a dynamically allocated buffer */
518 if (buf_ptr != buffer) HeapFree( GetProcessHeap(), 0, buf_ptr );
519 if (!(buf_ptr = HeapAlloc( GetProcessHeap(), 0, total_size )))
520 return ERROR_NOT_ENOUGH_MEMORY;
521 info = (KEY_NODE_INFORMATION *)buf_ptr;
522 status = NtEnumerateKey( hkey, index, KeyNodeInformation,
523 buf_ptr, total_size, &total_size );
Alexandre Julliard2fab2ef1999-11-23 19:41:34 +0000524 }
Alexandre Julliard454355e2000-10-02 03:46:58 +0000525
526 if (!status)
527 {
Alexandre Julliard60fd03d2001-12-05 22:18:48 +0000528 DWORD len, cls_len;
Alexandre Julliard454355e2000-10-02 03:46:58 +0000529
Alexandre Julliard60fd03d2001-12-05 22:18:48 +0000530 RtlUnicodeToMultiByteSize( &len, info->Name, info->NameLength );
531 RtlUnicodeToMultiByteSize( &cls_len, (WCHAR *)(buf_ptr + info->ClassOffset),
532 info->ClassLength );
Dmitry Timoshkov6b6596a2001-11-23 18:44:43 +0000533 if (ft) *ft = *(FILETIME *)&info->LastWriteTime;
Alexandre Julliard454355e2000-10-02 03:46:58 +0000534
Aric Stewart20a4cc32002-02-05 19:45:55 +0000535 if (len >= *name_len || (class && class_len && (cls_len >= *class_len)))
Alexandre Julliard454355e2000-10-02 03:46:58 +0000536 status = STATUS_BUFFER_OVERFLOW;
537 else
538 {
539 *name_len = len;
Alexandre Julliard60fd03d2001-12-05 22:18:48 +0000540 RtlUnicodeToMultiByteN( name, len, NULL, info->Name, info->NameLength );
Alexandre Julliard454355e2000-10-02 03:46:58 +0000541 name[len] = 0;
542 if (class_len)
543 {
544 *class_len = cls_len;
545 if (class)
546 {
Alexandre Julliard60fd03d2001-12-05 22:18:48 +0000547 RtlUnicodeToMultiByteN( class, cls_len, NULL,
548 (WCHAR *)(buf_ptr + info->ClassOffset),
549 info->ClassLength );
Alexandre Julliard454355e2000-10-02 03:46:58 +0000550 class[cls_len] = 0;
551 }
552 }
553 }
554 }
555
556 if (buf_ptr != buffer) HeapFree( GetProcessHeap(), 0, buf_ptr );
557 return RtlNtStatusToDosError( status );
Alexandre Julliard2fab2ef1999-11-23 19:41:34 +0000558}
559
560
561/******************************************************************************
James Hawkins6a358c42004-07-13 23:33:14 +0000562 * RegEnumKeyW [ADVAPI32.@]
563 *
564 * Enumerates subkyes of the specified open reg key.
565 *
566 * PARAMS
567 * hKey [I] Handle to an open key.
568 * dwIndex [I] Index of the subkey of hKey to retrieve.
569 * lpName [O] Name of the subkey.
570 * cchName [I] Size of lpName in TCHARS.
571 *
572 * RETURNS
573 * Success: ERROR_SUCCESS
574 * Failure: system error code. If there are no more subkeys available, the
575 * function returns ERROR_NO_MORE_ITEMS.
Alexandre Julliard2fab2ef1999-11-23 19:41:34 +0000576 */
577DWORD WINAPI RegEnumKeyW( HKEY hkey, DWORD index, LPWSTR name, DWORD name_len )
578{
579 return RegEnumKeyExW( hkey, index, name, &name_len, NULL, NULL, NULL, NULL );
580}
581
582
583/******************************************************************************
James Hawkins6a358c42004-07-13 23:33:14 +0000584 * RegEnumKeyA [ADVAPI32.@]
585 *
Markus Amslerd45811c2005-11-04 11:43:27 +0000586 * See RegEnumKeyW.
Alexandre Julliard2fab2ef1999-11-23 19:41:34 +0000587 */
588DWORD WINAPI RegEnumKeyA( HKEY hkey, DWORD index, LPSTR name, DWORD name_len )
589{
590 return RegEnumKeyExA( hkey, index, name, &name_len, NULL, NULL, NULL, NULL );
591}
592
593
594/******************************************************************************
James Hawkins6a358c42004-07-13 23:33:14 +0000595 * RegQueryInfoKeyW [ADVAPI32.@]
Alexandre Julliard2fab2ef1999-11-23 19:41:34 +0000596 *
Markus Amslerd45811c2005-11-04 11:43:27 +0000597 * Retrieves information about the specified registry key.
598 *
Alexandre Julliard2fab2ef1999-11-23 19:41:34 +0000599 * PARAMS
600 * hkey [I] Handle to key to query
601 * class [O] Buffer for class string
602 * class_len [O] Size of class string buffer
603 * reserved [I] Reserved
604 * subkeys [O] Buffer for number of subkeys
605 * max_subkey [O] Buffer for longest subkey name length
606 * max_class [O] Buffer for longest class string length
607 * values [O] Buffer for number of value entries
608 * max_value [O] Buffer for longest value name length
609 * max_data [O] Buffer for longest value data length
610 * security [O] Buffer for security descriptor length
611 * modif [O] Modification time
612 *
Markus Amslerd45811c2005-11-04 11:43:27 +0000613 * RETURNS
614 * Success: ERROR_SUCCESS
615 * Failure: system error code.
616 *
617 * NOTES
618 * - win95 allows class to be valid and class_len to be NULL
619 * - winnt returns ERROR_INVALID_PARAMETER if class is valid and class_len is NULL
620 * - both allow class to be NULL and class_len to be NULL
621 * (it's hard to test validity, so test !NULL instead)
Alexandre Julliard2fab2ef1999-11-23 19:41:34 +0000622 */
623DWORD WINAPI RegQueryInfoKeyW( HKEY hkey, LPWSTR class, LPDWORD class_len, LPDWORD reserved,
624 LPDWORD subkeys, LPDWORD max_subkey, LPDWORD max_class,
625 LPDWORD values, LPDWORD max_value, LPDWORD max_data,
626 LPDWORD security, FILETIME *modif )
627{
Alexandre Julliard454355e2000-10-02 03:46:58 +0000628 NTSTATUS status;
629 char buffer[256], *buf_ptr = buffer;
630 KEY_FULL_INFORMATION *info = (KEY_FULL_INFORMATION *)buffer;
631 DWORD total_size;
Alexandre Julliard2fab2ef1999-11-23 19:41:34 +0000632
Michael Stefaniuccbacde52002-10-25 19:17:33 +0000633 TRACE( "(%p,%p,%ld,%p,%p,%p,%p,%p,%p,%p,%p)\n", hkey, class, class_len ? *class_len : 0,
Alexandre Julliard2fab2ef1999-11-23 19:41:34 +0000634 reserved, subkeys, max_subkey, values, max_value, max_data, security, modif );
635
Michael Cardenas7dbce652002-03-21 01:24:52 +0000636 if (class && !class_len && is_version_nt()) return ERROR_INVALID_PARAMETER;
Alexandre Julliardf2ef2c22002-09-13 21:42:28 +0000637 if (!(hkey = get_special_root_hkey( hkey ))) return ERROR_INVALID_HANDLE;
Alexandre Julliard2fab2ef1999-11-23 19:41:34 +0000638
Alexandre Julliard454355e2000-10-02 03:46:58 +0000639 status = NtQueryKey( hkey, KeyFullInformation, buffer, sizeof(buffer), &total_size );
Alexandre Julliardc6615832001-02-14 21:45:52 +0000640 if (status && status != STATUS_BUFFER_OVERFLOW) goto done;
Alexandre Julliard2fab2ef1999-11-23 19:41:34 +0000641
642 if (class)
643 {
Alexandre Julliard454355e2000-10-02 03:46:58 +0000644 /* retry with a dynamically allocated buffer */
645 while (status == STATUS_BUFFER_OVERFLOW)
Alexandre Julliard2fab2ef1999-11-23 19:41:34 +0000646 {
Alexandre Julliard454355e2000-10-02 03:46:58 +0000647 if (buf_ptr != buffer) HeapFree( GetProcessHeap(), 0, buf_ptr );
648 if (!(buf_ptr = HeapAlloc( GetProcessHeap(), 0, total_size )))
649 return ERROR_NOT_ENOUGH_MEMORY;
650 info = (KEY_FULL_INFORMATION *)buf_ptr;
651 status = NtQueryKey( hkey, KeyFullInformation, buf_ptr, total_size, &total_size );
Alexandre Julliard2fab2ef1999-11-23 19:41:34 +0000652 }
Alexandre Julliard454355e2000-10-02 03:46:58 +0000653
Alexandre Julliardc6615832001-02-14 21:45:52 +0000654 if (status) goto done;
655
656 if (class_len && (info->ClassLength/sizeof(WCHAR) + 1 > *class_len))
Alexandre Julliard454355e2000-10-02 03:46:58 +0000657 {
Alexandre Julliardc6615832001-02-14 21:45:52 +0000658 status = STATUS_BUFFER_OVERFLOW;
659 }
660 else
661 {
662 memcpy( class, buf_ptr + info->ClassOffset, info->ClassLength );
663 class[info->ClassLength/sizeof(WCHAR)] = 0;
Alexandre Julliard454355e2000-10-02 03:46:58 +0000664 }
Alexandre Julliard2fab2ef1999-11-23 19:41:34 +0000665 }
Alexandre Julliardc6615832001-02-14 21:45:52 +0000666 else status = STATUS_SUCCESS;
Alexandre Julliard454355e2000-10-02 03:46:58 +0000667
Alexandre Julliardc6615832001-02-14 21:45:52 +0000668 if (class_len) *class_len = info->ClassLength / sizeof(WCHAR);
669 if (subkeys) *subkeys = info->SubKeys;
670 if (max_subkey) *max_subkey = info->MaxNameLen;
671 if (max_class) *max_class = info->MaxClassLen;
672 if (values) *values = info->Values;
673 if (max_value) *max_value = info->MaxValueNameLen;
674 if (max_data) *max_data = info->MaxValueDataLen;
Dmitry Timoshkov6b6596a2001-11-23 18:44:43 +0000675 if (modif) *modif = *(FILETIME *)&info->LastWriteTime;
Alexandre Julliard454355e2000-10-02 03:46:58 +0000676
Alexandre Julliardc6615832001-02-14 21:45:52 +0000677 done:
Alexandre Julliard454355e2000-10-02 03:46:58 +0000678 if (buf_ptr != buffer) HeapFree( GetProcessHeap(), 0, buf_ptr );
679 return RtlNtStatusToDosError( status );
Alexandre Julliard2fab2ef1999-11-23 19:41:34 +0000680}
681
682
683/******************************************************************************
James Hawkins6a358c42004-07-13 23:33:14 +0000684 * RegQueryMultipleValuesA [ADVAPI32.@]
685 *
686 * Retrieves the type and data for a list of value names associated with a key.
687 *
688 * PARAMS
689 * hKey [I] Handle to an open key.
690 * val_list [O] Array of VALENT structures that describes the entries.
691 * num_vals [I] Number of elements in val_list.
692 * lpValueBuf [O] Pointer to a buffer that receives the data for each value.
693 * ldwTotsize [I/O] Size of lpValueBuf.
694 *
695 * RETURNS
696 * Success: ERROR_SUCCESS. ldwTotsize contains num bytes copied.
697 * Failure: nonzero error code from Winerror.h ldwTotsize contains num needed
698 * bytes.
Dominik Strasser751c4542002-07-20 20:02:55 +0000699 */
700DWORD WINAPI RegQueryMultipleValuesA(HKEY hkey, PVALENTA val_list, DWORD num_vals,
701 LPSTR lpValueBuf, LPDWORD ldwTotsize)
702{
Hans Leidekker411fc5f2004-09-02 23:00:53 +0000703 unsigned int i;
Dominik Strasser751c4542002-07-20 20:02:55 +0000704 DWORD maxBytes = *ldwTotsize;
705 HRESULT status;
706 LPSTR bufptr = lpValueBuf;
707 *ldwTotsize = 0;
708
Michael Stefaniuccbacde52002-10-25 19:17:33 +0000709 TRACE("(%p,%p,%ld,%p,%p=%ld)\n", hkey, val_list, num_vals, lpValueBuf, ldwTotsize, *ldwTotsize);
Dominik Strasser751c4542002-07-20 20:02:55 +0000710
711 for(i=0; i < num_vals; ++i)
712 {
713
714 val_list[i].ve_valuelen=0;
715 status = RegQueryValueExA(hkey, val_list[i].ve_valuename, NULL, NULL, NULL, &val_list[i].ve_valuelen);
716 if(status != ERROR_SUCCESS)
717 {
718 return status;
719 }
720
721 if(lpValueBuf != NULL && *ldwTotsize + val_list[i].ve_valuelen <= maxBytes)
722 {
723 status = RegQueryValueExA(hkey, val_list[i].ve_valuename, NULL, &val_list[i].ve_type,
Mike McCormack257c3372005-07-07 12:08:42 +0000724 (LPBYTE)bufptr, &val_list[i].ve_valuelen);
Dominik Strasser751c4542002-07-20 20:02:55 +0000725 if(status != ERROR_SUCCESS)
726 {
727 return status;
728 }
729
730 val_list[i].ve_valueptr = (DWORD_PTR)bufptr;
731
732 bufptr += val_list[i].ve_valuelen;
733 }
734
735 *ldwTotsize += val_list[i].ve_valuelen;
736 }
737 return lpValueBuf != NULL && *ldwTotsize <= maxBytes ? ERROR_SUCCESS : ERROR_MORE_DATA;
738}
739
740
741/******************************************************************************
James Hawkins6a358c42004-07-13 23:33:14 +0000742 * RegQueryMultipleValuesW [ADVAPI32.@]
743 *
Markus Amslerd45811c2005-11-04 11:43:27 +0000744 * See RegQueryMultipleValuesA.
Dominik Strasser751c4542002-07-20 20:02:55 +0000745 */
746DWORD WINAPI RegQueryMultipleValuesW(HKEY hkey, PVALENTW val_list, DWORD num_vals,
747 LPWSTR lpValueBuf, LPDWORD ldwTotsize)
748{
Hans Leidekker411fc5f2004-09-02 23:00:53 +0000749 unsigned int i;
Dominik Strasser751c4542002-07-20 20:02:55 +0000750 DWORD maxBytes = *ldwTotsize;
751 HRESULT status;
752 LPSTR bufptr = (LPSTR)lpValueBuf;
753 *ldwTotsize = 0;
754
Michael Stefaniuccbacde52002-10-25 19:17:33 +0000755 TRACE("(%p,%p,%ld,%p,%p=%ld)\n", hkey, val_list, num_vals, lpValueBuf, ldwTotsize, *ldwTotsize);
Dominik Strasser751c4542002-07-20 20:02:55 +0000756
757 for(i=0; i < num_vals; ++i)
758 {
759 val_list[i].ve_valuelen=0;
760 status = RegQueryValueExW(hkey, val_list[i].ve_valuename, NULL, NULL, NULL, &val_list[i].ve_valuelen);
761 if(status != ERROR_SUCCESS)
762 {
763 return status;
764 }
765
766 if(lpValueBuf != NULL && *ldwTotsize + val_list[i].ve_valuelen <= maxBytes)
767 {
768 status = RegQueryValueExW(hkey, val_list[i].ve_valuename, NULL, &val_list[i].ve_type,
Mike McCormack257c3372005-07-07 12:08:42 +0000769 (LPBYTE)bufptr, &val_list[i].ve_valuelen);
Dominik Strasser751c4542002-07-20 20:02:55 +0000770 if(status != ERROR_SUCCESS)
771 {
772 return status;
773 }
774
775 val_list[i].ve_valueptr = (DWORD_PTR)bufptr;
776
777 bufptr += val_list[i].ve_valuelen;
778 }
779
780 *ldwTotsize += val_list[i].ve_valuelen;
781 }
782 return lpValueBuf != NULL && *ldwTotsize <= maxBytes ? ERROR_SUCCESS : ERROR_MORE_DATA;
783}
784
785/******************************************************************************
James Hawkins6a358c42004-07-13 23:33:14 +0000786 * RegQueryInfoKeyA [ADVAPI32.@]
787 *
788 * Retrieves information about a registry key.
789 *
790 * PARAMS
791 * hKey [I] Handle to an open key.
792 * lpClass [O] Class string of the key.
793 * lpcClass [I/O] size of lpClass.
794 * lpReserved [I] Reserved; must be NULL.
795 * lpcSubKeys [O] Number of subkeys contained by the key.
796 * lpcMaxSubKeyLen [O] Size of the key's subkey with the longest name.
797 * lpcMaxClassLen [O] Size of the longest string specifying a subkey
798 * class in TCHARS.
799 * lpcValues [O] Number of values associated with the key.
800 * lpcMaxValueNameLen [O] Size of the key's longest value name in TCHARS.
801 * lpcMaxValueLen [O] Longest data component among the key's values
802 * lpcbSecurityDescriptor [O] Size of the key's security descriptor.
803 * lpftLastWriteTime [O] FILETIME strucutre that is the last write time.
804 *
805 * RETURNS
806 * Success: ERROR_SUCCESS
807 * Failure: nonzero error code from Winerror.h
Alexandre Julliard2fab2ef1999-11-23 19:41:34 +0000808 */
809DWORD WINAPI RegQueryInfoKeyA( HKEY hkey, LPSTR class, LPDWORD class_len, LPDWORD reserved,
810 LPDWORD subkeys, LPDWORD max_subkey, LPDWORD max_class,
811 LPDWORD values, LPDWORD max_value, LPDWORD max_data,
812 LPDWORD security, FILETIME *modif )
813{
Alexandre Julliard454355e2000-10-02 03:46:58 +0000814 NTSTATUS status;
815 char buffer[256], *buf_ptr = buffer;
816 KEY_FULL_INFORMATION *info = (KEY_FULL_INFORMATION *)buffer;
Alexandre Julliardc6615832001-02-14 21:45:52 +0000817 DWORD total_size, len;
Alexandre Julliard2fab2ef1999-11-23 19:41:34 +0000818
Michael Stefaniuccbacde52002-10-25 19:17:33 +0000819 TRACE( "(%p,%p,%ld,%p,%p,%p,%p,%p,%p,%p,%p)\n", hkey, class, class_len ? *class_len : 0,
Alexandre Julliard2fab2ef1999-11-23 19:41:34 +0000820 reserved, subkeys, max_subkey, values, max_value, max_data, security, modif );
821
Michael Cardenas7dbce652002-03-21 01:24:52 +0000822 if (class && !class_len && is_version_nt()) return ERROR_INVALID_PARAMETER;
Alexandre Julliardf2ef2c22002-09-13 21:42:28 +0000823 if (!(hkey = get_special_root_hkey( hkey ))) return ERROR_INVALID_HANDLE;
Alexandre Julliard2fab2ef1999-11-23 19:41:34 +0000824
Alexandre Julliard454355e2000-10-02 03:46:58 +0000825 status = NtQueryKey( hkey, KeyFullInformation, buffer, sizeof(buffer), &total_size );
Alexandre Julliardc6615832001-02-14 21:45:52 +0000826 if (status && status != STATUS_BUFFER_OVERFLOW) goto done;
Alexandre Julliard2fab2ef1999-11-23 19:41:34 +0000827
Alexandre Julliard454355e2000-10-02 03:46:58 +0000828 if (class || class_len)
Alexandre Julliard2fab2ef1999-11-23 19:41:34 +0000829 {
Alexandre Julliard454355e2000-10-02 03:46:58 +0000830 /* retry with a dynamically allocated buffer */
831 while (status == STATUS_BUFFER_OVERFLOW)
Alexandre Julliard2fab2ef1999-11-23 19:41:34 +0000832 {
Alexandre Julliard454355e2000-10-02 03:46:58 +0000833 if (buf_ptr != buffer) HeapFree( GetProcessHeap(), 0, buf_ptr );
834 if (!(buf_ptr = HeapAlloc( GetProcessHeap(), 0, total_size )))
835 return ERROR_NOT_ENOUGH_MEMORY;
836 info = (KEY_FULL_INFORMATION *)buf_ptr;
837 status = NtQueryKey( hkey, KeyFullInformation, buf_ptr, total_size, &total_size );
Alexandre Julliard2fab2ef1999-11-23 19:41:34 +0000838 }
Alexandre Julliard454355e2000-10-02 03:46:58 +0000839
Alexandre Julliardc6615832001-02-14 21:45:52 +0000840 if (status) goto done;
841
Alexandre Julliard60fd03d2001-12-05 22:18:48 +0000842 RtlUnicodeToMultiByteSize( &len, (WCHAR *)(buf_ptr + info->ClassOffset), info->ClassLength);
Alexandre Julliardc6615832001-02-14 21:45:52 +0000843 if (class_len)
Alexandre Julliard454355e2000-10-02 03:46:58 +0000844 {
Alexandre Julliardc6615832001-02-14 21:45:52 +0000845 if (len + 1 > *class_len) status = STATUS_BUFFER_OVERFLOW;
846 *class_len = len;
847 }
848 if (class && !status)
849 {
Alexandre Julliard60fd03d2001-12-05 22:18:48 +0000850 RtlUnicodeToMultiByteN( class, len, NULL, (WCHAR *)(buf_ptr + info->ClassOffset),
851 info->ClassLength );
Alexandre Julliardc6615832001-02-14 21:45:52 +0000852 class[len] = 0;
Alexandre Julliard454355e2000-10-02 03:46:58 +0000853 }
Alexandre Julliard2fab2ef1999-11-23 19:41:34 +0000854 }
Alexandre Julliardc6615832001-02-14 21:45:52 +0000855 else status = STATUS_SUCCESS;
Alexandre Julliard454355e2000-10-02 03:46:58 +0000856
Alexandre Julliardc6615832001-02-14 21:45:52 +0000857 if (subkeys) *subkeys = info->SubKeys;
858 if (max_subkey) *max_subkey = info->MaxNameLen;
859 if (max_class) *max_class = info->MaxClassLen;
860 if (values) *values = info->Values;
861 if (max_value) *max_value = info->MaxValueNameLen;
862 if (max_data) *max_data = info->MaxValueDataLen;
Dmitry Timoshkov6b6596a2001-11-23 18:44:43 +0000863 if (modif) *modif = *(FILETIME *)&info->LastWriteTime;
Alexandre Julliard454355e2000-10-02 03:46:58 +0000864
Alexandre Julliardc6615832001-02-14 21:45:52 +0000865 done:
Alexandre Julliard454355e2000-10-02 03:46:58 +0000866 if (buf_ptr != buffer) HeapFree( GetProcessHeap(), 0, buf_ptr );
867 return RtlNtStatusToDosError( status );
Alexandre Julliard2fab2ef1999-11-23 19:41:34 +0000868}
869
870
871/******************************************************************************
James Hawkins6a358c42004-07-13 23:33:14 +0000872 * RegCloseKey [ADVAPI32.@]
Alexandre Julliard2fab2ef1999-11-23 19:41:34 +0000873 *
Jon Griffiths50ce0842004-04-23 21:32:34 +0000874 * Close an open registry key.
Alexandre Julliard2fab2ef1999-11-23 19:41:34 +0000875 *
876 * PARAMS
James Hawkins6a358c42004-07-13 23:33:14 +0000877 * hkey [I] Handle of key to close
Alexandre Julliard2fab2ef1999-11-23 19:41:34 +0000878 *
879 * RETURNS
James Hawkins6a358c42004-07-13 23:33:14 +0000880 * Success: ERROR_SUCCESS
881 * Failure: Error code
Alexandre Julliard2fab2ef1999-11-23 19:41:34 +0000882 */
883DWORD WINAPI RegCloseKey( HKEY hkey )
884{
James Hawkinse8d1e2f2005-02-25 16:52:10 +0000885 if (!hkey) return ERROR_INVALID_HANDLE;
James Hawkinsd5e2b7c2005-02-21 20:37:26 +0000886 if (hkey >= (HKEY)0x80000000) return ERROR_SUCCESS;
Alexandre Julliardbcf393a2000-10-01 01:44:50 +0000887 return RtlNtStatusToDosError( NtClose( hkey ) );
Alexandre Julliard2fab2ef1999-11-23 19:41:34 +0000888}
889
890
891/******************************************************************************
James Hawkins6a358c42004-07-13 23:33:14 +0000892 * RegDeleteKeyW [ADVAPI32.@]
Alexandre Julliard2fab2ef1999-11-23 19:41:34 +0000893 *
Jon Griffiths50ce0842004-04-23 21:32:34 +0000894 * See RegDeleteKeyA.
Alexandre Julliard2fab2ef1999-11-23 19:41:34 +0000895 */
896DWORD WINAPI RegDeleteKeyW( HKEY hkey, LPCWSTR name )
897{
898 DWORD ret;
Alexandre Julliardbcf393a2000-10-01 01:44:50 +0000899 HKEY tmp;
Alexandre Julliard2fab2ef1999-11-23 19:41:34 +0000900
James Hawkinsa9d5de82005-04-16 10:49:10 +0000901 if (!name) return ERROR_INVALID_PARAMETER;
902
Alexandre Julliardf2ef2c22002-09-13 21:42:28 +0000903 if (!(hkey = get_special_root_hkey( hkey ))) return ERROR_INVALID_HANDLE;
904
Robert Shearman45d47c42005-05-05 16:47:33 +0000905 if (!(ret = RegOpenKeyExW( hkey, name, 0, DELETE, &tmp )))
Mike McCormackda007422002-06-14 23:35:37 +0000906 {
Alexandre Julliardbcf393a2000-10-01 01:44:50 +0000907 ret = RtlNtStatusToDosError( NtDeleteKey( tmp ) );
908 RegCloseKey( tmp );
909 }
Mike McCormackda007422002-06-14 23:35:37 +0000910 TRACE("%s ret=%08lx\n", debugstr_w(name), ret);
Alexandre Julliardbcf393a2000-10-01 01:44:50 +0000911 return ret;
Alexandre Julliard2fab2ef1999-11-23 19:41:34 +0000912}
913
914
915/******************************************************************************
James Hawkins6a358c42004-07-13 23:33:14 +0000916 * RegDeleteKeyA [ADVAPI32.@]
Jon Griffiths50ce0842004-04-23 21:32:34 +0000917 *
918 * Delete a registry key.
919 *
920 * PARAMS
James Hawkins6a358c42004-07-13 23:33:14 +0000921 * hkey [I] Handle to parent key containing the key to delete
922 * name [I] Name of the key user hkey to delete
Jon Griffiths50ce0842004-04-23 21:32:34 +0000923 *
Robert Shearman45d47c42005-05-05 16:47:33 +0000924 * NOTES
925 *
926 * MSDN is wrong when it says that hkey must be opened with the DELETE access
927 * right. In reality, it opens a new handle with DELETE access.
928 *
Jon Griffiths50ce0842004-04-23 21:32:34 +0000929 * RETURNS
James Hawkins6a358c42004-07-13 23:33:14 +0000930 * Success: ERROR_SUCCESS
931 * Failure: Error code
Alexandre Julliard2fab2ef1999-11-23 19:41:34 +0000932 */
933DWORD WINAPI RegDeleteKeyA( HKEY hkey, LPCSTR name )
934{
935 DWORD ret;
Alexandre Julliardbcf393a2000-10-01 01:44:50 +0000936 HKEY tmp;
Alexandre Julliard2fab2ef1999-11-23 19:41:34 +0000937
James Hawkinsa9d5de82005-04-16 10:49:10 +0000938 if (!name) return ERROR_INVALID_PARAMETER;
939
Alexandre Julliardf2ef2c22002-09-13 21:42:28 +0000940 if (!(hkey = get_special_root_hkey( hkey ))) return ERROR_INVALID_HANDLE;
941
Robert Shearman45d47c42005-05-05 16:47:33 +0000942 if (!(ret = RegOpenKeyExA( hkey, name, 0, DELETE, &tmp )))
Mike McCormackda007422002-06-14 23:35:37 +0000943 {
944 if (!is_version_nt()) /* win95 does recursive key deletes */
945 {
946 CHAR name[MAX_PATH];
947
Francois Gouget95918362003-06-18 19:45:22 +0000948 while(!RegEnumKeyA(tmp, 0, name, sizeof(name)))
Mike McCormackda007422002-06-14 23:35:37 +0000949 {
950 if(RegDeleteKeyA(tmp, name)) /* recurse */
951 break;
952 }
953 }
Alexandre Julliardbcf393a2000-10-01 01:44:50 +0000954 ret = RtlNtStatusToDosError( NtDeleteKey( tmp ) );
955 RegCloseKey( tmp );
956 }
Mike McCormackda007422002-06-14 23:35:37 +0000957 TRACE("%s ret=%08lx\n", debugstr_a(name), ret);
Alexandre Julliardbcf393a2000-10-01 01:44:50 +0000958 return ret;
Alexandre Julliard2fab2ef1999-11-23 19:41:34 +0000959}
960
961
962
963/******************************************************************************
James Hawkins6a358c42004-07-13 23:33:14 +0000964 * RegSetValueExW [ADVAPI32.@]
Alexandre Julliard2fab2ef1999-11-23 19:41:34 +0000965 *
Jon Griffiths50ce0842004-04-23 21:32:34 +0000966 * Set the data and contents of a registry value.
Alexandre Julliard2fab2ef1999-11-23 19:41:34 +0000967 *
968 * PARAMS
James Hawkins6a358c42004-07-13 23:33:14 +0000969 * hkey [I] Handle of key to set value for
970 * name [I] Name of value to set
971 * reserved [I] Reserved, must be zero
972 * type [I] Type of the value being set
973 * data [I] The new contents of the value to set
974 * count [I] Size of data
Alexandre Julliard2fab2ef1999-11-23 19:41:34 +0000975 *
976 * RETURNS
James Hawkins6a358c42004-07-13 23:33:14 +0000977 * Success: ERROR_SUCCESS
978 * Failure: Error code
Alexandre Julliard2fab2ef1999-11-23 19:41:34 +0000979 */
980DWORD WINAPI RegSetValueExW( HKEY hkey, LPCWSTR name, DWORD reserved,
981 DWORD type, CONST BYTE *data, DWORD count )
982{
Alexandre Julliardbcf393a2000-10-01 01:44:50 +0000983 UNICODE_STRING nameW;
Alexandre Julliard2fab2ef1999-11-23 19:41:34 +0000984
Alexandre Julliardbba76fc2004-07-24 02:32:50 +0000985 /* no need for version check, not implemented on win9x anyway */
986 if (count && is_string(type))
Alexandre Julliard2fab2ef1999-11-23 19:41:34 +0000987 {
988 LPCWSTR str = (LPCWSTR)data;
989 /* if user forgot to count terminating null, add it (yes NT does this) */
990 if (str[count / sizeof(WCHAR) - 1] && !str[count / sizeof(WCHAR)])
991 count += sizeof(WCHAR);
992 }
Alexandre Julliardf2ef2c22002-09-13 21:42:28 +0000993 if (!(hkey = get_special_root_hkey( hkey ))) return ERROR_INVALID_HANDLE;
Alexandre Julliarda01004d2000-05-14 22:57:57 +0000994
Alexandre Julliardbcf393a2000-10-01 01:44:50 +0000995 RtlInitUnicodeString( &nameW, name );
996 return RtlNtStatusToDosError( NtSetValueKey( hkey, &nameW, 0, type, data, count ) );
Alexandre Julliard2fab2ef1999-11-23 19:41:34 +0000997}
998
999
1000/******************************************************************************
James Hawkins6a358c42004-07-13 23:33:14 +00001001 * RegSetValueExA [ADVAPI32.@]
1002 *
Markus Amslerd45811c2005-11-04 11:43:27 +00001003 * See RegSetValueExW.
Alexandre Julliardbba76fc2004-07-24 02:32:50 +00001004 *
1005 * NOTES
1006 * win95 does not care about count for REG_SZ and finds out the len by itself (js)
1007 * NT does definitely care (aj)
Alexandre Julliard2fab2ef1999-11-23 19:41:34 +00001008 */
1009DWORD WINAPI RegSetValueExA( HKEY hkey, LPCSTR name, DWORD reserved, DWORD type,
Alexandre Julliardbcf393a2000-10-01 01:44:50 +00001010 CONST BYTE *data, DWORD count )
Alexandre Julliard2fab2ef1999-11-23 19:41:34 +00001011{
Alexandre Julliardbcf393a2000-10-01 01:44:50 +00001012 ANSI_STRING nameA;
1013 WCHAR *dataW = NULL;
1014 NTSTATUS status;
Alexandre Julliard2fab2ef1999-11-23 19:41:34 +00001015
Michael Cardenas7dbce652002-03-21 01:24:52 +00001016 if (!is_version_nt()) /* win95 */
Alexandre Julliard918da642001-04-10 21:30:24 +00001017 {
Alexandre Julliardbba76fc2004-07-24 02:32:50 +00001018 if (type == REG_SZ)
1019 {
1020 if (!data) return ERROR_INVALID_PARAMETER;
Mike McCormack280bcf62005-08-27 10:00:38 +00001021 count = strlen((const char *)data) + 1;
Alexandre Julliardbba76fc2004-07-24 02:32:50 +00001022 }
Alexandre Julliard918da642001-04-10 21:30:24 +00001023 }
1024 else if (count && is_string(type))
Alexandre Julliard2fab2ef1999-11-23 19:41:34 +00001025 {
1026 /* if user forgot to count terminating null, add it (yes NT does this) */
1027 if (data[count-1] && !data[count]) count++;
1028 }
Alexandre Julliardbcf393a2000-10-01 01:44:50 +00001029
Alexandre Julliardf2ef2c22002-09-13 21:42:28 +00001030 if (!(hkey = get_special_root_hkey( hkey ))) return ERROR_INVALID_HANDLE;
1031
Alexandre Julliarda01004d2000-05-14 22:57:57 +00001032 if (is_string( type )) /* need to convert to Unicode */
Alexandre Julliarda01004d2000-05-14 22:57:57 +00001033 {
Alexandre Julliard60fd03d2001-12-05 22:18:48 +00001034 DWORD lenW;
Mike McCormack280bcf62005-08-27 10:00:38 +00001035 RtlMultiByteToUnicodeSize( &lenW, (const char *)data, count );
Alexandre Julliard60fd03d2001-12-05 22:18:48 +00001036 if (!(dataW = HeapAlloc( GetProcessHeap(), 0, lenW ))) return ERROR_OUTOFMEMORY;
Mike McCormack280bcf62005-08-27 10:00:38 +00001037 RtlMultiByteToUnicodeN( dataW, lenW, NULL, (const char *)data, count );
Alexandre Julliard60fd03d2001-12-05 22:18:48 +00001038 count = lenW;
Alexandre Julliardbcf393a2000-10-01 01:44:50 +00001039 data = (BYTE *)dataW;
Alexandre Julliarda01004d2000-05-14 22:57:57 +00001040 }
Alexandre Julliardbcf393a2000-10-01 01:44:50 +00001041
1042 RtlInitAnsiString( &nameA, name );
Alexandre Julliardab5e9752001-03-23 19:12:01 +00001043 if (!(status = RtlAnsiStringToUnicodeString( &NtCurrentTeb()->StaticUnicodeString,
1044 &nameA, FALSE )))
Alexandre Julliardbcf393a2000-10-01 01:44:50 +00001045 {
Alexandre Julliardab5e9752001-03-23 19:12:01 +00001046 status = NtSetValueKey( hkey, &NtCurrentTeb()->StaticUnicodeString, 0, type, data, count );
Alexandre Julliardbcf393a2000-10-01 01:44:50 +00001047 }
Michael Stefaniuc5ad7d852004-12-23 17:06:43 +00001048 HeapFree( GetProcessHeap(), 0, dataW );
Alexandre Julliardbcf393a2000-10-01 01:44:50 +00001049 return RtlNtStatusToDosError( status );
Alexandre Julliard2fab2ef1999-11-23 19:41:34 +00001050}
1051
1052
1053/******************************************************************************
James Hawkins6a358c42004-07-13 23:33:14 +00001054 * RegSetValueW [ADVAPI32.@]
1055 *
1056 * Sets the data for the default or unnamed value of a reg key.
1057 *
1058 * PARAMS
1059 * hKey [I] Handle to an open key.
1060 * lpSubKey [I] Name of a subkey of hKey.
1061 * dwType [I] Type of information to store.
1062 * lpData [I] String that contains the data to set for the default value.
1063 * cbData [I] Size of lpData.
1064 *
1065 * RETURNS
1066 * Success: ERROR_SUCCESS
1067 * Failure: nonzero error code from Winerror.h
Alexandre Julliard2fab2ef1999-11-23 19:41:34 +00001068 */
1069DWORD WINAPI RegSetValueW( HKEY hkey, LPCWSTR name, DWORD type, LPCWSTR data, DWORD count )
1070{
1071 HKEY subkey = hkey;
1072 DWORD ret;
1073
Michael Stefaniuccbacde52002-10-25 19:17:33 +00001074 TRACE("(%p,%s,%ld,%s,%ld)\n", hkey, debugstr_w(name), type, debugstr_w(data), count );
Alexandre Julliard2fab2ef1999-11-23 19:41:34 +00001075
1076 if (type != REG_SZ) return ERROR_INVALID_PARAMETER;
1077
1078 if (name && name[0]) /* need to create the subkey */
1079 {
1080 if ((ret = RegCreateKeyW( hkey, name, &subkey )) != ERROR_SUCCESS) return ret;
1081 }
1082
Eric Pouech0a258962004-11-30 21:38:57 +00001083 ret = RegSetValueExW( subkey, NULL, 0, REG_SZ, (const BYTE*)data,
Alexandre Julliardc7e7df82000-08-14 14:41:19 +00001084 (strlenW( data ) + 1) * sizeof(WCHAR) );
Alexandre Julliard2fab2ef1999-11-23 19:41:34 +00001085 if (subkey != hkey) RegCloseKey( subkey );
1086 return ret;
1087}
1088
1089
1090/******************************************************************************
James Hawkins6a358c42004-07-13 23:33:14 +00001091 * RegSetValueA [ADVAPI32.@]
1092 *
Markus Amslerd45811c2005-11-04 11:43:27 +00001093 * See RegSetValueW.
Alexandre Julliard2fab2ef1999-11-23 19:41:34 +00001094 */
1095DWORD WINAPI RegSetValueA( HKEY hkey, LPCSTR name, DWORD type, LPCSTR data, DWORD count )
1096{
1097 HKEY subkey = hkey;
1098 DWORD ret;
1099
Michael Stefaniuccbacde52002-10-25 19:17:33 +00001100 TRACE("(%p,%s,%ld,%s,%ld)\n", hkey, debugstr_a(name), type, debugstr_a(data), count );
Alexandre Julliard2fab2ef1999-11-23 19:41:34 +00001101
1102 if (type != REG_SZ) return ERROR_INVALID_PARAMETER;
1103
1104 if (name && name[0]) /* need to create the subkey */
1105 {
1106 if ((ret = RegCreateKeyA( hkey, name, &subkey )) != ERROR_SUCCESS) return ret;
1107 }
Eric Pouech0a258962004-11-30 21:38:57 +00001108 ret = RegSetValueExA( subkey, NULL, 0, REG_SZ, (const BYTE*)data, strlen(data)+1 );
Alexandre Julliard2fab2ef1999-11-23 19:41:34 +00001109 if (subkey != hkey) RegCloseKey( subkey );
1110 return ret;
1111}
1112
1113
1114
1115/******************************************************************************
James Hawkins6a358c42004-07-13 23:33:14 +00001116 * RegQueryValueExW [ADVAPI32.@]
Alexandre Julliard2fab2ef1999-11-23 19:41:34 +00001117 *
Jon Griffiths50ce0842004-04-23 21:32:34 +00001118 * See RegQueryValueExA.
Alexandre Julliard2fab2ef1999-11-23 19:41:34 +00001119 */
1120DWORD WINAPI RegQueryValueExW( HKEY hkey, LPCWSTR name, LPDWORD reserved, LPDWORD type,
Alexandre Julliardbcf393a2000-10-01 01:44:50 +00001121 LPBYTE data, LPDWORD count )
Alexandre Julliard2fab2ef1999-11-23 19:41:34 +00001122{
Alexandre Julliardbcf393a2000-10-01 01:44:50 +00001123 NTSTATUS status;
1124 UNICODE_STRING name_str;
1125 DWORD total_size;
Alexandre Julliard454355e2000-10-02 03:46:58 +00001126 char buffer[256], *buf_ptr = buffer;
Alexandre Julliardbcf393a2000-10-01 01:44:50 +00001127 KEY_VALUE_PARTIAL_INFORMATION *info = (KEY_VALUE_PARTIAL_INFORMATION *)buffer;
Alexandre Julliarda0109322002-07-05 21:30:38 +00001128 static const int info_size = offsetof( KEY_VALUE_PARTIAL_INFORMATION, Data );
Alexandre Julliard2fab2ef1999-11-23 19:41:34 +00001129
Michael Stefaniuccbacde52002-10-25 19:17:33 +00001130 TRACE("(%p,%s,%p,%p,%p,%p=%ld)\n",
Francois Gouget8f63a712003-12-13 01:34:40 +00001131 hkey, debugstr_w(name), reserved, type, data, count,
1132 (count && data) ? *count : 0 );
Alexandre Julliard2fab2ef1999-11-23 19:41:34 +00001133
Eric Pouech2c655f51999-11-25 22:05:46 +00001134 if ((data && !count) || reserved) return ERROR_INVALID_PARAMETER;
Alexandre Julliardf2ef2c22002-09-13 21:42:28 +00001135 if (!(hkey = get_special_root_hkey( hkey ))) return ERROR_INVALID_HANDLE;
Alexandre Julliard2fab2ef1999-11-23 19:41:34 +00001136
Alexandre Julliardbcf393a2000-10-01 01:44:50 +00001137 RtlInitUnicodeString( &name_str, name );
1138
1139 if (data) total_size = min( sizeof(buffer), *count + info_size );
1140 else total_size = info_size;
1141
1142 status = NtQueryValueKey( hkey, &name_str, KeyValuePartialInformation,
1143 buffer, total_size, &total_size );
1144 if (status && status != STATUS_BUFFER_OVERFLOW) goto done;
Alexandre Julliarda01004d2000-05-14 22:57:57 +00001145
1146 if (data)
Alexandre Julliard2fab2ef1999-11-23 19:41:34 +00001147 {
Alexandre Julliardbcf393a2000-10-01 01:44:50 +00001148 /* retry with a dynamically allocated buffer */
1149 while (status == STATUS_BUFFER_OVERFLOW && total_size - info_size <= *count)
Alexandre Julliarda01004d2000-05-14 22:57:57 +00001150 {
Alexandre Julliardbcf393a2000-10-01 01:44:50 +00001151 if (buf_ptr != buffer) HeapFree( GetProcessHeap(), 0, buf_ptr );
1152 if (!(buf_ptr = HeapAlloc( GetProcessHeap(), 0, total_size )))
Alexandre Julliard454355e2000-10-02 03:46:58 +00001153 return ERROR_NOT_ENOUGH_MEMORY;
1154 info = (KEY_VALUE_PARTIAL_INFORMATION *)buf_ptr;
1155 status = NtQueryValueKey( hkey, &name_str, KeyValuePartialInformation,
1156 buf_ptr, total_size, &total_size );
Alexandre Julliardbcf393a2000-10-01 01:44:50 +00001157 }
1158
1159 if (!status)
1160 {
1161 memcpy( data, buf_ptr + info_size, total_size - info_size );
1162 /* if the type is REG_SZ and data is not 0-terminated
1163 * and there is enough space in the buffer NT appends a \0 */
1164 if (total_size - info_size <= *count-sizeof(WCHAR) && is_string(info->Type))
Alexandre Julliarda01004d2000-05-14 22:57:57 +00001165 {
Alexandre Julliardbcf393a2000-10-01 01:44:50 +00001166 WCHAR *ptr = (WCHAR *)(data + total_size - info_size);
1167 if (ptr > (WCHAR *)data && ptr[-1]) *ptr = 0;
Alexandre Julliarda01004d2000-05-14 22:57:57 +00001168 }
1169 }
Alexandre Julliard454355e2000-10-02 03:46:58 +00001170 else if (status != STATUS_BUFFER_OVERFLOW) goto done;
Alexandre Julliard2fab2ef1999-11-23 19:41:34 +00001171 }
Alexandre Julliardc6615832001-02-14 21:45:52 +00001172 else status = STATUS_SUCCESS;
Alexandre Julliardbcf393a2000-10-01 01:44:50 +00001173
1174 if (type) *type = info->Type;
1175 if (count) *count = total_size - info_size;
1176
1177 done:
Alexandre Julliard454355e2000-10-02 03:46:58 +00001178 if (buf_ptr != buffer) HeapFree( GetProcessHeap(), 0, buf_ptr );
Alexandre Julliardbcf393a2000-10-01 01:44:50 +00001179 return RtlNtStatusToDosError(status);
Alexandre Julliard2fab2ef1999-11-23 19:41:34 +00001180}
1181
1182
1183/******************************************************************************
James Hawkins6a358c42004-07-13 23:33:14 +00001184 * RegQueryValueExA [ADVAPI32.@]
Alexandre Julliard2fab2ef1999-11-23 19:41:34 +00001185 *
Jon Griffiths50ce0842004-04-23 21:32:34 +00001186 * Get the type and contents of a specified value under with a key.
1187 *
1188 * PARAMS
James Hawkins6a358c42004-07-13 23:33:14 +00001189 * hkey [I] Handle of the key to query
1190 * name [I] Name of value under hkey to query
1191 * reserved [I] Reserved - must be NULL
1192 * type [O] Destination for the value type, or NULL if not required
1193 * data [O] Destination for the values contents, or NULL if not required
1194 * count [I/O] Size of data, updated with the number of bytes returned
Jon Griffiths50ce0842004-04-23 21:32:34 +00001195 *
1196 * RETURNS
1197 * Success: ERROR_SUCCESS. *count is updated with the number of bytes copied to data.
1198 * Failure: ERROR_INVALID_HANDLE, if hkey is invalid.
1199 * ERROR_INVALID_PARAMETER, if any other parameter is invalid.
1200 * ERROR_MORE_DATA, if on input *count is too small to hold the contents.
1201 *
1202 * NOTES
1203 * MSDN states that if data is too small it is partially filled. In reality
1204 * it remains untouched.
Alexandre Julliard2fab2ef1999-11-23 19:41:34 +00001205 */
1206DWORD WINAPI RegQueryValueExA( HKEY hkey, LPCSTR name, LPDWORD reserved, LPDWORD type,
Alexandre Julliardbcf393a2000-10-01 01:44:50 +00001207 LPBYTE data, LPDWORD count )
Alexandre Julliard2fab2ef1999-11-23 19:41:34 +00001208{
Alexandre Julliardbcf393a2000-10-01 01:44:50 +00001209 NTSTATUS status;
1210 ANSI_STRING nameA;
Alexandre Julliardbcf393a2000-10-01 01:44:50 +00001211 DWORD total_size;
Alexandre Julliard454355e2000-10-02 03:46:58 +00001212 char buffer[256], *buf_ptr = buffer;
Alexandre Julliardbcf393a2000-10-01 01:44:50 +00001213 KEY_VALUE_PARTIAL_INFORMATION *info = (KEY_VALUE_PARTIAL_INFORMATION *)buffer;
Alexandre Julliarda0109322002-07-05 21:30:38 +00001214 static const int info_size = offsetof( KEY_VALUE_PARTIAL_INFORMATION, Data );
Alexandre Julliard2fab2ef1999-11-23 19:41:34 +00001215
Michael Stefaniuccbacde52002-10-25 19:17:33 +00001216 TRACE("(%p,%s,%p,%p,%p,%p=%ld)\n",
Alexandre Julliard2fab2ef1999-11-23 19:41:34 +00001217 hkey, debugstr_a(name), reserved, type, data, count, count ? *count : 0 );
1218
Eric Pouech2c655f51999-11-25 22:05:46 +00001219 if ((data && !count) || reserved) return ERROR_INVALID_PARAMETER;
Alexandre Julliardf2ef2c22002-09-13 21:42:28 +00001220 if (!(hkey = get_special_root_hkey( hkey ))) return ERROR_INVALID_HANDLE;
Alexandre Julliard2fab2ef1999-11-23 19:41:34 +00001221
Alexandre Julliardbcf393a2000-10-01 01:44:50 +00001222 RtlInitAnsiString( &nameA, name );
Alexandre Julliardab5e9752001-03-23 19:12:01 +00001223 if ((status = RtlAnsiStringToUnicodeString( &NtCurrentTeb()->StaticUnicodeString,
1224 &nameA, FALSE )))
Alexandre Julliard454355e2000-10-02 03:46:58 +00001225 return RtlNtStatusToDosError(status);
Alexandre Julliarda01004d2000-05-14 22:57:57 +00001226
Alexandre Julliardab5e9752001-03-23 19:12:01 +00001227 status = NtQueryValueKey( hkey, &NtCurrentTeb()->StaticUnicodeString,
1228 KeyValuePartialInformation, buffer, sizeof(buffer), &total_size );
Alexandre Julliardbcf393a2000-10-01 01:44:50 +00001229 if (status && status != STATUS_BUFFER_OVERFLOW) goto done;
Alexandre Julliarda01004d2000-05-14 22:57:57 +00001230
Alexandre Julliardbcf393a2000-10-01 01:44:50 +00001231 /* we need to fetch the contents for a string type even if not requested,
1232 * because we need to compute the length of the ASCII string. */
1233 if (data || is_string(info->Type))
Alexandre Julliard2fab2ef1999-11-23 19:41:34 +00001234 {
Alexandre Julliardbcf393a2000-10-01 01:44:50 +00001235 /* retry with a dynamically allocated buffer */
1236 while (status == STATUS_BUFFER_OVERFLOW)
Alexandre Julliarda01004d2000-05-14 22:57:57 +00001237 {
Alexandre Julliardbcf393a2000-10-01 01:44:50 +00001238 if (buf_ptr != buffer) HeapFree( GetProcessHeap(), 0, buf_ptr );
1239 if (!(buf_ptr = HeapAlloc( GetProcessHeap(), 0, total_size )))
Alexandre Julliard454355e2000-10-02 03:46:58 +00001240 {
Alexandre Julliardbcf393a2000-10-01 01:44:50 +00001241 status = STATUS_NO_MEMORY;
Alexandre Julliard454355e2000-10-02 03:46:58 +00001242 goto done;
1243 }
1244 info = (KEY_VALUE_PARTIAL_INFORMATION *)buf_ptr;
Alexandre Julliardab5e9752001-03-23 19:12:01 +00001245 status = NtQueryValueKey( hkey, &NtCurrentTeb()->StaticUnicodeString,
1246 KeyValuePartialInformation, buf_ptr, total_size, &total_size );
Alexandre Julliardbcf393a2000-10-01 01:44:50 +00001247 }
1248
Alexandre Julliardc6615832001-02-14 21:45:52 +00001249 if (status) goto done;
1250
1251 if (is_string(info->Type))
Alexandre Julliardbcf393a2000-10-01 01:44:50 +00001252 {
Alexandre Julliard60fd03d2001-12-05 22:18:48 +00001253 DWORD len;
1254
1255 RtlUnicodeToMultiByteSize( &len, (WCHAR *)(buf_ptr + info_size),
1256 total_size - info_size );
Alexandre Julliardc6615832001-02-14 21:45:52 +00001257 if (data && len)
Alexandre Julliard57f05e12000-10-15 00:40:25 +00001258 {
Alexandre Julliardc6615832001-02-14 21:45:52 +00001259 if (len > *count) status = STATUS_BUFFER_OVERFLOW;
1260 else
1261 {
Mike McCormack280bcf62005-08-27 10:00:38 +00001262 RtlUnicodeToMultiByteN( (char*)data, len, NULL, (WCHAR *)(buf_ptr + info_size),
Alexandre Julliard60fd03d2001-12-05 22:18:48 +00001263 total_size - info_size );
Alexandre Julliardc6615832001-02-14 21:45:52 +00001264 /* if the type is REG_SZ and data is not 0-terminated
1265 * and there is enough space in the buffer NT appends a \0 */
1266 if (len < *count && data[len-1]) data[len] = 0;
1267 }
Alexandre Julliard57f05e12000-10-15 00:40:25 +00001268 }
Alexandre Julliardc6615832001-02-14 21:45:52 +00001269 total_size = len + info_size;
Alexandre Julliarda01004d2000-05-14 22:57:57 +00001270 }
Alexandre Julliardc6615832001-02-14 21:45:52 +00001271 else if (data)
1272 {
1273 if (total_size - info_size > *count) status = STATUS_BUFFER_OVERFLOW;
1274 else memcpy( data, buf_ptr + info_size, total_size - info_size );
1275 }
Alexandre Julliard2fab2ef1999-11-23 19:41:34 +00001276 }
Alexandre Julliardc6615832001-02-14 21:45:52 +00001277 else status = STATUS_SUCCESS;
Alexandre Julliarda01004d2000-05-14 22:57:57 +00001278
Alexandre Julliardbcf393a2000-10-01 01:44:50 +00001279 if (type) *type = info->Type;
1280 if (count) *count = total_size - info_size;
Alexandre Julliardbcf393a2000-10-01 01:44:50 +00001281
1282 done:
Alexandre Julliard454355e2000-10-02 03:46:58 +00001283 if (buf_ptr != buffer) HeapFree( GetProcessHeap(), 0, buf_ptr );
Alexandre Julliardbcf393a2000-10-01 01:44:50 +00001284 return RtlNtStatusToDosError(status);
Alexandre Julliard2fab2ef1999-11-23 19:41:34 +00001285}
1286
1287
1288/******************************************************************************
James Hawkins6a358c42004-07-13 23:33:14 +00001289 * RegQueryValueW [ADVAPI32.@]
1290 *
1291 * Retrieves the data associated with the default or unnamed value of a key.
1292 *
1293 * PARAMS
Alexandre Julliardbbde53f2004-10-19 21:14:09 +00001294 * hkey [I] Handle to an open key.
1295 * name [I] Name of the subkey of hKey.
1296 * data [O] Receives the string associated with the default value
James Hawkins6a358c42004-07-13 23:33:14 +00001297 * of the key.
Alexandre Julliardbbde53f2004-10-19 21:14:09 +00001298 * count [I/O] Size of lpValue in bytes.
James Hawkins6a358c42004-07-13 23:33:14 +00001299 *
1300 * RETURNS
1301 * Success: ERROR_SUCCESS
1302 * Failure: nonzero error code from Winerror.h
Alexandre Julliard2fab2ef1999-11-23 19:41:34 +00001303 */
1304DWORD WINAPI RegQueryValueW( HKEY hkey, LPCWSTR name, LPWSTR data, LPLONG count )
1305{
1306 DWORD ret;
1307 HKEY subkey = hkey;
1308
Michael Stefaniuccbacde52002-10-25 19:17:33 +00001309 TRACE("(%p,%s,%p,%ld)\n", hkey, debugstr_w(name), data, count ? *count : 0 );
Alexandre Julliard2fab2ef1999-11-23 19:41:34 +00001310
1311 if (name && name[0])
1312 {
1313 if ((ret = RegOpenKeyW( hkey, name, &subkey )) != ERROR_SUCCESS) return ret;
1314 }
Mike McCormack280bcf62005-08-27 10:00:38 +00001315 ret = RegQueryValueExW( subkey, NULL, NULL, NULL, (LPBYTE)data, (LPDWORD)count );
Alexandre Julliard2fab2ef1999-11-23 19:41:34 +00001316 if (subkey != hkey) RegCloseKey( subkey );
1317 if (ret == ERROR_FILE_NOT_FOUND)
1318 {
1319 /* return empty string if default value not found */
1320 if (data) *data = 0;
Alexandre Julliardbbde53f2004-10-19 21:14:09 +00001321 if (count) *count = sizeof(WCHAR);
Alexandre Julliard2fab2ef1999-11-23 19:41:34 +00001322 ret = ERROR_SUCCESS;
1323 }
1324 return ret;
1325}
1326
1327
1328/******************************************************************************
James Hawkins6a358c42004-07-13 23:33:14 +00001329 * RegQueryValueA [ADVAPI32.@]
1330 *
Markus Amslerd45811c2005-11-04 11:43:27 +00001331 * See RegQueryValueW.
Alexandre Julliard2fab2ef1999-11-23 19:41:34 +00001332 */
1333DWORD WINAPI RegQueryValueA( HKEY hkey, LPCSTR name, LPSTR data, LPLONG count )
1334{
1335 DWORD ret;
1336 HKEY subkey = hkey;
1337
Michael Stefaniuccbacde52002-10-25 19:17:33 +00001338 TRACE("(%p,%s,%p,%ld)\n", hkey, debugstr_a(name), data, count ? *count : 0 );
Alexandre Julliard2fab2ef1999-11-23 19:41:34 +00001339
1340 if (name && name[0])
1341 {
1342 if ((ret = RegOpenKeyA( hkey, name, &subkey )) != ERROR_SUCCESS) return ret;
1343 }
Mike McCormack280bcf62005-08-27 10:00:38 +00001344 ret = RegQueryValueExA( subkey, NULL, NULL, NULL, (LPBYTE)data, (LPDWORD)count );
Alexandre Julliard2fab2ef1999-11-23 19:41:34 +00001345 if (subkey != hkey) RegCloseKey( subkey );
1346 if (ret == ERROR_FILE_NOT_FOUND)
1347 {
1348 /* return empty string if default value not found */
1349 if (data) *data = 0;
1350 if (count) *count = 1;
1351 ret = ERROR_SUCCESS;
1352 }
1353 return ret;
1354}
1355
1356
1357/******************************************************************************
Felix Nawothnig48533ae2005-07-18 15:10:22 +00001358 * ADVAPI_ApplyRestrictions [internal]
1359 *
1360 * Helper function for RegGetValueA/W.
1361 */
1362VOID ADVAPI_ApplyRestrictions( DWORD dwFlags, DWORD dwType, DWORD cbData,
1363 PLONG ret )
1364{
1365 /* Check if the type is restricted by the passed flags */
1366 if (*ret == ERROR_SUCCESS || *ret == ERROR_MORE_DATA)
1367 {
1368 DWORD dwMask = 0;
1369
1370 switch (dwType)
1371 {
1372 case REG_NONE: dwMask = RRF_RT_REG_NONE; break;
1373 case REG_SZ: dwMask = RRF_RT_REG_SZ; break;
1374 case REG_EXPAND_SZ: dwMask = RRF_RT_REG_EXPAND_SZ; break;
1375 case REG_MULTI_SZ: dwMask = RRF_RT_REG_MULTI_SZ; break;
1376 case REG_BINARY: dwMask = RRF_RT_REG_BINARY; break;
1377 case REG_DWORD: dwMask = RRF_RT_REG_DWORD; break;
1378 case REG_QWORD: dwMask = RRF_RT_REG_QWORD; break;
1379 }
1380
1381 if (dwFlags & dwMask)
1382 {
1383 /* Type is not restricted, check for size mismatch */
1384 if (dwType == REG_BINARY)
1385 {
1386 DWORD cbExpect = 0;
1387
1388 if ((dwFlags & RRF_RT_DWORD) == RRF_RT_DWORD)
1389 cbExpect = 4;
1390 else if ((dwFlags & RRF_RT_DWORD) == RRF_RT_QWORD)
1391 cbExpect = 8;
1392
1393 if (cbExpect && cbData != cbExpect)
1394 *ret = ERROR_DATATYPE_MISMATCH;
1395 }
1396 }
1397 else *ret = ERROR_UNSUPPORTED_TYPE;
1398 }
1399}
1400
1401
1402/******************************************************************************
1403 * RegGetValueW [ADVAPI32.@]
1404 *
1405 * Retrieves the type and data for a value name associated with a key
1406 * optionally expanding it's content and restricting it's type.
1407 *
1408 * PARAMS
1409 * hKey [I] Handle to an open key.
1410 * pszSubKey [I] Name of the subkey of hKey.
1411 * pszValue [I] Name of value under hKey/szSubKey to query.
1412 * dwFlags [I] Flags restricting the value type to retrieve.
1413 * pdwType [O] Destination for the values type, may be NULL.
1414 * pvData [O] Destination for the values content, may be NULL.
1415 * pcbData [I/O] Size of pvData, updated with the size required to
1416 * retrieve the whole content.
1417 *
1418 * RETURNS
1419 * Success: ERROR_SUCCESS
1420 * Failure: nonzero error code from Winerror.h
1421 *
1422 * NOTES
1423 * - Unless RRF_NOEXPAND is specified REG_EXPAND_SZ is automatically expanded
1424 * and REG_SZ is retrieved instead.
1425 * - Restrictions are applied after expanding, using RRF_RT_REG_EXPAND_SZ
1426 * without RRF_NOEXPAND is thus not allowed.
1427 */
1428LONG WINAPI RegGetValueW( HKEY hKey, LPCWSTR pszSubKey, LPCWSTR pszValue,
1429 DWORD dwFlags, LPDWORD pdwType, PVOID pvData,
1430 LPDWORD pcbData )
1431{
1432 DWORD dwType, cbData = pcbData ? *pcbData : 0;
1433 PVOID pvBuf = NULL;
1434 LONG ret;
1435
1436 TRACE("(%p,%s,%s,%ld,%p,%p,%p=%ld)\n",
1437 hKey, debugstr_w(pszSubKey), debugstr_w(pszValue), dwFlags, pdwType,
1438 pvData, pcbData, cbData);
1439
1440 if ((dwFlags & RRF_RT_REG_EXPAND_SZ) && !(dwFlags & RRF_NOEXPAND))
1441 return ERROR_INVALID_PARAMETER;
1442
1443 if (pszSubKey && pszSubKey[0])
1444 {
1445 ret = RegOpenKeyExW(hKey, pszSubKey, 0, KEY_QUERY_VALUE, &hKey);
1446 if (ret != ERROR_SUCCESS) return ret;
1447 }
1448
1449 ret = RegQueryValueExW(hKey, pszValue, NULL, &dwType, pvData, &cbData);
1450
1451 /* If we are going to expand we need to read in the whole the value even
1452 * if the passed buffer was too small as the expanded string might be
1453 * smaller than the unexpanded one and could fit into cbData bytes. */
1454 if ((ret == ERROR_SUCCESS || ret == ERROR_MORE_DATA) &&
1455 (dwType == REG_EXPAND_SZ && !(dwFlags & RRF_NOEXPAND)))
1456 {
1457 do {
1458 if (pvBuf) HeapFree(GetProcessHeap(), 0, pvBuf);
1459
1460 pvBuf = HeapAlloc(GetProcessHeap(), 0, cbData);
1461 if (!pvBuf)
1462 {
1463 ret = ERROR_NOT_ENOUGH_MEMORY;
1464 break;
1465 }
1466
1467 if (ret == ERROR_MORE_DATA)
1468 ret = RegQueryValueExW(hKey, pszValue, NULL,
1469 &dwType, pvBuf, &cbData);
1470 else
1471 {
1472 /* Even if cbData was large enough we have to copy the
1473 * string since ExpandEnvironmentStrings can't handle
1474 * overlapping buffers. */
1475 CopyMemory(pvBuf, pvData, cbData);
1476 }
1477
1478 /* Both the type or the value itself could have been modified in
1479 * between so we have to keep retrying until the buffer is large
1480 * enough or we no longer have to expand the value. */
1481 } while (dwType == REG_EXPAND_SZ && ret == ERROR_MORE_DATA);
1482
1483 if (ret == ERROR_SUCCESS)
1484 {
1485 if (dwType == REG_EXPAND_SZ)
1486 {
1487 cbData = ExpandEnvironmentStringsW(pvBuf, pvData,
1488 pcbData ? *pcbData : 0);
1489 dwType = REG_SZ;
1490 if(pcbData && cbData > *pcbData)
1491 ret = ERROR_MORE_DATA;
1492 }
1493 else if (pcbData)
1494 CopyMemory(pvData, pvBuf, *pcbData);
1495 }
1496
1497 if (pvBuf) HeapFree(GetProcessHeap(), 0, pvBuf);
1498 }
1499
1500 if (pszSubKey && pszSubKey[0])
1501 RegCloseKey(hKey);
1502
1503 ADVAPI_ApplyRestrictions(dwFlags, dwType, cbData, &ret);
1504
1505 if (pcbData && ret != ERROR_SUCCESS && (dwFlags & RRF_ZEROONFAILURE))
1506 ZeroMemory(pvData, *pcbData);
1507
1508 if (pdwType) *pdwType = dwType;
1509 if (pcbData) *pcbData = cbData;
1510
1511 return ret;
1512}
1513
1514
1515/******************************************************************************
1516 * RegGetValueA [ADVAPI32.@]
1517 *
1518 * See RegGetValueW.
1519 */
1520LONG WINAPI RegGetValueA( HKEY hKey, LPCSTR pszSubKey, LPCSTR pszValue,
1521 DWORD dwFlags, LPDWORD pdwType, PVOID pvData,
1522 LPDWORD pcbData )
1523{
1524 DWORD dwType, cbData = pcbData ? *pcbData : 0;
1525 PVOID pvBuf = NULL;
1526 LONG ret;
1527
1528 TRACE("(%p,%s,%s,%ld,%p,%p,%p=%ld)\n",
1529 hKey, pszSubKey, pszValue, dwFlags, pdwType, pvData, pcbData,
1530 cbData);
1531
1532 if ((dwFlags & RRF_RT_REG_EXPAND_SZ) && !(dwFlags & RRF_NOEXPAND))
1533 return ERROR_INVALID_PARAMETER;
1534
1535 if (pszSubKey && pszSubKey[0])
1536 {
1537 ret = RegOpenKeyExA(hKey, pszSubKey, 0, KEY_QUERY_VALUE, &hKey);
1538 if (ret != ERROR_SUCCESS) return ret;
1539 }
1540
1541 ret = RegQueryValueExA(hKey, pszValue, NULL, &dwType, pvData, &cbData);
1542
1543 /* If we are going to expand we need to read in the whole the value even
1544 * if the passed buffer was too small as the expanded string might be
1545 * smaller than the unexpanded one and could fit into cbData bytes. */
1546 if ((ret == ERROR_SUCCESS || ret == ERROR_MORE_DATA) &&
1547 (dwType == REG_EXPAND_SZ && !(dwFlags & RRF_NOEXPAND)))
1548 {
1549 do {
1550 if (pvBuf) HeapFree(GetProcessHeap(), 0, pvBuf);
1551
1552 pvBuf = HeapAlloc(GetProcessHeap(), 0, cbData);
1553 if (!pvBuf)
1554 {
1555 ret = ERROR_NOT_ENOUGH_MEMORY;
1556 break;
1557 }
1558
1559 if (ret == ERROR_MORE_DATA)
1560 ret = RegQueryValueExA(hKey, pszValue, NULL,
1561 &dwType, pvBuf, &cbData);
1562 else
1563 {
1564 /* Even if cbData was large enough we have to copy the
1565 * string since ExpandEnvironmentStrings can't handle
1566 * overlapping buffers. */
1567 CopyMemory(pvBuf, pvData, cbData);
1568 }
1569
1570 /* Both the type or the value itself could have been modified in
1571 * between so we have to keep retrying until the buffer is large
1572 * enough or we no longer have to expand the value. */
1573 } while (dwType == REG_EXPAND_SZ && ret == ERROR_MORE_DATA);
1574
1575 if (ret == ERROR_SUCCESS)
1576 {
1577 if (dwType == REG_EXPAND_SZ)
1578 {
1579 cbData = ExpandEnvironmentStringsA(pvBuf, pvData,
1580 pcbData ? *pcbData : 0);
1581 dwType = REG_SZ;
1582 if(pcbData && cbData > *pcbData)
1583 ret = ERROR_MORE_DATA;
1584 }
1585 else if (pcbData)
1586 CopyMemory(pvData, pvBuf, *pcbData);
1587 }
1588
1589 if (pvBuf) HeapFree(GetProcessHeap(), 0, pvBuf);
1590 }
1591
1592 if (pszSubKey && pszSubKey[0])
1593 RegCloseKey(hKey);
1594
1595 ADVAPI_ApplyRestrictions(dwFlags, dwType, cbData, &ret);
1596
1597 if (pcbData && ret != ERROR_SUCCESS && (dwFlags & RRF_ZEROONFAILURE))
1598 ZeroMemory(pvData, *pcbData);
1599
1600 if (pdwType) *pdwType = dwType;
1601 if (pcbData) *pcbData = cbData;
1602
1603 return ret;
1604}
1605
1606
1607/******************************************************************************
James Hawkins6a358c42004-07-13 23:33:14 +00001608 * RegEnumValueW [ADVAPI32.@]
Alexandre Julliard2fab2ef1999-11-23 19:41:34 +00001609 *
Markus Amslerd45811c2005-11-04 11:43:27 +00001610 * Enumerates the values for the specified open registry key.
1611 *
Alexandre Julliard2fab2ef1999-11-23 19:41:34 +00001612 * PARAMS
James Hawkins6a358c42004-07-13 23:33:14 +00001613 * hkey [I] Handle to key to query
1614 * index [I] Index of value to query
1615 * value [O] Value string
1616 * val_count [I/O] Size of value buffer (in wchars)
1617 * reserved [I] Reserved
1618 * type [O] Type code
1619 * data [O] Value data
1620 * count [I/O] Size of data buffer (in bytes)
1621 *
1622 * RETURNS
1623 * Success: ERROR_SUCCESS
1624 * Failure: nonzero error code from Winerror.h
Alexandre Julliard2fab2ef1999-11-23 19:41:34 +00001625 */
1626
1627DWORD WINAPI RegEnumValueW( HKEY hkey, DWORD index, LPWSTR value, LPDWORD val_count,
1628 LPDWORD reserved, LPDWORD type, LPBYTE data, LPDWORD count )
1629{
Alexandre Julliard0b6a79c2000-12-15 20:57:00 +00001630 NTSTATUS status;
1631 DWORD total_size;
1632 char buffer[256], *buf_ptr = buffer;
1633 KEY_VALUE_FULL_INFORMATION *info = (KEY_VALUE_FULL_INFORMATION *)buffer;
Alexandre Julliarda0109322002-07-05 21:30:38 +00001634 static const int info_size = offsetof( KEY_VALUE_FULL_INFORMATION, Name );
Alexandre Julliard2fab2ef1999-11-23 19:41:34 +00001635
Michael Stefaniuccbacde52002-10-25 19:17:33 +00001636 TRACE("(%p,%ld,%p,%p,%p,%p,%p,%p)\n",
Alexandre Julliard2fab2ef1999-11-23 19:41:34 +00001637 hkey, index, value, val_count, reserved, type, data, count );
1638
1639 /* NT only checks count, not val_count */
Eric Pouech2c655f51999-11-25 22:05:46 +00001640 if ((data && !count) || reserved) return ERROR_INVALID_PARAMETER;
Alexandre Julliardf2ef2c22002-09-13 21:42:28 +00001641 if (!(hkey = get_special_root_hkey( hkey ))) return ERROR_INVALID_HANDLE;
Alexandre Julliard2fab2ef1999-11-23 19:41:34 +00001642
Alexandre Julliard0b6a79c2000-12-15 20:57:00 +00001643 total_size = info_size + (MAX_PATH + 1) * sizeof(WCHAR);
1644 if (data) total_size += *count;
1645 total_size = min( sizeof(buffer), total_size );
Alexandre Julliard2fab2ef1999-11-23 19:41:34 +00001646
Alexandre Julliard0b6a79c2000-12-15 20:57:00 +00001647 status = NtEnumerateValueKey( hkey, index, KeyValueFullInformation,
1648 buffer, total_size, &total_size );
1649 if (status && status != STATUS_BUFFER_OVERFLOW) goto done;
Alexandre Julliard2fab2ef1999-11-23 19:41:34 +00001650
Alexandre Julliard0b6a79c2000-12-15 20:57:00 +00001651 if (value || data)
Alexandre Julliarda01004d2000-05-14 22:57:57 +00001652 {
Alexandre Julliard0b6a79c2000-12-15 20:57:00 +00001653 /* retry with a dynamically allocated buffer */
1654 while (status == STATUS_BUFFER_OVERFLOW)
Alexandre Julliarda01004d2000-05-14 22:57:57 +00001655 {
Alexandre Julliard0b6a79c2000-12-15 20:57:00 +00001656 if (buf_ptr != buffer) HeapFree( GetProcessHeap(), 0, buf_ptr );
1657 if (!(buf_ptr = HeapAlloc( GetProcessHeap(), 0, total_size )))
1658 return ERROR_NOT_ENOUGH_MEMORY;
1659 info = (KEY_VALUE_FULL_INFORMATION *)buf_ptr;
1660 status = NtEnumerateValueKey( hkey, index, KeyValueFullInformation,
1661 buf_ptr, total_size, &total_size );
1662 }
1663
1664 if (status) goto done;
1665
1666 if (value)
1667 {
1668 if (info->NameLength/sizeof(WCHAR) >= *val_count)
Alexandre Julliarda01004d2000-05-14 22:57:57 +00001669 {
Alexandre Julliard0b6a79c2000-12-15 20:57:00 +00001670 status = STATUS_BUFFER_OVERFLOW;
Alexandre Julliardc1dddbe2002-07-10 03:27:35 +00001671 goto overflow;
Alexandre Julliard0b6a79c2000-12-15 20:57:00 +00001672 }
1673 memcpy( value, info->Name, info->NameLength );
1674 *val_count = info->NameLength / sizeof(WCHAR);
1675 value[*val_count] = 0;
1676 }
1677
1678 if (data)
1679 {
1680 if (total_size - info->DataOffset > *count)
1681 {
1682 status = STATUS_BUFFER_OVERFLOW;
Alexandre Julliardc1dddbe2002-07-10 03:27:35 +00001683 goto overflow;
Alexandre Julliard0b6a79c2000-12-15 20:57:00 +00001684 }
1685 memcpy( data, buf_ptr + info->DataOffset, total_size - info->DataOffset );
1686 if (total_size - info->DataOffset <= *count-sizeof(WCHAR) && is_string(info->Type))
1687 {
1688 /* if the type is REG_SZ and data is not 0-terminated
1689 * and there is enough space in the buffer NT appends a \0 */
1690 WCHAR *ptr = (WCHAR *)(data + total_size - info->DataOffset);
1691 if (ptr > (WCHAR *)data && ptr[-1]) *ptr = 0;
Alexandre Julliarda01004d2000-05-14 22:57:57 +00001692 }
1693 }
Alexandre Julliarda01004d2000-05-14 22:57:57 +00001694 }
Alexandre Julliardc6615832001-02-14 21:45:52 +00001695 else status = STATUS_SUCCESS;
Alexandre Julliard0b6a79c2000-12-15 20:57:00 +00001696
Alexandre Julliardc1dddbe2002-07-10 03:27:35 +00001697 overflow:
Alexandre Julliard0b6a79c2000-12-15 20:57:00 +00001698 if (type) *type = info->Type;
1699 if (count) *count = info->DataLength;
1700
1701 done:
1702 if (buf_ptr != buffer) HeapFree( GetProcessHeap(), 0, buf_ptr );
1703 return RtlNtStatusToDosError(status);
Alexandre Julliard2fab2ef1999-11-23 19:41:34 +00001704}
1705
1706
1707/******************************************************************************
James Hawkins6a358c42004-07-13 23:33:14 +00001708 * RegEnumValueA [ADVAPI32.@]
1709 *
Markus Amslerd45811c2005-11-04 11:43:27 +00001710 * See RegEnumValueW.
Alexandre Julliard2fab2ef1999-11-23 19:41:34 +00001711 */
1712DWORD WINAPI RegEnumValueA( HKEY hkey, DWORD index, LPSTR value, LPDWORD val_count,
1713 LPDWORD reserved, LPDWORD type, LPBYTE data, LPDWORD count )
1714{
Alexandre Julliard0b6a79c2000-12-15 20:57:00 +00001715 NTSTATUS status;
1716 DWORD total_size;
1717 char buffer[256], *buf_ptr = buffer;
1718 KEY_VALUE_FULL_INFORMATION *info = (KEY_VALUE_FULL_INFORMATION *)buffer;
Alexandre Julliarda0109322002-07-05 21:30:38 +00001719 static const int info_size = offsetof( KEY_VALUE_FULL_INFORMATION, Name );
Alexandre Julliard2fab2ef1999-11-23 19:41:34 +00001720
Michael Stefaniuccbacde52002-10-25 19:17:33 +00001721 TRACE("(%p,%ld,%p,%p,%p,%p,%p,%p)\n",
Alexandre Julliard2fab2ef1999-11-23 19:41:34 +00001722 hkey, index, value, val_count, reserved, type, data, count );
1723
1724 /* NT only checks count, not val_count */
Eric Pouech2c655f51999-11-25 22:05:46 +00001725 if ((data && !count) || reserved) return ERROR_INVALID_PARAMETER;
Alexandre Julliardf2ef2c22002-09-13 21:42:28 +00001726 if (!(hkey = get_special_root_hkey( hkey ))) return ERROR_INVALID_HANDLE;
Alexandre Julliard2fab2ef1999-11-23 19:41:34 +00001727
Alexandre Julliard0b6a79c2000-12-15 20:57:00 +00001728 total_size = info_size + (MAX_PATH + 1) * sizeof(WCHAR);
1729 if (data) total_size += *count;
1730 total_size = min( sizeof(buffer), total_size );
Alexandre Julliard2fab2ef1999-11-23 19:41:34 +00001731
Alexandre Julliard0b6a79c2000-12-15 20:57:00 +00001732 status = NtEnumerateValueKey( hkey, index, KeyValueFullInformation,
1733 buffer, total_size, &total_size );
1734 if (status && status != STATUS_BUFFER_OVERFLOW) goto done;
Alexandre Julliard2fab2ef1999-11-23 19:41:34 +00001735
Alexandre Julliard0b6a79c2000-12-15 20:57:00 +00001736 /* we need to fetch the contents for a string type even if not requested,
1737 * because we need to compute the length of the ASCII string. */
1738 if (value || data || is_string(info->Type))
Alexandre Julliarda01004d2000-05-14 22:57:57 +00001739 {
Alexandre Julliard0b6a79c2000-12-15 20:57:00 +00001740 /* retry with a dynamically allocated buffer */
1741 while (status == STATUS_BUFFER_OVERFLOW)
Alexandre Julliarda01004d2000-05-14 22:57:57 +00001742 {
Alexandre Julliard0b6a79c2000-12-15 20:57:00 +00001743 if (buf_ptr != buffer) HeapFree( GetProcessHeap(), 0, buf_ptr );
1744 if (!(buf_ptr = HeapAlloc( GetProcessHeap(), 0, total_size )))
1745 return ERROR_NOT_ENOUGH_MEMORY;
1746 info = (KEY_VALUE_FULL_INFORMATION *)buf_ptr;
1747 status = NtEnumerateValueKey( hkey, index, KeyValueFullInformation,
1748 buf_ptr, total_size, &total_size );
Alexandre Julliarda01004d2000-05-14 22:57:57 +00001749 }
Alexandre Julliard0b6a79c2000-12-15 20:57:00 +00001750
1751 if (status) goto done;
1752
Alexandre Julliard0b6a79c2000-12-15 20:57:00 +00001753 if (is_string(info->Type))
1754 {
Alexandre Julliard60fd03d2001-12-05 22:18:48 +00001755 DWORD len;
1756 RtlUnicodeToMultiByteSize( &len, (WCHAR *)(buf_ptr + info->DataOffset),
1757 total_size - info->DataOffset );
Alexandre Julliard0b6a79c2000-12-15 20:57:00 +00001758 if (data && len)
1759 {
Alexandre Julliardc1dddbe2002-07-10 03:27:35 +00001760 if (len > *count) status = STATUS_BUFFER_OVERFLOW;
1761 else
Alexandre Julliard0b6a79c2000-12-15 20:57:00 +00001762 {
Mike McCormack280bcf62005-08-27 10:00:38 +00001763 RtlUnicodeToMultiByteN( (char*)data, len, NULL, (WCHAR *)(buf_ptr + info->DataOffset),
Alexandre Julliardc1dddbe2002-07-10 03:27:35 +00001764 total_size - info->DataOffset );
1765 /* if the type is REG_SZ and data is not 0-terminated
1766 * and there is enough space in the buffer NT appends a \0 */
1767 if (len < *count && data[len-1]) data[len] = 0;
Alexandre Julliard0b6a79c2000-12-15 20:57:00 +00001768 }
Alexandre Julliard0b6a79c2000-12-15 20:57:00 +00001769 }
1770 info->DataLength = len;
1771 }
1772 else if (data)
1773 {
1774 if (total_size - info->DataOffset > *count) status = STATUS_BUFFER_OVERFLOW;
1775 else memcpy( data, buf_ptr + info->DataOffset, total_size - info->DataOffset );
1776 }
Alexandre Julliardc1dddbe2002-07-10 03:27:35 +00001777
1778 if (value && !status)
1779 {
1780 DWORD len;
1781
1782 RtlUnicodeToMultiByteSize( &len, info->Name, info->NameLength );
1783 if (len >= *val_count)
1784 {
1785 status = STATUS_BUFFER_OVERFLOW;
1786 if (*val_count)
1787 {
1788 len = *val_count - 1;
1789 RtlUnicodeToMultiByteN( value, len, NULL, info->Name, info->NameLength );
1790 value[len] = 0;
1791 }
1792 }
1793 else
1794 {
1795 RtlUnicodeToMultiByteN( value, len, NULL, info->Name, info->NameLength );
1796 value[len] = 0;
1797 *val_count = len;
1798 }
1799 }
Alexandre Julliarda01004d2000-05-14 22:57:57 +00001800 }
Alexandre Julliardc6615832001-02-14 21:45:52 +00001801 else status = STATUS_SUCCESS;
Alexandre Julliarda01004d2000-05-14 22:57:57 +00001802
Alexandre Julliard0b6a79c2000-12-15 20:57:00 +00001803 if (type) *type = info->Type;
1804 if (count) *count = info->DataLength;
1805
1806 done:
1807 if (buf_ptr != buffer) HeapFree( GetProcessHeap(), 0, buf_ptr );
1808 return RtlNtStatusToDosError(status);
Alexandre Julliard2fab2ef1999-11-23 19:41:34 +00001809}
1810
1811
1812
1813/******************************************************************************
James Hawkins6a358c42004-07-13 23:33:14 +00001814 * RegDeleteValueW [ADVAPI32.@]
Alexandre Julliard2fab2ef1999-11-23 19:41:34 +00001815 *
Jon Griffithscd4234a2003-03-18 18:35:48 +00001816 * See RegDeleteValueA.
Alexandre Julliard2fab2ef1999-11-23 19:41:34 +00001817 */
1818DWORD WINAPI RegDeleteValueW( HKEY hkey, LPCWSTR name )
1819{
Alexandre Julliardbcf393a2000-10-01 01:44:50 +00001820 UNICODE_STRING nameW;
Alexandre Julliardf2ef2c22002-09-13 21:42:28 +00001821
1822 if (!(hkey = get_special_root_hkey( hkey ))) return ERROR_INVALID_HANDLE;
1823
Alexandre Julliardbcf393a2000-10-01 01:44:50 +00001824 RtlInitUnicodeString( &nameW, name );
1825 return RtlNtStatusToDosError( NtDeleteValueKey( hkey, &nameW ) );
Alexandre Julliard2fab2ef1999-11-23 19:41:34 +00001826}
1827
1828
1829/******************************************************************************
James Hawkins6a358c42004-07-13 23:33:14 +00001830 * RegDeleteValueA [ADVAPI32.@]
Jon Griffithscd4234a2003-03-18 18:35:48 +00001831 *
1832 * Delete a value from the registry.
1833 *
1834 * PARAMS
1835 * hkey [I] Registry handle of the key holding the value
1836 * name [I] Name of the value under hkey to delete
1837 *
1838 * RETURNS
James Hawkins6a358c42004-07-13 23:33:14 +00001839 * Success: ERROR_SUCCESS
1840 * Failure: nonzero error code from Winerror.h
Alexandre Julliard2fab2ef1999-11-23 19:41:34 +00001841 */
1842DWORD WINAPI RegDeleteValueA( HKEY hkey, LPCSTR name )
1843{
Alexandre Julliardbcf393a2000-10-01 01:44:50 +00001844 STRING nameA;
1845 NTSTATUS status;
Alexandre Julliard2fab2ef1999-11-23 19:41:34 +00001846
Alexandre Julliardf2ef2c22002-09-13 21:42:28 +00001847 if (!(hkey = get_special_root_hkey( hkey ))) return ERROR_INVALID_HANDLE;
1848
Alexandre Julliardbcf393a2000-10-01 01:44:50 +00001849 RtlInitAnsiString( &nameA, name );
Alexandre Julliardab5e9752001-03-23 19:12:01 +00001850 if (!(status = RtlAnsiStringToUnicodeString( &NtCurrentTeb()->StaticUnicodeString,
1851 &nameA, FALSE )))
Alexandre Julliardab5e9752001-03-23 19:12:01 +00001852 status = NtDeleteValueKey( hkey, &NtCurrentTeb()->StaticUnicodeString );
Alexandre Julliardbcf393a2000-10-01 01:44:50 +00001853 return RtlNtStatusToDosError( status );
Alexandre Julliard2fab2ef1999-11-23 19:41:34 +00001854}
1855
1856
1857/******************************************************************************
James Hawkins6a358c42004-07-13 23:33:14 +00001858 * RegLoadKeyW [ADVAPI32.@]
Alexandre Julliard2fab2ef1999-11-23 19:41:34 +00001859 *
Markus Amslerec350522005-11-12 19:12:03 +00001860 * Create a subkey under HKEY_USERS or HKEY_LOCAL_MACHINE and store
1861 * registration information from a specified file into that subkey.
1862 *
Alexandre Julliard2fab2ef1999-11-23 19:41:34 +00001863 * PARAMS
James Hawkins6a358c42004-07-13 23:33:14 +00001864 * hkey [I] Handle of open key
1865 * subkey [I] Address of name of subkey
1866 * filename [I] Address of filename for registry information
1867 *
1868 * RETURNS
1869 * Success: ERROR_SUCCES
1870 * Failure: nonzero error code from Winerror.h
Alexandre Julliard2fab2ef1999-11-23 19:41:34 +00001871 */
1872LONG WINAPI RegLoadKeyW( HKEY hkey, LPCWSTR subkey, LPCWSTR filename )
1873{
James Hawkins580ded62005-03-29 11:38:58 +00001874 OBJECT_ATTRIBUTES destkey, file;
1875 UNICODE_STRING subkeyW, filenameW;
Alexandre Julliard2fab2ef1999-11-23 19:41:34 +00001876
James Hawkins580ded62005-03-29 11:38:58 +00001877 if (!(hkey = get_special_root_hkey(hkey))) return ERROR_INVALID_HANDLE;
Alexandre Julliard2fab2ef1999-11-23 19:41:34 +00001878
James Hawkins580ded62005-03-29 11:38:58 +00001879 destkey.Length = sizeof(destkey);
1880 destkey.RootDirectory = hkey; /* root key: HKLM or HKU */
1881 destkey.ObjectName = &subkeyW; /* name of the key */
1882 destkey.Attributes = 0;
1883 destkey.SecurityDescriptor = NULL;
1884 destkey.SecurityQualityOfService = NULL;
1885 RtlInitUnicodeString(&subkeyW, subkey);
Alexandre Julliard2fab2ef1999-11-23 19:41:34 +00001886
James Hawkins580ded62005-03-29 11:38:58 +00001887 file.Length = sizeof(file);
1888 file.RootDirectory = NULL;
1889 file.ObjectName = &filenameW; /* file containing the hive */
1890 file.Attributes = OBJ_CASE_INSENSITIVE;
1891 file.SecurityDescriptor = NULL;
1892 file.SecurityQualityOfService = NULL;
1893 RtlDosPathNameToNtPathName_U(filename, &filenameW, NULL, NULL);
Alexandre Julliard57f05e12000-10-15 00:40:25 +00001894
James Hawkins580ded62005-03-29 11:38:58 +00001895 return RtlNtStatusToDosError( NtLoadKey(&destkey, &file) );
Alexandre Julliard2fab2ef1999-11-23 19:41:34 +00001896}
1897
1898
1899/******************************************************************************
James Hawkins6a358c42004-07-13 23:33:14 +00001900 * RegLoadKeyA [ADVAPI32.@]
1901 *
Markus Amslerd45811c2005-11-04 11:43:27 +00001902 * See RegLoadKeyW.
Alexandre Julliard2fab2ef1999-11-23 19:41:34 +00001903 */
1904LONG WINAPI RegLoadKeyA( HKEY hkey, LPCSTR subkey, LPCSTR filename )
1905{
James Hawkins580ded62005-03-29 11:38:58 +00001906 UNICODE_STRING subkeyW, filenameW;
1907 STRING subkeyA, filenameA;
1908 NTSTATUS status;
Alexandre Julliard2fab2ef1999-11-23 19:41:34 +00001909
James Hawkins580ded62005-03-29 11:38:58 +00001910 RtlInitAnsiString(&subkeyA, subkey);
1911 RtlInitAnsiString(&filenameA, filename);
Alexandre Julliard2fab2ef1999-11-23 19:41:34 +00001912
James Hawkins580ded62005-03-29 11:38:58 +00001913 if ((status = RtlAnsiStringToUnicodeString(&subkeyW, &subkeyA, TRUE)))
1914 return RtlNtStatusToDosError(status);
Alexandre Julliard2fab2ef1999-11-23 19:41:34 +00001915
James Hawkins580ded62005-03-29 11:38:58 +00001916 if ((status = RtlAnsiStringToUnicodeString(&filenameW, &filenameA, TRUE)))
1917 return RtlNtStatusToDosError(status);
Alexandre Julliard57f05e12000-10-15 00:40:25 +00001918
James Hawkins580ded62005-03-29 11:38:58 +00001919 return RegLoadKeyW(hkey, subkeyW.Buffer, filenameW.Buffer);
Alexandre Julliard2fab2ef1999-11-23 19:41:34 +00001920}
1921
1922
1923/******************************************************************************
James Hawkins6a358c42004-07-13 23:33:14 +00001924 * RegSaveKeyW [ADVAPI32.@]
Alexandre Julliard2fab2ef1999-11-23 19:41:34 +00001925 *
Markus Amslerec350522005-11-12 19:12:03 +00001926 * Save a key and all of its subkeys and values to a new file in the standard format.
1927 *
Alexandre Julliard2fab2ef1999-11-23 19:41:34 +00001928 * PARAMS
James Hawkins6a358c42004-07-13 23:33:14 +00001929 * hkey [I] Handle of key where save begins
1930 * lpFile [I] Address of filename to save to
1931 * sa [I] Address of security structure
1932 *
1933 * RETURNS
1934 * Success: ERROR_SUCCESS
1935 * Failure: nonzero error code from Winerror.h
Alexandre Julliard2fab2ef1999-11-23 19:41:34 +00001936 */
Tony Lambregts4550b8b2003-03-14 04:50:34 +00001937LONG WINAPI RegSaveKeyW( HKEY hkey, LPCWSTR file, LPSECURITY_ATTRIBUTES sa )
Alexandre Julliard2fab2ef1999-11-23 19:41:34 +00001938{
Tony Lambregts4550b8b2003-03-14 04:50:34 +00001939 static const WCHAR format[] =
1940 {'r','e','g','%','0','4','x','.','t','m','p',0};
1941 WCHAR buffer[MAX_PATH];
Alexandre Julliard2fab2ef1999-11-23 19:41:34 +00001942 int count = 0;
Tony Lambregts4550b8b2003-03-14 04:50:34 +00001943 LPWSTR nameW;
Alexandre Julliard2fab2ef1999-11-23 19:41:34 +00001944 DWORD ret, err;
Alexandre Julliard73755972002-07-31 19:26:03 +00001945 HANDLE handle;
Alexandre Julliard2fab2ef1999-11-23 19:41:34 +00001946
Tony Lambregts4550b8b2003-03-14 04:50:34 +00001947 TRACE( "(%p,%s,%p)\n", hkey, debugstr_w(file), sa );
Alexandre Julliard2fab2ef1999-11-23 19:41:34 +00001948
1949 if (!file || !*file) return ERROR_INVALID_PARAMETER;
Alexandre Julliardf2ef2c22002-09-13 21:42:28 +00001950 if (!(hkey = get_special_root_hkey( hkey ))) return ERROR_INVALID_HANDLE;
Alexandre Julliard2fab2ef1999-11-23 19:41:34 +00001951
1952 err = GetLastError();
Tony Lambregts4550b8b2003-03-14 04:50:34 +00001953 GetFullPathNameW( file, sizeof(buffer)/sizeof(WCHAR), buffer, &nameW );
1954
Alexandre Julliard2fab2ef1999-11-23 19:41:34 +00001955 for (;;)
1956 {
Tony Lambregts4550b8b2003-03-14 04:50:34 +00001957 snprintfW( nameW, 16, format, count++ );
1958 handle = CreateFileW( buffer, GENERIC_WRITE, 0, NULL,
François Gougetda2b6a92001-01-06 01:29:18 +00001959 CREATE_NEW, FILE_ATTRIBUTE_NORMAL, 0 );
Alexandre Julliard2fab2ef1999-11-23 19:41:34 +00001960 if (handle != INVALID_HANDLE_VALUE) break;
Alexandre Julliard53544172000-03-26 18:18:03 +00001961 if ((ret = GetLastError()) != ERROR_ALREADY_EXISTS) goto done;
Andreas Mohr62974512000-05-09 22:31:43 +00001962
1963 /* Something gone haywire ? Please report if this happens abnormally */
1964 if (count >= 100)
Tony Lambregts4550b8b2003-03-14 04:50:34 +00001965 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", debugstr_w(buffer), count);
Alexandre Julliard2fab2ef1999-11-23 19:41:34 +00001966 }
1967
Robert Shearmanf74b0ad2005-03-30 10:21:15 +00001968 ret = RtlNtStatusToDosError(NtSaveKey(hkey, handle));
Alexandre Julliard57f05e12000-10-15 00:40:25 +00001969
Alexandre Julliard2fab2ef1999-11-23 19:41:34 +00001970 CloseHandle( handle );
1971 if (!ret)
1972 {
Tony Lambregts4550b8b2003-03-14 04:50:34 +00001973 if (!MoveFileExW( buffer, file, MOVEFILE_REPLACE_EXISTING ))
Alexandre Julliard2fab2ef1999-11-23 19:41:34 +00001974 {
Tony Lambregts4550b8b2003-03-14 04:50:34 +00001975 ERR( "Failed to move %s to %s\n", debugstr_w(buffer),
1976 debugstr_w(file) );
Alexandre Julliard2fab2ef1999-11-23 19:41:34 +00001977 ret = GetLastError();
1978 }
1979 }
Tony Lambregts4550b8b2003-03-14 04:50:34 +00001980 if (ret) DeleteFileW( buffer );
Alexandre Julliard2fab2ef1999-11-23 19:41:34 +00001981
1982done:
1983 SetLastError( err ); /* restore last error code */
1984 return ret;
1985}
1986
1987
1988/******************************************************************************
James Hawkins6a358c42004-07-13 23:33:14 +00001989 * RegSaveKeyA [ADVAPI32.@]
1990 *
Markus Amslerd45811c2005-11-04 11:43:27 +00001991 * See RegSaveKeyW.
Alexandre Julliard2fab2ef1999-11-23 19:41:34 +00001992 */
Tony Lambregts4550b8b2003-03-14 04:50:34 +00001993LONG WINAPI RegSaveKeyA( HKEY hkey, LPCSTR file, LPSECURITY_ATTRIBUTES sa )
Alexandre Julliard2fab2ef1999-11-23 19:41:34 +00001994{
Tony Lambregts4550b8b2003-03-14 04:50:34 +00001995 UNICODE_STRING *fileW = &NtCurrentTeb()->StaticUnicodeString;
1996 NTSTATUS status;
1997 STRING fileA;
1998
1999 RtlInitAnsiString(&fileA, file);
2000 if ((status = RtlAnsiStringToUnicodeString(fileW, &fileA, FALSE)))
2001 return RtlNtStatusToDosError( status );
2002 return RegSaveKeyW(hkey, fileW->Buffer, sa);
Alexandre Julliard2fab2ef1999-11-23 19:41:34 +00002003}
Alexandre Julliard5ce23292000-11-30 20:31:41 +00002004
2005
2006/******************************************************************************
Patrik Stridvalld0a41772001-02-14 23:11:17 +00002007 * RegRestoreKeyW [ADVAPI32.@]
Alexandre Julliard5ce23292000-11-30 20:31:41 +00002008 *
Markus Amslerec350522005-11-12 19:12:03 +00002009 * Read the registry information from a file and copy it over a key.
2010 *
Alexandre Julliard5ce23292000-11-30 20:31:41 +00002011 * PARAMS
James Hawkins6a358c42004-07-13 23:33:14 +00002012 * hkey [I] Handle of key where restore begins
2013 * lpFile [I] Address of filename containing saved tree
2014 * dwFlags [I] Optional flags
2015 *
2016 * RETURNS
2017 * Success: ERROR_SUCCESS
2018 * Failure: nonzero error code from Winerror.h
Alexandre Julliard5ce23292000-11-30 20:31:41 +00002019 */
2020LONG WINAPI RegRestoreKeyW( HKEY hkey, LPCWSTR lpFile, DWORD dwFlags )
2021{
Michael Stefaniuccbacde52002-10-25 19:17:33 +00002022 TRACE("(%p,%s,%ld)\n",hkey,debugstr_w(lpFile),dwFlags);
Alexandre Julliard5ce23292000-11-30 20:31:41 +00002023
2024 /* It seems to do this check before the hkey check */
2025 if (!lpFile || !*lpFile)
2026 return ERROR_INVALID_PARAMETER;
2027
Michael Stefaniuccbacde52002-10-25 19:17:33 +00002028 FIXME("(%p,%s,%ld): stub\n",hkey,debugstr_w(lpFile),dwFlags);
Alexandre Julliard5ce23292000-11-30 20:31:41 +00002029
2030 /* Check for file existence */
2031
2032 return ERROR_SUCCESS;
2033}
2034
2035
2036/******************************************************************************
Patrik Stridvalld0a41772001-02-14 23:11:17 +00002037 * RegRestoreKeyA [ADVAPI32.@]
James Hawkins6a358c42004-07-13 23:33:14 +00002038 *
Markus Amslerd45811c2005-11-04 11:43:27 +00002039 * See RegRestoreKeyW.
Alexandre Julliard5ce23292000-11-30 20:31:41 +00002040 */
2041LONG WINAPI RegRestoreKeyA( HKEY hkey, LPCSTR lpFile, DWORD dwFlags )
2042{
Matthew Davison6f2a0712003-01-20 23:23:12 +00002043 UNICODE_STRING lpFileW;
2044 LONG ret;
2045
2046 RtlCreateUnicodeStringFromAsciiz( &lpFileW, lpFile );
2047 ret = RegRestoreKeyW( hkey, lpFileW.Buffer, dwFlags );
2048 RtlFreeUnicodeString( &lpFileW );
Alexandre Julliard5ce23292000-11-30 20:31:41 +00002049 return ret;
2050}
2051
2052
2053/******************************************************************************
Patrik Stridvalld0a41772001-02-14 23:11:17 +00002054 * RegUnLoadKeyW [ADVAPI32.@]
Alexandre Julliard5ce23292000-11-30 20:31:41 +00002055 *
Markus Amslerec350522005-11-12 19:12:03 +00002056 * Unload a registry key and its subkeys from the registry.
2057 *
Alexandre Julliard5ce23292000-11-30 20:31:41 +00002058 * PARAMS
James Hawkins6a358c42004-07-13 23:33:14 +00002059 * hkey [I] Handle of open key
2060 * lpSubKey [I] Address of name of subkey to unload
2061 *
2062 * RETURNS
2063 * Success: ERROR_SUCCESS
2064 * Failure: nonzero error code from Winerror.h
Alexandre Julliard5ce23292000-11-30 20:31:41 +00002065 */
2066LONG WINAPI RegUnLoadKeyW( HKEY hkey, LPCWSTR lpSubKey )
2067{
Mike McCormack5ac945c2003-08-19 03:08:17 +00002068 DWORD ret;
2069 HKEY shkey;
2070
2071 TRACE("(%p,%s)\n",hkey, debugstr_w(lpSubKey));
2072
2073 ret = RegOpenKeyW(hkey,lpSubKey,&shkey);
2074 if( ret )
2075 return ERROR_INVALID_PARAMETER;
2076
Robert Shearmanf74b0ad2005-03-30 10:21:15 +00002077 ret = RtlNtStatusToDosError(NtUnloadKey(shkey));
2078
Mike McCormack5ac945c2003-08-19 03:08:17 +00002079 RegCloseKey(shkey);
2080
2081 return ret;
Alexandre Julliard5ce23292000-11-30 20:31:41 +00002082}
2083
2084
2085/******************************************************************************
Patrik Stridvalld0a41772001-02-14 23:11:17 +00002086 * RegUnLoadKeyA [ADVAPI32.@]
James Hawkins6a358c42004-07-13 23:33:14 +00002087 *
Markus Amslerd45811c2005-11-04 11:43:27 +00002088 * See RegUnLoadKeyW.
Alexandre Julliard5ce23292000-11-30 20:31:41 +00002089 */
2090LONG WINAPI RegUnLoadKeyA( HKEY hkey, LPCSTR lpSubKey )
2091{
Matthew Davison6f2a0712003-01-20 23:23:12 +00002092 UNICODE_STRING lpSubKeyW;
2093 LONG ret;
2094
2095 RtlCreateUnicodeStringFromAsciiz( &lpSubKeyW, lpSubKey );
2096 ret = RegUnLoadKeyW( hkey, lpSubKeyW.Buffer );
2097 RtlFreeUnicodeString( &lpSubKeyW );
Alexandre Julliard5ce23292000-11-30 20:31:41 +00002098 return ret;
2099}
2100
2101
2102/******************************************************************************
Patrik Stridvalld0a41772001-02-14 23:11:17 +00002103 * RegReplaceKeyW [ADVAPI32.@]
Alexandre Julliard5ce23292000-11-30 20:31:41 +00002104 *
Markus Amslerec350522005-11-12 19:12:03 +00002105 * Replace the file backing a registry key and all its subkeys with another file.
2106 *
Alexandre Julliard5ce23292000-11-30 20:31:41 +00002107 * PARAMS
James Hawkins6a358c42004-07-13 23:33:14 +00002108 * hkey [I] Handle of open key
2109 * lpSubKey [I] Address of name of subkey
2110 * lpNewFile [I] Address of filename for file with new data
2111 * lpOldFile [I] Address of filename for backup file
2112 *
2113 * RETURNS
2114 * Success: ERROR_SUCCESS
2115 * Failure: nonzero error code from Winerror.h
Alexandre Julliard5ce23292000-11-30 20:31:41 +00002116 */
2117LONG WINAPI RegReplaceKeyW( HKEY hkey, LPCWSTR lpSubKey, LPCWSTR lpNewFile,
2118 LPCWSTR lpOldFile )
2119{
Michael Stefaniuccbacde52002-10-25 19:17:33 +00002120 FIXME("(%p,%s,%s,%s): stub\n", hkey, debugstr_w(lpSubKey),
Alexandre Julliard5ce23292000-11-30 20:31:41 +00002121 debugstr_w(lpNewFile),debugstr_w(lpOldFile));
2122 return ERROR_SUCCESS;
2123}
2124
2125
2126/******************************************************************************
Patrik Stridvalld0a41772001-02-14 23:11:17 +00002127 * RegReplaceKeyA [ADVAPI32.@]
James Hawkins6a358c42004-07-13 23:33:14 +00002128 *
Markus Amslerd45811c2005-11-04 11:43:27 +00002129 * See RegReplaceKeyW.
Alexandre Julliard5ce23292000-11-30 20:31:41 +00002130 */
2131LONG WINAPI RegReplaceKeyA( HKEY hkey, LPCSTR lpSubKey, LPCSTR lpNewFile,
2132 LPCSTR lpOldFile )
2133{
Matthew Davison6f2a0712003-01-20 23:23:12 +00002134 UNICODE_STRING lpSubKeyW;
2135 UNICODE_STRING lpNewFileW;
2136 UNICODE_STRING lpOldFileW;
2137 LONG ret;
2138
2139 RtlCreateUnicodeStringFromAsciiz( &lpSubKeyW, lpSubKey );
2140 RtlCreateUnicodeStringFromAsciiz( &lpOldFileW, lpOldFile );
2141 RtlCreateUnicodeStringFromAsciiz( &lpNewFileW, lpNewFile );
2142 ret = RegReplaceKeyW( hkey, lpSubKeyW.Buffer, lpNewFileW.Buffer, lpOldFileW.Buffer );
2143 RtlFreeUnicodeString( &lpOldFileW );
2144 RtlFreeUnicodeString( &lpNewFileW );
2145 RtlFreeUnicodeString( &lpSubKeyW );
Alexandre Julliard5ce23292000-11-30 20:31:41 +00002146 return ret;
2147}
2148
2149
2150/******************************************************************************
Patrik Stridvalld0a41772001-02-14 23:11:17 +00002151 * RegSetKeySecurity [ADVAPI32.@]
Alexandre Julliard5ce23292000-11-30 20:31:41 +00002152 *
Markus Amslerec350522005-11-12 19:12:03 +00002153 * Set the security of an open registry key.
2154 *
Alexandre Julliard5ce23292000-11-30 20:31:41 +00002155 * PARAMS
James Hawkins6a358c42004-07-13 23:33:14 +00002156 * hkey [I] Open handle of key to set
2157 * SecurityInfo [I] Descriptor contents
2158 * pSecurityDesc [I] Address of descriptor for key
2159 *
2160 * RETURNS
2161 * Success: ERROR_SUCCESS
2162 * Failure: nonzero error code from Winerror.h
Alexandre Julliard5ce23292000-11-30 20:31:41 +00002163 */
2164LONG WINAPI RegSetKeySecurity( HKEY hkey, SECURITY_INFORMATION SecurityInfo,
2165 PSECURITY_DESCRIPTOR pSecurityDesc )
2166{
Michael Stefaniuccbacde52002-10-25 19:17:33 +00002167 TRACE("(%p,%ld,%p)\n",hkey,SecurityInfo,pSecurityDesc);
Alexandre Julliard5ce23292000-11-30 20:31:41 +00002168
2169 /* It seems to perform this check before the hkey check */
2170 if ((SecurityInfo & OWNER_SECURITY_INFORMATION) ||
2171 (SecurityInfo & GROUP_SECURITY_INFORMATION) ||
2172 (SecurityInfo & DACL_SECURITY_INFORMATION) ||
2173 (SecurityInfo & SACL_SECURITY_INFORMATION)) {
2174 /* Param OK */
2175 } else
2176 return ERROR_INVALID_PARAMETER;
2177
2178 if (!pSecurityDesc)
2179 return ERROR_INVALID_PARAMETER;
2180
Michael Stefaniuccbacde52002-10-25 19:17:33 +00002181 FIXME(":(%p,%ld,%p): stub\n",hkey,SecurityInfo,pSecurityDesc);
Alexandre Julliard5ce23292000-11-30 20:31:41 +00002182
2183 return ERROR_SUCCESS;
2184}
2185
2186
2187/******************************************************************************
Patrik Stridvalld0a41772001-02-14 23:11:17 +00002188 * RegGetKeySecurity [ADVAPI32.@]
Jon Griffiths50ce0842004-04-23 21:32:34 +00002189 *
2190 * Get a copy of the security descriptor for a given registry key.
Alexandre Julliard5ce23292000-11-30 20:31:41 +00002191 *
2192 * PARAMS
James Hawkins6a358c42004-07-13 23:33:14 +00002193 * hkey [I] Open handle of key to set
2194 * SecurityInformation [I] Descriptor contents
2195 * pSecurityDescriptor [O] Address of descriptor for key
2196 * lpcbSecurityDescriptor [I/O] Address of size of buffer and description
Alexandre Julliard5ce23292000-11-30 20:31:41 +00002197 *
2198 * RETURNS
James Hawkins6a358c42004-07-13 23:33:14 +00002199 * Success: ERROR_SUCCESS
2200 * Failure: Error code
Alexandre Julliard5ce23292000-11-30 20:31:41 +00002201 */
2202LONG WINAPI RegGetKeySecurity( HKEY hkey, SECURITY_INFORMATION SecurityInformation,
2203 PSECURITY_DESCRIPTOR pSecurityDescriptor,
2204 LPDWORD lpcbSecurityDescriptor )
2205{
Michael Stefaniuccbacde52002-10-25 19:17:33 +00002206 TRACE("(%p,%ld,%p,%ld)\n",hkey,SecurityInformation,pSecurityDescriptor,
Alexandre Julliard5ce23292000-11-30 20:31:41 +00002207 lpcbSecurityDescriptor?*lpcbSecurityDescriptor:0);
2208
2209 /* FIXME: Check for valid SecurityInformation values */
2210
2211 if (*lpcbSecurityDescriptor < sizeof(SECURITY_DESCRIPTOR))
2212 return ERROR_INSUFFICIENT_BUFFER;
2213
Michael Stefaniuccbacde52002-10-25 19:17:33 +00002214 FIXME("(%p,%ld,%p,%ld): stub\n",hkey,SecurityInformation,
Alexandre Julliard5ce23292000-11-30 20:31:41 +00002215 pSecurityDescriptor,lpcbSecurityDescriptor?*lpcbSecurityDescriptor:0);
2216
Dmitry Timoshkov79313d32002-04-02 02:41:27 +00002217 /* Do not leave security descriptor filled with garbage */
2218 RtlCreateSecurityDescriptor(pSecurityDescriptor, SECURITY_DESCRIPTOR_REVISION);
2219
Alexandre Julliard5ce23292000-11-30 20:31:41 +00002220 return ERROR_SUCCESS;
2221}
2222
2223
2224/******************************************************************************
Patrik Stridvalld0a41772001-02-14 23:11:17 +00002225 * RegFlushKey [ADVAPI32.@]
Jon Griffiths50ce0842004-04-23 21:32:34 +00002226 *
2227 * Immediately write a registry key to registry.
Alexandre Julliard5ce23292000-11-30 20:31:41 +00002228 *
2229 * PARAMS
James Hawkins6a358c42004-07-13 23:33:14 +00002230 * hkey [I] Handle of key to write
Alexandre Julliard5ce23292000-11-30 20:31:41 +00002231 *
2232 * RETURNS
James Hawkins6a358c42004-07-13 23:33:14 +00002233 * Success: ERROR_SUCCESS
2234 * Failure: Error code
Alexandre Julliard5ce23292000-11-30 20:31:41 +00002235 */
2236DWORD WINAPI RegFlushKey( HKEY hkey )
2237{
Mike Hearn43cb03b2004-01-03 00:38:30 +00002238 hkey = get_special_root_hkey( hkey );
2239 if (!hkey) return ERROR_INVALID_HANDLE;
2240
2241 return RtlNtStatusToDosError( NtFlushKey( hkey ) );
Alexandre Julliard5ce23292000-11-30 20:31:41 +00002242}
2243
2244
2245/******************************************************************************
Patrik Stridvalld0a41772001-02-14 23:11:17 +00002246 * RegConnectRegistryW [ADVAPI32.@]
Alexandre Julliard5ce23292000-11-30 20:31:41 +00002247 *
Markus Amslerec350522005-11-12 19:12:03 +00002248 * Establishe a connection to a predefined registry key on another computer.
2249 *
Alexandre Julliard5ce23292000-11-30 20:31:41 +00002250 * PARAMS
James Hawkins6a358c42004-07-13 23:33:14 +00002251 * lpMachineName [I] Address of name of remote computer
2252 * hHey [I] Predefined registry handle
2253 * phkResult [I] Address of buffer for remote registry handle
2254 *
2255 * RETURNS
2256 * Success: ERROR_SUCCESS
2257 * Failure: nonzero error code from Winerror.h
Alexandre Julliard5ce23292000-11-30 20:31:41 +00002258 */
Vincent Béron9a624912002-05-31 23:06:46 +00002259LONG WINAPI RegConnectRegistryW( LPCWSTR lpMachineName, HKEY hKey,
Alexandre Julliard5cf56a32002-10-03 19:46:27 +00002260 PHKEY phkResult )
Alexandre Julliard5ce23292000-11-30 20:31:41 +00002261{
Juan Langae176d12004-03-18 01:34:23 +00002262 LONG ret;
2263
Michael Stefaniuccbacde52002-10-25 19:17:33 +00002264 TRACE("(%s,%p,%p): stub\n",debugstr_w(lpMachineName),hKey,phkResult);
Alexandre Julliard5ce23292000-11-30 20:31:41 +00002265
2266 if (!lpMachineName || !*lpMachineName) {
2267 /* Use the local machine name */
Juan Langae176d12004-03-18 01:34:23 +00002268 ret = RegOpenKeyW( hKey, NULL, phkResult );
Alexandre Julliard5ce23292000-11-30 20:31:41 +00002269 }
Rein Klazesc16e7052005-09-15 09:31:05 +00002270 else {
Juan Langae176d12004-03-18 01:34:23 +00002271 WCHAR compName[MAX_COMPUTERNAME_LENGTH + 1];
2272 DWORD len = sizeof(compName) / sizeof(WCHAR);
Alexandre Julliard5ce23292000-11-30 20:31:41 +00002273
Rein Klazesc16e7052005-09-15 09:31:05 +00002274 /* MSDN says lpMachineName must start with \\ : not so */
2275 if( lpMachineName[0] == '\\' && lpMachineName[1] == '\\')
2276 lpMachineName += 2;
Juan Langae176d12004-03-18 01:34:23 +00002277 if (GetComputerNameW(compName, &len))
2278 {
Rein Klazesc16e7052005-09-15 09:31:05 +00002279 if (!strcmpiW(lpMachineName, compName))
Juan Langae176d12004-03-18 01:34:23 +00002280 ret = RegOpenKeyW(hKey, NULL, phkResult);
2281 else
2282 {
Rein Klazesc16e7052005-09-15 09:31:05 +00002283 FIXME("Connect to %s is not supported.\n",debugstr_w(lpMachineName));
Juan Langae176d12004-03-18 01:34:23 +00002284 ret = ERROR_BAD_NETPATH;
2285 }
2286 }
2287 else
2288 ret = GetLastError();
2289 }
2290 return ret;
Alexandre Julliard5ce23292000-11-30 20:31:41 +00002291}
2292
2293
2294/******************************************************************************
Patrik Stridvalld0a41772001-02-14 23:11:17 +00002295 * RegConnectRegistryA [ADVAPI32.@]
James Hawkins6a358c42004-07-13 23:33:14 +00002296 *
Markus Amslerd45811c2005-11-04 11:43:27 +00002297 * See RegConnectRegistryW.
Alexandre Julliard5ce23292000-11-30 20:31:41 +00002298 */
Alexandre Julliard5cf56a32002-10-03 19:46:27 +00002299LONG WINAPI RegConnectRegistryA( LPCSTR machine, HKEY hkey, PHKEY reskey )
Alexandre Julliard5ce23292000-11-30 20:31:41 +00002300{
Matthew Davison6f2a0712003-01-20 23:23:12 +00002301 UNICODE_STRING machineW;
2302 LONG ret;
2303
2304 RtlCreateUnicodeStringFromAsciiz( &machineW, machine );
2305 ret = RegConnectRegistryW( machineW.Buffer, hkey, reskey );
2306 RtlFreeUnicodeString( &machineW );
Alexandre Julliard5ce23292000-11-30 20:31:41 +00002307 return ret;
2308}
2309
2310
2311/******************************************************************************
Patrik Stridvalld0a41772001-02-14 23:11:17 +00002312 * RegNotifyChangeKeyValue [ADVAPI32.@]
Alexandre Julliard5ce23292000-11-30 20:31:41 +00002313 *
Markus Amslerec350522005-11-12 19:12:03 +00002314 * Notify the caller about changes to the attributes or contents of a registry key.
2315 *
Alexandre Julliard5ce23292000-11-30 20:31:41 +00002316 * PARAMS
James Hawkins6a358c42004-07-13 23:33:14 +00002317 * hkey [I] Handle of key to watch
2318 * fWatchSubTree [I] Flag for subkey notification
2319 * fdwNotifyFilter [I] Changes to be reported
2320 * hEvent [I] Handle of signaled event
2321 * fAsync [I] Flag for asynchronous reporting
2322 *
2323 * RETURNS
2324 * Success: ERROR_SUCCESS
2325 * Failure: nonzero error code from Winerror.h
Alexandre Julliard5ce23292000-11-30 20:31:41 +00002326 */
Vincent Béron9a624912002-05-31 23:06:46 +00002327LONG WINAPI RegNotifyChangeKeyValue( HKEY hkey, BOOL fWatchSubTree,
Alexandre Julliard5ce23292000-11-30 20:31:41 +00002328 DWORD fdwNotifyFilter, HANDLE hEvent,
2329 BOOL fAsync )
2330{
Robert Shearmanefbea2e2005-05-16 14:08:11 +00002331 NTSTATUS status;
2332 IO_STATUS_BLOCK iosb;
Mike McCormack11f4b442002-11-25 02:47:32 +00002333
Robert Shearmanefbea2e2005-05-16 14:08:11 +00002334 hkey = get_special_root_hkey( hkey );
2335 if (!hkey) return ERROR_INVALID_HANDLE;
Mike McCormack11f4b442002-11-25 02:47:32 +00002336
Robert Shearmanefbea2e2005-05-16 14:08:11 +00002337 TRACE("(%p,%i,%ld,%p,%i)\n", hkey, fWatchSubTree, fdwNotifyFilter,
2338 hEvent, fAsync);
Mike McCormack11f4b442002-11-25 02:47:32 +00002339
Robert Shearmanefbea2e2005-05-16 14:08:11 +00002340 status = NtNotifyChangeKey( hkey, hEvent, NULL, NULL, &iosb,
Aric Stewart91080632006-02-09 12:08:47 +01002341 fdwNotifyFilter, fAsync, NULL, 0,
2342 fWatchSubTree);
Mike McCormack11f4b442002-11-25 02:47:32 +00002343
Robert Shearmanefbea2e2005-05-16 14:08:11 +00002344 if (status && status != STATUS_TIMEOUT)
2345 return RtlNtStatusToDosError( status );
2346
2347 return ERROR_SUCCESS;
Alexandre Julliard5ce23292000-11-30 20:31:41 +00002348}
Robert Shearman65e81822004-01-16 04:40:33 +00002349
2350/******************************************************************************
2351 * RegOpenUserClassesRoot [ADVAPI32.@]
Jon Griffiths50ce0842004-04-23 21:32:34 +00002352 *
2353 * Open the HKEY_CLASSES_ROOT key for a user.
Robert Shearman65e81822004-01-16 04:40:33 +00002354 *
2355 * PARAMS
James Hawkins6a358c42004-07-13 23:33:14 +00002356 * hToken [I] Handle of token representing the user
2357 * dwOptions [I] Reserved, nust be 0
2358 * samDesired [I] Desired access rights
2359 * phkResult [O] Destination for the resulting key handle
Robert Shearman65e81822004-01-16 04:40:33 +00002360 *
James Hawkins6a358c42004-07-13 23:33:14 +00002361 * RETURNS
2362 * Success: ERROR_SUCCESS
2363 * Failure: nonzero error code from Winerror.h
2364 *
Jon Griffiths50ce0842004-04-23 21:32:34 +00002365 * NOTES
James Hawkins6a358c42004-07-13 23:33:14 +00002366 * On Windows 2000 and upwards the HKEY_CLASSES_ROOT key is a view of the
2367 * "HKEY_LOCAL_MACHINE\Software\Classes" and the
2368 * "HKEY_CURRENT_USER\Software\Classes" keys merged together.
Robert Shearman65e81822004-01-16 04:40:33 +00002369 */
2370LONG WINAPI RegOpenUserClassesRoot(
2371 HANDLE hToken,
2372 DWORD dwOptions,
2373 REGSAM samDesired,
2374 PHKEY phkResult
2375)
2376{
2377 FIXME("(%p, 0x%lx, 0x%lx, %p) semi-stub\n", hToken, dwOptions, samDesired, phkResult);
2378
2379 *phkResult = HKEY_CLASSES_ROOT;
2380 return ERROR_SUCCESS;
2381}
Michael Jungac615ce2006-02-14 10:41:18 +01002382
2383/******************************************************************************
2384 * load_string [Internal]
2385 *
2386 * This is basically a copy of user32/resource.c's LoadStringW. Necessary to
2387 * avoid importing user32, which is higher level than advapi32. Helper for
2388 * RegLoadMUIString.
2389 */
2390static int load_string(HINSTANCE hModule, UINT resId, LPWSTR pwszBuffer, INT cMaxChars)
2391{
2392 HGLOBAL hMemory;
2393 HRSRC hResource;
2394 WCHAR *pString;
2395 int idxString;
2396
2397 /* Negative values have to be inverted. */
2398 if (HIWORD(resId) == 0xffff)
2399 resId = (UINT)(-((INT)resId));
2400
2401 /* Load the resource into memory and get a pointer to it. */
2402 hResource = FindResourceW(hModule, MAKEINTRESOURCEW(LOWORD(resId >> 4) + 1), (LPWSTR)RT_STRING);
2403 if (!hResource) return 0;
2404 hMemory = LoadResource(hModule, hResource);
2405 if (!hMemory) return 0;
2406 pString = LockResource(hMemory);
2407
2408 /* Strings are length-prefixed. Lowest nibble of resId is an index. */
2409 idxString = resId & 0xf;
2410 while (idxString--) pString += *pString + 1;
2411
2412 /* If no buffer is given, return length of the string. */
2413 if (!pwszBuffer) return *pString;
2414
2415 /* Else copy over the string, respecting the buffer size. */
2416 cMaxChars = (*pString < cMaxChars) ? *pString : (cMaxChars - 1);
2417 if (cMaxChars >= 0) {
2418 memcpy(pwszBuffer, pString+1, cMaxChars * sizeof(WCHAR));
2419 pwszBuffer[cMaxChars] = '\0';
2420 }
2421
2422 return cMaxChars;
2423}
2424
2425/******************************************************************************
2426 * RegLoadMUIStringW [ADVAPI32.@]
2427 *
2428 * Load the localized version of a string resource from some PE, respective
2429 * id and path of which are given in the registry value in the format
2430 * @[path]\dllname,-resourceId
2431 *
2432 * PARAMS
2433 * hKey [I] Key, of which to load the string value from.
2434 * pszValue [I] The value to be loaded (Has to be of REG_EXPAND_SZ or REG_SZ type).
2435 * pszBuffer [O] Buffer to store the localized string in.
2436 * cbBuffer [I] Size of the destination buffer in bytes.
2437 * pcbData [O] Number of bytes written to pszBuffer (optional, may be NULL).
2438 * dwFlags [I] None supported yet.
2439 * pszBaseDir [I] Not supported yet.
2440 *
2441 * RETURNS
2442 * Success: ERROR_SUCCESS,
2443 * Failure: nonzero error code from winerror.h
2444 *
2445 * NOTES
2446 * This is an API of Windows Vista, which wasn't available at the time this code
2447 * was written. We have to check for the correct behaviour once it's available.
2448 */
2449LONG WINAPI RegLoadMUIStringW(HKEY hKey, LPCWSTR pwszValue, LPWSTR pwszBuffer, DWORD cbBuffer,
2450 LPDWORD pcbData, DWORD dwFlags, LPCWSTR pwszBaseDir)
2451{
2452 DWORD dwValueType, cbData;
2453 LPWSTR pwszTempBuffer = NULL, pwszExpandedBuffer = NULL;
2454 LONG result;
2455
2456 TRACE("(hKey = %p, pwszValue = %s, pwszBuffer = %p, cbBuffer = %ld, pcbData = %p, "
2457 "dwFlags = %ld, pwszBaseDir = %s) stub\n", hKey, debugstr_w(pwszValue), pwszBuffer,
2458 cbBuffer, pcbData, dwFlags, debugstr_w(pwszBaseDir));
2459
2460 /* Parameter sanity checks. */
2461 if (!hKey || !pwszBuffer)
2462 return ERROR_INVALID_PARAMETER;
2463
2464 if (pwszBaseDir && *pwszBaseDir) {
2465 FIXME("BaseDir parameter not yet supported!\n");
2466 return ERROR_INVALID_PARAMETER;
2467 }
2468
2469 /* Check for value existence and correctness of it's type, allocate a buffer and load it. */
2470 result = RegQueryValueExW(hKey, pwszValue, NULL, &dwValueType, NULL, &cbData);
2471 if (result != ERROR_SUCCESS) goto cleanup;
2472 if (!(dwValueType == REG_SZ || dwValueType == REG_EXPAND_SZ) || !cbData) {
2473 result = ERROR_FILE_NOT_FOUND;
2474 goto cleanup;
2475 }
2476 pwszTempBuffer = HeapAlloc(GetProcessHeap(), 0, cbData);
2477 if (!pwszTempBuffer) {
2478 result = ERROR_NOT_ENOUGH_MEMORY;
2479 goto cleanup;
2480 }
2481 result = RegQueryValueExW(hKey, pwszValue, NULL, &dwValueType, (LPBYTE)pwszTempBuffer, &cbData);
2482 if (result != ERROR_SUCCESS) goto cleanup;
2483
2484 /* Expand environment variables, if appropriate, or copy the original string over. */
2485 if (dwValueType == REG_EXPAND_SZ) {
2486 cbData = ExpandEnvironmentStringsW(pwszTempBuffer, NULL, 0) * sizeof(WCHAR);
2487 if (!cbData) goto cleanup;
2488 pwszExpandedBuffer = HeapAlloc(GetProcessHeap(), 0, cbData);
2489 if (!pwszExpandedBuffer) {
2490 result = ERROR_NOT_ENOUGH_MEMORY;
2491 goto cleanup;
2492 }
2493 ExpandEnvironmentStringsW(pwszTempBuffer, pwszExpandedBuffer, cbData);
2494 } else {
2495 pwszExpandedBuffer = HeapAlloc(GetProcessHeap(), 0, cbData);
2496 memcpy(pwszExpandedBuffer, pwszTempBuffer, cbData);
2497 }
2498
2499 /* If the value references a resource based string, parse the value and load the string.
2500 * Else just copy over the original value. */
2501 result = ERROR_SUCCESS;
2502 if (*pwszExpandedBuffer != '@') { /* '@' is the prefix for resource based string entries. */
2503 lstrcpynW(pwszBuffer, pwszExpandedBuffer, cbBuffer / sizeof(WCHAR));
2504 } else {
2505 WCHAR *pComma = strrchrW(pwszExpandedBuffer, ',');
2506 UINT uiStringId;
2507 HMODULE hModule;
2508
2509 /* Format of the expanded value is 'path_to_dll,-resId' */
2510 if (!pComma || pComma[1] != '-') {
2511 result = ERROR_BADKEY;
2512 goto cleanup;
2513 }
2514
2515 uiStringId = atoiW(pComma+2);
2516 *pComma = '\0';
2517
2518 hModule = LoadLibraryW(pwszExpandedBuffer + 1);
2519 if (!hModule || !load_string(hModule, uiStringId, pwszBuffer, cbBuffer/sizeof(WCHAR)))
2520 result = ERROR_BADKEY;
2521 FreeLibrary(hModule);
2522 }
2523
2524cleanup:
2525 HeapFree(GetProcessHeap(), 0, pwszTempBuffer);
2526 HeapFree(GetProcessHeap(), 0, pwszExpandedBuffer);
2527 return result;
2528}
2529
2530/******************************************************************************
2531 * RegLoadMUIStringA [ADVAPI32.@]
2532 *
2533 * See RegLoadMUIStringW
2534 */
2535LONG WINAPI RegLoadMUIStringA(HKEY hKey, LPCSTR pszValue, LPSTR pszBuffer, DWORD cbBuffer,
2536 LPDWORD pcbData, DWORD dwFlags, LPCSTR pszBaseDir)
2537{
2538 UNICODE_STRING valueW, baseDirW;
2539 WCHAR *pwszBuffer;
2540 DWORD cbData = cbBuffer * sizeof(WCHAR);
2541 LONG result;
2542
2543 valueW.Buffer = baseDirW.Buffer = pwszBuffer = NULL;
2544 if (!RtlCreateUnicodeStringFromAsciiz(&valueW, pszValue) ||
2545 !RtlCreateUnicodeStringFromAsciiz(&baseDirW, pszBaseDir) ||
2546 !(pwszBuffer = HeapAlloc(GetProcessHeap(), 0, cbData)))
2547 {
2548 result = ERROR_NOT_ENOUGH_MEMORY;
2549 goto cleanup;
2550 }
2551
2552 result = RegLoadMUIStringW(hKey, valueW.Buffer, pwszBuffer, cbData, NULL, dwFlags,
2553 baseDirW.Buffer);
2554
2555 if (result == ERROR_SUCCESS) {
2556 cbData = WideCharToMultiByte(CP_ACP, 0, pwszBuffer, -1, pszBuffer, cbBuffer, NULL, NULL);
2557 if (pcbData)
2558 *pcbData = cbData;
2559 }
2560
2561cleanup:
2562 HeapFree(GetProcessHeap(), 0, pwszBuffer);
2563 RtlFreeUnicodeString(&baseDirW);
2564 RtlFreeUnicodeString(&valueW);
2565
2566 return result;
2567}