Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 1 | /* |
| 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 Julliard | 0799c1a | 2002-03-09 23:29:33 +0000 | [diff] [blame] | 13 | * |
| 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 Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 27 | */ |
| 28 | |
| 29 | #include <stdlib.h> |
Alexandre Julliard | e37c6e1 | 2003-09-05 23:08:26 +0000 | [diff] [blame] | 30 | #include <stdarg.h> |
Alexandre Julliard | 383da68 | 2000-02-10 22:15:21 +0000 | [diff] [blame] | 31 | #include <stdio.h> |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 32 | |
Ge van Geldorp | 1a1583a | 2005-11-28 17:32:54 +0100 | [diff] [blame] | 33 | #include "ntstatus.h" |
| 34 | #define WIN32_NO_STATUS |
Alexandre Julliard | e37c6e1 | 2003-09-05 23:08:26 +0000 | [diff] [blame] | 35 | #include "windef.h" |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 36 | #include "winbase.h" |
| 37 | #include "winreg.h" |
| 38 | #include "winerror.h" |
Matthew Davison | 6f2a071 | 2003-01-20 23:23:12 +0000 | [diff] [blame] | 39 | #include "winternl.h" |
Michael Jung | ac615ce | 2006-02-14 10:41:18 +0100 | [diff] [blame] | 40 | #include "winuser.h" |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 41 | |
Robert Shearman | efbea2e | 2005-05-16 14:08:11 +0000 | [diff] [blame] | 42 | #include "wine/unicode.h" |
| 43 | #include "wine/debug.h" |
| 44 | |
Alexandre Julliard | 0799c1a | 2002-03-09 23:29:33 +0000 | [diff] [blame] | 45 | WINE_DEFAULT_DEBUG_CHANNEL(reg); |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 46 | |
Alexandre Julliard | f2ef2c2 | 2002-09-13 21:42:28 +0000 | [diff] [blame] | 47 | /* 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 | |
| 54 | static HKEY special_root_keys[NB_SPECIAL_ROOT_KEYS]; |
| 55 | |
| 56 | static 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}; |
| 60 | static const WCHAR name_LOCAL_MACHINE[] = |
| 61 | {'M','a','c','h','i','n','e',0}; |
| 62 | static const WCHAR name_USERS[] = |
| 63 | {'U','s','e','r',0}; |
| 64 | static const WCHAR name_PERFORMANCE_DATA[] = |
| 65 | {'P','e','r','f','D','a','t','a',0}; |
| 66 | static 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 Davies | 8e9d88c1 | 2004-08-26 18:22:58 +0000 | [diff] [blame] | 70 | 'H','a','r','d','w','a','r','e',' ','P','r','o','f','i','l','e','s','\\', |
Alexandre Julliard | f2ef2c2 | 2002-09-13 21:42:28 +0000 | [diff] [blame] | 71 | 'C','u','r','r','e','n','t',0}; |
| 72 | static 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 } |
| 76 | static 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 Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 88 | |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 89 | /* check if value type needs string conversion (Ansi<->Unicode) */ |
Michael Cardenas | 7dbce65 | 2002-03-21 01:24:52 +0000 | [diff] [blame] | 90 | inline static int is_string( DWORD type ) |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 91 | { |
| 92 | return (type == REG_SZ) || (type == REG_EXPAND_SZ) || (type == REG_MULTI_SZ); |
| 93 | } |
| 94 | |
Michael Cardenas | 7dbce65 | 2002-03-21 01:24:52 +0000 | [diff] [blame] | 95 | /* check if current version is NT or Win95 */ |
| 96 | inline static int is_version_nt(void) |
| 97 | { |
| 98 | return !(GetVersion() & 0x80000000); |
| 99 | } |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 100 | |
Alexandre Julliard | f2ef2c2 | 2002-09-13 21:42:28 +0000 | [diff] [blame] | 101 | /* create one of the HKEY_* special root keys */ |
Mike McCormack | 5b2d5fd | 2005-06-17 13:58:33 +0000 | [diff] [blame] | 102 | static HKEY create_special_root_hkey( HANDLE hkey, DWORD access ) |
Alexandre Julliard | f2ef2c2 | 2002-09-13 21:42:28 +0000 | [diff] [blame] | 103 | { |
| 104 | HKEY ret = 0; |
Alexandre Julliard | 261e376 | 2005-09-12 15:14:06 +0000 | [diff] [blame] | 105 | int idx = (UINT_PTR)hkey - (UINT_PTR)HKEY_SPECIAL_ROOT_FIRST; |
Alexandre Julliard | f2ef2c2 | 2002-09-13 21:42:28 +0000 | [diff] [blame] | 106 | |
| 107 | if (hkey == HKEY_CURRENT_USER) |
| 108 | { |
| 109 | if (RtlOpenCurrentUser( access, &hkey )) return 0; |
Michael Stefaniuc | cbacde5 | 2002-10-25 19:17:33 +0000 | [diff] [blame] | 110 | TRACE( "HKEY_CURRENT_USER -> %p\n", hkey ); |
Alexandre Julliard | f2ef2c2 | 2002-09-13 21:42:28 +0000 | [diff] [blame] | 111 | } |
| 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 Stefaniuc | cbacde5 | 2002-10-25 19:17:33 +0000 | [diff] [blame] | 123 | TRACE( "%s -> %p\n", debugstr_w(attr.ObjectName->Buffer), hkey ); |
Alexandre Julliard | f2ef2c2 | 2002-09-13 21:42:28 +0000 | [diff] [blame] | 124 | } |
| 125 | |
Michael Stefaniuc | cbacde5 | 2002-10-25 19:17:33 +0000 | [diff] [blame] | 126 | if (!(ret = InterlockedCompareExchangePointer( (void **)&special_root_keys[idx], hkey, 0 ))) |
Alexandre Julliard | f2ef2c2 | 2002-09-13 21:42:28 +0000 | [diff] [blame] | 127 | 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 */ |
| 134 | inline 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 Julliard | 261e376 | 2005-09-12 15:14:06 +0000 | [diff] [blame] | 140 | if (!(ret = special_root_keys[(UINT_PTR)hkey - (UINT_PTR)HKEY_SPECIAL_ROOT_FIRST])) |
Alexandre Julliard | f2ef2c2 | 2002-09-13 21:42:28 +0000 | [diff] [blame] | 141 | ret = create_special_root_hkey( hkey, KEY_ALL_ACCESS ); |
| 142 | } |
| 143 | return ret; |
| 144 | } |
| 145 | |
Juergen Schmied | a44e0b0 | 2002-05-09 19:39:10 +0000 | [diff] [blame] | 146 | |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 147 | /****************************************************************************** |
James Hawkins | 6a358c4 | 2004-07-13 23:33:14 +0000 | [diff] [blame] | 148 | * RegCreateKeyExW [ADVAPI32.@] |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 149 | * |
Jon Griffiths | 50ce084 | 2004-04-23 21:32:34 +0000 | [diff] [blame] | 150 | * See RegCreateKeyExA. |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 151 | */ |
Steven Edwards | e14569d | 2005-07-28 10:18:23 +0000 | [diff] [blame] | 152 | DWORD WINAPI RegCreateKeyExW( HKEY hkey, LPCWSTR name, DWORD reserved, LPWSTR class, |
Vincent Béron | 9a62491 | 2002-05-31 23:06:46 +0000 | [diff] [blame] | 153 | DWORD options, REGSAM access, SECURITY_ATTRIBUTES *sa, |
Alexandre Julliard | 5cf56a3 | 2002-10-03 19:46:27 +0000 | [diff] [blame] | 154 | PHKEY retkey, LPDWORD dispos ) |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 155 | { |
Alexandre Julliard | bcf393a | 2000-10-01 01:44:50 +0000 | [diff] [blame] | 156 | OBJECT_ATTRIBUTES attr; |
| 157 | UNICODE_STRING nameW, classW; |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 158 | |
| 159 | if (reserved) return ERROR_INVALID_PARAMETER; |
Juergen Schmied | a44e0b0 | 2002-05-09 19:39:10 +0000 | [diff] [blame] | 160 | if (!(access & KEY_ACCESS_MASK) || (access & ~KEY_ACCESS_MASK)) return ERROR_ACCESS_DENIED; |
Alexandre Julliard | f2ef2c2 | 2002-09-13 21:42:28 +0000 | [diff] [blame] | 161 | if (!(hkey = get_special_root_hkey( hkey ))) return ERROR_INVALID_HANDLE; |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 162 | |
Alexandre Julliard | bcf393a | 2000-10-01 01:44:50 +0000 | [diff] [blame] | 163 | 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 McCormack | 5b2d5fd | 2005-06-17 13:58:33 +0000 | [diff] [blame] | 172 | return RtlNtStatusToDosError( NtCreateKey( (PHANDLE)retkey, access, &attr, 0, |
Alexandre Julliard | bcf393a | 2000-10-01 01:44:50 +0000 | [diff] [blame] | 173 | &classW, options, dispos ) ); |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 174 | } |
| 175 | |
| 176 | |
| 177 | /****************************************************************************** |
James Hawkins | 6a358c4 | 2004-07-13 23:33:14 +0000 | [diff] [blame] | 178 | * RegCreateKeyExA [ADVAPI32.@] |
Juergen Schmied | a44e0b0 | 2002-05-09 19:39:10 +0000 | [diff] [blame] | 179 | * |
Jon Griffiths | 50ce084 | 2004-04-23 21:32:34 +0000 | [diff] [blame] | 180 | * Open a registry key, creating it if it doesn't exist. |
| 181 | * |
| 182 | * PARAMS |
James Hawkins | 6a358c4 | 2004-07-13 23:33:14 +0000 | [diff] [blame] | 183 | * 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 Griffiths | 50ce084 | 2004-04-23 21:32:34 +0000 | [diff] [blame] | 192 | * |
| 193 | * RETURNS |
James Hawkins | 6a358c4 | 2004-07-13 23:33:14 +0000 | [diff] [blame] | 194 | * Success: ERROR_SUCCESS. |
| 195 | * Failure: A standard Win32 error code. retkey remains untouched. |
Jon Griffiths | 50ce084 | 2004-04-23 21:32:34 +0000 | [diff] [blame] | 196 | * |
| 197 | * FIXME |
James Hawkins | 6a358c4 | 2004-07-13 23:33:14 +0000 | [diff] [blame] | 198 | * MAXIMUM_ALLOWED in access mask not supported by server |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 199 | */ |
Steven Edwards | e14569d | 2005-07-28 10:18:23 +0000 | [diff] [blame] | 200 | DWORD WINAPI RegCreateKeyExA( HKEY hkey, LPCSTR name, DWORD reserved, LPSTR class, |
Vincent Béron | 9a62491 | 2002-05-31 23:06:46 +0000 | [diff] [blame] | 201 | DWORD options, REGSAM access, SECURITY_ATTRIBUTES *sa, |
Alexandre Julliard | 5cf56a3 | 2002-10-03 19:46:27 +0000 | [diff] [blame] | 202 | PHKEY retkey, LPDWORD dispos ) |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 203 | { |
Alexandre Julliard | bcf393a | 2000-10-01 01:44:50 +0000 | [diff] [blame] | 204 | OBJECT_ATTRIBUTES attr; |
Alexandre Julliard | ab5e975 | 2001-03-23 19:12:01 +0000 | [diff] [blame] | 205 | UNICODE_STRING classW; |
Alexandre Julliard | bcf393a | 2000-10-01 01:44:50 +0000 | [diff] [blame] | 206 | ANSI_STRING nameA, classA; |
| 207 | NTSTATUS status; |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 208 | |
| 209 | if (reserved) return ERROR_INVALID_PARAMETER; |
Rein Klazes | 62b69d6 | 2005-12-08 13:49:02 +0100 | [diff] [blame] | 210 | 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 Schmied | a44e0b0 | 2002-05-09 19:39:10 +0000 | [diff] [blame] | 215 | else if (!(access & KEY_ACCESS_MASK) || (access & ~KEY_ACCESS_MASK)) return ERROR_ACCESS_DENIED; |
Alexandre Julliard | f2ef2c2 | 2002-09-13 21:42:28 +0000 | [diff] [blame] | 216 | if (!(hkey = get_special_root_hkey( hkey ))) return ERROR_INVALID_HANDLE; |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 217 | |
Alexandre Julliard | bcf393a | 2000-10-01 01:44:50 +0000 | [diff] [blame] | 218 | attr.Length = sizeof(attr); |
| 219 | attr.RootDirectory = hkey; |
Alexandre Julliard | ab5e975 | 2001-03-23 19:12:01 +0000 | [diff] [blame] | 220 | attr.ObjectName = &NtCurrentTeb()->StaticUnicodeString; |
Alexandre Julliard | bcf393a | 2000-10-01 01:44:50 +0000 | [diff] [blame] | 221 | attr.Attributes = 0; |
| 222 | attr.SecurityDescriptor = NULL; |
| 223 | attr.SecurityQualityOfService = NULL; |
| 224 | RtlInitAnsiString( &nameA, name ); |
| 225 | RtlInitAnsiString( &classA, class ); |
| 226 | |
Alexandre Julliard | ab5e975 | 2001-03-23 19:12:01 +0000 | [diff] [blame] | 227 | if (!(status = RtlAnsiStringToUnicodeString( &NtCurrentTeb()->StaticUnicodeString, |
| 228 | &nameA, FALSE ))) |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 229 | { |
Alexandre Julliard | bcf393a | 2000-10-01 01:44:50 +0000 | [diff] [blame] | 230 | if (!(status = RtlAnsiStringToUnicodeString( &classW, &classA, TRUE ))) |
| 231 | { |
Mike McCormack | 5b2d5fd | 2005-06-17 13:58:33 +0000 | [diff] [blame] | 232 | status = NtCreateKey( (PHANDLE)retkey, access, &attr, 0, &classW, options, dispos ); |
Alexandre Julliard | bcf393a | 2000-10-01 01:44:50 +0000 | [diff] [blame] | 233 | RtlFreeUnicodeString( &classW ); |
| 234 | } |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 235 | } |
Alexandre Julliard | bcf393a | 2000-10-01 01:44:50 +0000 | [diff] [blame] | 236 | return RtlNtStatusToDosError( status ); |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 237 | } |
| 238 | |
| 239 | |
| 240 | /****************************************************************************** |
James Hawkins | 6a358c4 | 2004-07-13 23:33:14 +0000 | [diff] [blame] | 241 | * 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 Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 253 | */ |
James Hawkins | 6a358c4 | 2004-07-13 23:33:14 +0000 | [diff] [blame] | 254 | DWORD WINAPI RegCreateKeyW( HKEY hkey, LPCWSTR lpSubKey, PHKEY phkResult ) |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 255 | { |
| 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 Hawkins | 6a358c4 | 2004-07-13 23:33:14 +0000 | [diff] [blame] | 258 | return RegCreateKeyExW( hkey, lpSubKey, 0, NULL, REG_OPTION_NON_VOLATILE, |
| 259 | KEY_ALL_ACCESS, NULL, phkResult, NULL ); |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 260 | } |
| 261 | |
| 262 | |
| 263 | /****************************************************************************** |
James Hawkins | 6a358c4 | 2004-07-13 23:33:14 +0000 | [diff] [blame] | 264 | * RegCreateKeyA [ADVAPI32.@] |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 265 | * |
Markus Amsler | d45811c | 2005-11-04 11:43:27 +0000 | [diff] [blame] | 266 | * See RegCreateKeyW. |
James Hawkins | 6a358c4 | 2004-07-13 23:33:14 +0000 | [diff] [blame] | 267 | */ |
| 268 | DWORD 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 Griffiths | 50ce084 | 2004-04-23 21:32:34 +0000 | [diff] [blame] | 279 | * See RegOpenKeyExA. |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 280 | */ |
Alexandre Julliard | 5cf56a3 | 2002-10-03 19:46:27 +0000 | [diff] [blame] | 281 | DWORD WINAPI RegOpenKeyExW( HKEY hkey, LPCWSTR name, DWORD reserved, REGSAM access, PHKEY retkey ) |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 282 | { |
Alexandre Julliard | bcf393a | 2000-10-01 01:44:50 +0000 | [diff] [blame] | 283 | OBJECT_ATTRIBUTES attr; |
| 284 | UNICODE_STRING nameW; |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 285 | |
Alexandre Julliard | f2ef2c2 | 2002-09-13 21:42:28 +0000 | [diff] [blame] | 286 | if (!(hkey = get_special_root_hkey( hkey ))) return ERROR_INVALID_HANDLE; |
| 287 | |
Alexandre Julliard | bcf393a | 2000-10-01 01:44:50 +0000 | [diff] [blame] | 288 | 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 McCormack | 5b2d5fd | 2005-06-17 13:58:33 +0000 | [diff] [blame] | 295 | return RtlNtStatusToDosError( NtOpenKey( (PHANDLE)retkey, access, &attr ) ); |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 296 | } |
| 297 | |
| 298 | |
| 299 | /****************************************************************************** |
James Hawkins | 6a358c4 | 2004-07-13 23:33:14 +0000 | [diff] [blame] | 300 | * RegOpenKeyExA [ADVAPI32.@] |
Jon Griffiths | 50ce084 | 2004-04-23 21:32:34 +0000 | [diff] [blame] | 301 | * |
| 302 | * Open a registry key. |
| 303 | * |
| 304 | * PARAMS |
James Hawkins | 6a358c4 | 2004-07-13 23:33:14 +0000 | [diff] [blame] | 305 | * 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 Griffiths | 50ce084 | 2004-04-23 21:32:34 +0000 | [diff] [blame] | 310 | * |
| 311 | * RETURNS |
James Hawkins | 6a358c4 | 2004-07-13 23:33:14 +0000 | [diff] [blame] | 312 | * Success: ERROR_SUCCESS |
| 313 | * Failure: A standard Win32 error code. retkey is set to 0. |
Jon Griffiths | 50ce084 | 2004-04-23 21:32:34 +0000 | [diff] [blame] | 314 | * |
| 315 | * NOTES |
James Hawkins | 6a358c4 | 2004-07-13 23:33:14 +0000 | [diff] [blame] | 316 | * Unlike RegCreateKeyExA(), this function will not create the key if it |
| 317 | * does not exist. |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 318 | */ |
Alexandre Julliard | 5cf56a3 | 2002-10-03 19:46:27 +0000 | [diff] [blame] | 319 | DWORD WINAPI RegOpenKeyExA( HKEY hkey, LPCSTR name, DWORD reserved, REGSAM access, PHKEY retkey ) |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 320 | { |
Alexandre Julliard | bcf393a | 2000-10-01 01:44:50 +0000 | [diff] [blame] | 321 | OBJECT_ATTRIBUTES attr; |
Alexandre Julliard | bcf393a | 2000-10-01 01:44:50 +0000 | [diff] [blame] | 322 | STRING nameA; |
| 323 | NTSTATUS status; |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 324 | |
Michael Cardenas | 7dbce65 | 2002-03-21 01:24:52 +0000 | [diff] [blame] | 325 | if (!is_version_nt()) access = KEY_ALL_ACCESS; /* Win95 ignores the access mask */ |
| 326 | |
Alexandre Julliard | f2ef2c2 | 2002-09-13 21:42:28 +0000 | [diff] [blame] | 327 | if (!(hkey = get_special_root_hkey( hkey ))) return ERROR_INVALID_HANDLE; |
| 328 | |
Alexandre Julliard | bcf393a | 2000-10-01 01:44:50 +0000 | [diff] [blame] | 329 | attr.Length = sizeof(attr); |
| 330 | attr.RootDirectory = hkey; |
Alexandre Julliard | ab5e975 | 2001-03-23 19:12:01 +0000 | [diff] [blame] | 331 | attr.ObjectName = &NtCurrentTeb()->StaticUnicodeString; |
Alexandre Julliard | bcf393a | 2000-10-01 01:44:50 +0000 | [diff] [blame] | 332 | attr.Attributes = 0; |
| 333 | attr.SecurityDescriptor = NULL; |
| 334 | attr.SecurityQualityOfService = NULL; |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 335 | |
Alexandre Julliard | bcf393a | 2000-10-01 01:44:50 +0000 | [diff] [blame] | 336 | RtlInitAnsiString( &nameA, name ); |
Alexandre Julliard | ab5e975 | 2001-03-23 19:12:01 +0000 | [diff] [blame] | 337 | if (!(status = RtlAnsiStringToUnicodeString( &NtCurrentTeb()->StaticUnicodeString, |
| 338 | &nameA, FALSE ))) |
Alexandre Julliard | bcf393a | 2000-10-01 01:44:50 +0000 | [diff] [blame] | 339 | { |
Mike McCormack | 5b2d5fd | 2005-06-17 13:58:33 +0000 | [diff] [blame] | 340 | status = NtOpenKey( (PHANDLE)retkey, access, &attr ); |
Alexandre Julliard | bcf393a | 2000-10-01 01:44:50 +0000 | [diff] [blame] | 341 | } |
| 342 | return RtlNtStatusToDosError( status ); |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 343 | } |
| 344 | |
| 345 | |
| 346 | /****************************************************************************** |
James Hawkins | 6a358c4 | 2004-07-13 23:33:14 +0000 | [diff] [blame] | 347 | * RegOpenKeyW [ADVAPI32.@] |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 348 | * |
Jon Griffiths | 50ce084 | 2004-04-23 21:32:34 +0000 | [diff] [blame] | 349 | * See RegOpenKeyA. |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 350 | */ |
Alexandre Julliard | 5cf56a3 | 2002-10-03 19:46:27 +0000 | [diff] [blame] | 351 | DWORD WINAPI RegOpenKeyW( HKEY hkey, LPCWSTR name, PHKEY retkey ) |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 352 | { |
James Hawkins | e8d1e2f | 2005-02-25 16:52:10 +0000 | [diff] [blame] | 353 | if (!name || !*name) |
| 354 | { |
| 355 | *retkey = hkey; |
| 356 | return ERROR_SUCCESS; |
| 357 | } |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 358 | return RegOpenKeyExW( hkey, name, 0, KEY_ALL_ACCESS, retkey ); |
| 359 | } |
| 360 | |
| 361 | |
| 362 | /****************************************************************************** |
James Hawkins | 6a358c4 | 2004-07-13 23:33:14 +0000 | [diff] [blame] | 363 | * RegOpenKeyA [ADVAPI32.@] |
Jon Griffiths | 50ce084 | 2004-04-23 21:32:34 +0000 | [diff] [blame] | 364 | * |
| 365 | * Open a registry key. |
| 366 | * |
| 367 | * PARAMS |
James Hawkins | 6a358c4 | 2004-07-13 23:33:14 +0000 | [diff] [blame] | 368 | * 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 Griffiths | 50ce084 | 2004-04-23 21:32:34 +0000 | [diff] [blame] | 371 | * |
| 372 | * RETURNS |
James Hawkins | 6a358c4 | 2004-07-13 23:33:14 +0000 | [diff] [blame] | 373 | * Success: ERROR_SUCCESS |
| 374 | * Failure: A standard Win32 error code. retkey is set to 0. |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 375 | */ |
Alexandre Julliard | 5cf56a3 | 2002-10-03 19:46:27 +0000 | [diff] [blame] | 376 | DWORD WINAPI RegOpenKeyA( HKEY hkey, LPCSTR name, PHKEY retkey ) |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 377 | { |
James Hawkins | e8d1e2f | 2005-02-25 16:52:10 +0000 | [diff] [blame] | 378 | if (!name || !*name) |
| 379 | { |
| 380 | *retkey = hkey; |
| 381 | return ERROR_SUCCESS; |
| 382 | } |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 383 | return RegOpenKeyExA( hkey, name, 0, KEY_ALL_ACCESS, retkey ); |
| 384 | } |
| 385 | |
| 386 | |
David Elliott | 44f84b5 | 2000-10-29 01:24:54 +0000 | [diff] [blame] | 387 | /****************************************************************************** |
James Hawkins | 6a358c4 | 2004-07-13 23:33:14 +0000 | [diff] [blame] | 388 | * RegOpenCurrentUser [ADVAPI32.@] |
Markus Amsler | ec35052 | 2005-11-12 19:12:03 +0000 | [diff] [blame] | 389 | * |
| 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 Elliott | 44f84b5 | 2000-10-29 01:24:54 +0000 | [diff] [blame] | 406 | */ |
| 407 | DWORD WINAPI RegOpenCurrentUser( REGSAM access, PHKEY retkey ) |
| 408 | { |
| 409 | return RegOpenKeyExA( HKEY_CURRENT_USER, "", 0, access, retkey ); |
| 410 | } |
| 411 | |
| 412 | |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 413 | |
| 414 | /****************************************************************************** |
James Hawkins | 6a358c4 | 2004-07-13 23:33:14 +0000 | [diff] [blame] | 415 | * RegEnumKeyExW [ADVAPI32.@] |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 416 | * |
Markus Amsler | ec35052 | 2005-11-12 19:12:03 +0000 | [diff] [blame] | 417 | * Enumerate subkeys of the specified open registry key. |
| 418 | * |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 419 | * PARAMS |
James Hawkins | 6a358c4 | 2004-07-13 23:33:14 +0000 | [diff] [blame] | 420 | * 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 Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 433 | */ |
| 434 | DWORD WINAPI RegEnumKeyExW( HKEY hkey, DWORD index, LPWSTR name, LPDWORD name_len, |
| 435 | LPDWORD reserved, LPWSTR class, LPDWORD class_len, FILETIME *ft ) |
| 436 | { |
Alexandre Julliard | 454355e | 2000-10-02 03:46:58 +0000 | [diff] [blame] | 437 | NTSTATUS status; |
| 438 | char buffer[256], *buf_ptr = buffer; |
| 439 | KEY_NODE_INFORMATION *info = (KEY_NODE_INFORMATION *)buffer; |
| 440 | DWORD total_size; |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 441 | |
Michael Stefaniuc | cbacde5 | 2002-10-25 19:17:33 +0000 | [diff] [blame] | 442 | TRACE( "(%p,%ld,%p,%p(%ld),%p,%p,%p,%p)\n", hkey, index, name, name_len, |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 443 | name_len ? *name_len : -1, reserved, class, class_len, ft ); |
| 444 | |
| 445 | if (reserved) return ERROR_INVALID_PARAMETER; |
Alexandre Julliard | f2ef2c2 | 2002-09-13 21:42:28 +0000 | [diff] [blame] | 446 | if (!(hkey = get_special_root_hkey( hkey ))) return ERROR_INVALID_HANDLE; |
Rein Klazes | 0bb6fdd | 2002-07-05 01:21:13 +0000 | [diff] [blame] | 447 | |
Alexandre Julliard | 454355e | 2000-10-02 03:46:58 +0000 | [diff] [blame] | 448 | status = NtEnumerateKey( hkey, index, KeyNodeInformation, |
| 449 | buffer, sizeof(buffer), &total_size ); |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 450 | |
Alexandre Julliard | 454355e | 2000-10-02 03:46:58 +0000 | [diff] [blame] | 451 | while (status == STATUS_BUFFER_OVERFLOW) |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 452 | { |
Alexandre Julliard | 454355e | 2000-10-02 03:46:58 +0000 | [diff] [blame] | 453 | /* 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 Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 460 | } |
Alexandre Julliard | 454355e | 2000-10-02 03:46:58 +0000 | [diff] [blame] | 461 | |
| 462 | if (!status) |
| 463 | { |
| 464 | DWORD len = info->NameLength / sizeof(WCHAR); |
| 465 | DWORD cls_len = info->ClassLength / sizeof(WCHAR); |
| 466 | |
Dmitry Timoshkov | 6b6596a | 2001-11-23 18:44:43 +0000 | [diff] [blame] | 467 | if (ft) *ft = *(FILETIME *)&info->LastWriteTime; |
Alexandre Julliard | 454355e | 2000-10-02 03:46:58 +0000 | [diff] [blame] | 468 | |
Aric Stewart | 20a4cc3 | 2002-02-05 19:45:55 +0000 | [diff] [blame] | 469 | if (len >= *name_len || (class && class_len && (cls_len >= *class_len))) |
Alexandre Julliard | 454355e | 2000-10-02 03:46:58 +0000 | [diff] [blame] | 470 | 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 Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 490 | } |
| 491 | |
| 492 | |
| 493 | /****************************************************************************** |
James Hawkins | 6a358c4 | 2004-07-13 23:33:14 +0000 | [diff] [blame] | 494 | * RegEnumKeyExA [ADVAPI32.@] |
| 495 | * |
Markus Amsler | d45811c | 2005-11-04 11:43:27 +0000 | [diff] [blame] | 496 | * See RegEnumKeyExW. |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 497 | */ |
| 498 | DWORD WINAPI RegEnumKeyExA( HKEY hkey, DWORD index, LPSTR name, LPDWORD name_len, |
| 499 | LPDWORD reserved, LPSTR class, LPDWORD class_len, FILETIME *ft ) |
| 500 | { |
Alexandre Julliard | 454355e | 2000-10-02 03:46:58 +0000 | [diff] [blame] | 501 | NTSTATUS status; |
| 502 | char buffer[256], *buf_ptr = buffer; |
| 503 | KEY_NODE_INFORMATION *info = (KEY_NODE_INFORMATION *)buffer; |
| 504 | DWORD total_size; |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 505 | |
Michael Stefaniuc | cbacde5 | 2002-10-25 19:17:33 +0000 | [diff] [blame] | 506 | TRACE( "(%p,%ld,%p,%p(%ld),%p,%p,%p,%p)\n", hkey, index, name, name_len, |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 507 | name_len ? *name_len : -1, reserved, class, class_len, ft ); |
| 508 | |
| 509 | if (reserved) return ERROR_INVALID_PARAMETER; |
Alexandre Julliard | f2ef2c2 | 2002-09-13 21:42:28 +0000 | [diff] [blame] | 510 | if (!(hkey = get_special_root_hkey( hkey ))) return ERROR_INVALID_HANDLE; |
Rein Klazes | 0bb6fdd | 2002-07-05 01:21:13 +0000 | [diff] [blame] | 511 | |
Alexandre Julliard | 454355e | 2000-10-02 03:46:58 +0000 | [diff] [blame] | 512 | status = NtEnumerateKey( hkey, index, KeyNodeInformation, |
| 513 | buffer, sizeof(buffer), &total_size ); |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 514 | |
Alexandre Julliard | 454355e | 2000-10-02 03:46:58 +0000 | [diff] [blame] | 515 | while (status == STATUS_BUFFER_OVERFLOW) |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 516 | { |
Alexandre Julliard | 454355e | 2000-10-02 03:46:58 +0000 | [diff] [blame] | 517 | /* 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 Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 524 | } |
Alexandre Julliard | 454355e | 2000-10-02 03:46:58 +0000 | [diff] [blame] | 525 | |
| 526 | if (!status) |
| 527 | { |
Alexandre Julliard | 60fd03d | 2001-12-05 22:18:48 +0000 | [diff] [blame] | 528 | DWORD len, cls_len; |
Alexandre Julliard | 454355e | 2000-10-02 03:46:58 +0000 | [diff] [blame] | 529 | |
Alexandre Julliard | 60fd03d | 2001-12-05 22:18:48 +0000 | [diff] [blame] | 530 | RtlUnicodeToMultiByteSize( &len, info->Name, info->NameLength ); |
| 531 | RtlUnicodeToMultiByteSize( &cls_len, (WCHAR *)(buf_ptr + info->ClassOffset), |
| 532 | info->ClassLength ); |
Dmitry Timoshkov | 6b6596a | 2001-11-23 18:44:43 +0000 | [diff] [blame] | 533 | if (ft) *ft = *(FILETIME *)&info->LastWriteTime; |
Alexandre Julliard | 454355e | 2000-10-02 03:46:58 +0000 | [diff] [blame] | 534 | |
Aric Stewart | 20a4cc3 | 2002-02-05 19:45:55 +0000 | [diff] [blame] | 535 | if (len >= *name_len || (class && class_len && (cls_len >= *class_len))) |
Alexandre Julliard | 454355e | 2000-10-02 03:46:58 +0000 | [diff] [blame] | 536 | status = STATUS_BUFFER_OVERFLOW; |
| 537 | else |
| 538 | { |
| 539 | *name_len = len; |
Alexandre Julliard | 60fd03d | 2001-12-05 22:18:48 +0000 | [diff] [blame] | 540 | RtlUnicodeToMultiByteN( name, len, NULL, info->Name, info->NameLength ); |
Alexandre Julliard | 454355e | 2000-10-02 03:46:58 +0000 | [diff] [blame] | 541 | name[len] = 0; |
| 542 | if (class_len) |
| 543 | { |
| 544 | *class_len = cls_len; |
| 545 | if (class) |
| 546 | { |
Alexandre Julliard | 60fd03d | 2001-12-05 22:18:48 +0000 | [diff] [blame] | 547 | RtlUnicodeToMultiByteN( class, cls_len, NULL, |
| 548 | (WCHAR *)(buf_ptr + info->ClassOffset), |
| 549 | info->ClassLength ); |
Alexandre Julliard | 454355e | 2000-10-02 03:46:58 +0000 | [diff] [blame] | 550 | class[cls_len] = 0; |
| 551 | } |
| 552 | } |
| 553 | } |
| 554 | } |
| 555 | |
| 556 | if (buf_ptr != buffer) HeapFree( GetProcessHeap(), 0, buf_ptr ); |
| 557 | return RtlNtStatusToDosError( status ); |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 558 | } |
| 559 | |
| 560 | |
| 561 | /****************************************************************************** |
James Hawkins | 6a358c4 | 2004-07-13 23:33:14 +0000 | [diff] [blame] | 562 | * 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 Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 576 | */ |
| 577 | DWORD 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 Hawkins | 6a358c4 | 2004-07-13 23:33:14 +0000 | [diff] [blame] | 584 | * RegEnumKeyA [ADVAPI32.@] |
| 585 | * |
Markus Amsler | d45811c | 2005-11-04 11:43:27 +0000 | [diff] [blame] | 586 | * See RegEnumKeyW. |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 587 | */ |
| 588 | DWORD 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 Hawkins | 6a358c4 | 2004-07-13 23:33:14 +0000 | [diff] [blame] | 595 | * RegQueryInfoKeyW [ADVAPI32.@] |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 596 | * |
Markus Amsler | d45811c | 2005-11-04 11:43:27 +0000 | [diff] [blame] | 597 | * Retrieves information about the specified registry key. |
| 598 | * |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 599 | * 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 Amsler | d45811c | 2005-11-04 11:43:27 +0000 | [diff] [blame] | 613 | * 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 Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 622 | */ |
| 623 | DWORD 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 Julliard | 454355e | 2000-10-02 03:46:58 +0000 | [diff] [blame] | 628 | NTSTATUS status; |
| 629 | char buffer[256], *buf_ptr = buffer; |
| 630 | KEY_FULL_INFORMATION *info = (KEY_FULL_INFORMATION *)buffer; |
| 631 | DWORD total_size; |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 632 | |
Michael Stefaniuc | cbacde5 | 2002-10-25 19:17:33 +0000 | [diff] [blame] | 633 | TRACE( "(%p,%p,%ld,%p,%p,%p,%p,%p,%p,%p,%p)\n", hkey, class, class_len ? *class_len : 0, |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 634 | reserved, subkeys, max_subkey, values, max_value, max_data, security, modif ); |
| 635 | |
Michael Cardenas | 7dbce65 | 2002-03-21 01:24:52 +0000 | [diff] [blame] | 636 | if (class && !class_len && is_version_nt()) return ERROR_INVALID_PARAMETER; |
Alexandre Julliard | f2ef2c2 | 2002-09-13 21:42:28 +0000 | [diff] [blame] | 637 | if (!(hkey = get_special_root_hkey( hkey ))) return ERROR_INVALID_HANDLE; |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 638 | |
Alexandre Julliard | 454355e | 2000-10-02 03:46:58 +0000 | [diff] [blame] | 639 | status = NtQueryKey( hkey, KeyFullInformation, buffer, sizeof(buffer), &total_size ); |
Alexandre Julliard | c661583 | 2001-02-14 21:45:52 +0000 | [diff] [blame] | 640 | if (status && status != STATUS_BUFFER_OVERFLOW) goto done; |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 641 | |
| 642 | if (class) |
| 643 | { |
Alexandre Julliard | 454355e | 2000-10-02 03:46:58 +0000 | [diff] [blame] | 644 | /* retry with a dynamically allocated buffer */ |
| 645 | while (status == STATUS_BUFFER_OVERFLOW) |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 646 | { |
Alexandre Julliard | 454355e | 2000-10-02 03:46:58 +0000 | [diff] [blame] | 647 | 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 Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 652 | } |
Alexandre Julliard | 454355e | 2000-10-02 03:46:58 +0000 | [diff] [blame] | 653 | |
Alexandre Julliard | c661583 | 2001-02-14 21:45:52 +0000 | [diff] [blame] | 654 | if (status) goto done; |
| 655 | |
| 656 | if (class_len && (info->ClassLength/sizeof(WCHAR) + 1 > *class_len)) |
Alexandre Julliard | 454355e | 2000-10-02 03:46:58 +0000 | [diff] [blame] | 657 | { |
Alexandre Julliard | c661583 | 2001-02-14 21:45:52 +0000 | [diff] [blame] | 658 | 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 Julliard | 454355e | 2000-10-02 03:46:58 +0000 | [diff] [blame] | 664 | } |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 665 | } |
Alexandre Julliard | c661583 | 2001-02-14 21:45:52 +0000 | [diff] [blame] | 666 | else status = STATUS_SUCCESS; |
Alexandre Julliard | 454355e | 2000-10-02 03:46:58 +0000 | [diff] [blame] | 667 | |
Alexandre Julliard | c661583 | 2001-02-14 21:45:52 +0000 | [diff] [blame] | 668 | 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 Timoshkov | 6b6596a | 2001-11-23 18:44:43 +0000 | [diff] [blame] | 675 | if (modif) *modif = *(FILETIME *)&info->LastWriteTime; |
Alexandre Julliard | 454355e | 2000-10-02 03:46:58 +0000 | [diff] [blame] | 676 | |
Alexandre Julliard | c661583 | 2001-02-14 21:45:52 +0000 | [diff] [blame] | 677 | done: |
Alexandre Julliard | 454355e | 2000-10-02 03:46:58 +0000 | [diff] [blame] | 678 | if (buf_ptr != buffer) HeapFree( GetProcessHeap(), 0, buf_ptr ); |
| 679 | return RtlNtStatusToDosError( status ); |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 680 | } |
| 681 | |
| 682 | |
| 683 | /****************************************************************************** |
James Hawkins | 6a358c4 | 2004-07-13 23:33:14 +0000 | [diff] [blame] | 684 | * 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 Strasser | 751c454 | 2002-07-20 20:02:55 +0000 | [diff] [blame] | 699 | */ |
| 700 | DWORD WINAPI RegQueryMultipleValuesA(HKEY hkey, PVALENTA val_list, DWORD num_vals, |
| 701 | LPSTR lpValueBuf, LPDWORD ldwTotsize) |
| 702 | { |
Hans Leidekker | 411fc5f | 2004-09-02 23:00:53 +0000 | [diff] [blame] | 703 | unsigned int i; |
Dominik Strasser | 751c454 | 2002-07-20 20:02:55 +0000 | [diff] [blame] | 704 | DWORD maxBytes = *ldwTotsize; |
| 705 | HRESULT status; |
| 706 | LPSTR bufptr = lpValueBuf; |
| 707 | *ldwTotsize = 0; |
| 708 | |
Michael Stefaniuc | cbacde5 | 2002-10-25 19:17:33 +0000 | [diff] [blame] | 709 | TRACE("(%p,%p,%ld,%p,%p=%ld)\n", hkey, val_list, num_vals, lpValueBuf, ldwTotsize, *ldwTotsize); |
Dominik Strasser | 751c454 | 2002-07-20 20:02:55 +0000 | [diff] [blame] | 710 | |
| 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 McCormack | 257c337 | 2005-07-07 12:08:42 +0000 | [diff] [blame] | 724 | (LPBYTE)bufptr, &val_list[i].ve_valuelen); |
Dominik Strasser | 751c454 | 2002-07-20 20:02:55 +0000 | [diff] [blame] | 725 | 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 Hawkins | 6a358c4 | 2004-07-13 23:33:14 +0000 | [diff] [blame] | 742 | * RegQueryMultipleValuesW [ADVAPI32.@] |
| 743 | * |
Markus Amsler | d45811c | 2005-11-04 11:43:27 +0000 | [diff] [blame] | 744 | * See RegQueryMultipleValuesA. |
Dominik Strasser | 751c454 | 2002-07-20 20:02:55 +0000 | [diff] [blame] | 745 | */ |
| 746 | DWORD WINAPI RegQueryMultipleValuesW(HKEY hkey, PVALENTW val_list, DWORD num_vals, |
| 747 | LPWSTR lpValueBuf, LPDWORD ldwTotsize) |
| 748 | { |
Hans Leidekker | 411fc5f | 2004-09-02 23:00:53 +0000 | [diff] [blame] | 749 | unsigned int i; |
Dominik Strasser | 751c454 | 2002-07-20 20:02:55 +0000 | [diff] [blame] | 750 | DWORD maxBytes = *ldwTotsize; |
| 751 | HRESULT status; |
| 752 | LPSTR bufptr = (LPSTR)lpValueBuf; |
| 753 | *ldwTotsize = 0; |
| 754 | |
Michael Stefaniuc | cbacde5 | 2002-10-25 19:17:33 +0000 | [diff] [blame] | 755 | TRACE("(%p,%p,%ld,%p,%p=%ld)\n", hkey, val_list, num_vals, lpValueBuf, ldwTotsize, *ldwTotsize); |
Dominik Strasser | 751c454 | 2002-07-20 20:02:55 +0000 | [diff] [blame] | 756 | |
| 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 McCormack | 257c337 | 2005-07-07 12:08:42 +0000 | [diff] [blame] | 769 | (LPBYTE)bufptr, &val_list[i].ve_valuelen); |
Dominik Strasser | 751c454 | 2002-07-20 20:02:55 +0000 | [diff] [blame] | 770 | 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 Hawkins | 6a358c4 | 2004-07-13 23:33:14 +0000 | [diff] [blame] | 786 | * 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 Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 808 | */ |
| 809 | DWORD 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 Julliard | 454355e | 2000-10-02 03:46:58 +0000 | [diff] [blame] | 814 | NTSTATUS status; |
| 815 | char buffer[256], *buf_ptr = buffer; |
| 816 | KEY_FULL_INFORMATION *info = (KEY_FULL_INFORMATION *)buffer; |
Alexandre Julliard | c661583 | 2001-02-14 21:45:52 +0000 | [diff] [blame] | 817 | DWORD total_size, len; |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 818 | |
Michael Stefaniuc | cbacde5 | 2002-10-25 19:17:33 +0000 | [diff] [blame] | 819 | TRACE( "(%p,%p,%ld,%p,%p,%p,%p,%p,%p,%p,%p)\n", hkey, class, class_len ? *class_len : 0, |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 820 | reserved, subkeys, max_subkey, values, max_value, max_data, security, modif ); |
| 821 | |
Michael Cardenas | 7dbce65 | 2002-03-21 01:24:52 +0000 | [diff] [blame] | 822 | if (class && !class_len && is_version_nt()) return ERROR_INVALID_PARAMETER; |
Alexandre Julliard | f2ef2c2 | 2002-09-13 21:42:28 +0000 | [diff] [blame] | 823 | if (!(hkey = get_special_root_hkey( hkey ))) return ERROR_INVALID_HANDLE; |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 824 | |
Alexandre Julliard | 454355e | 2000-10-02 03:46:58 +0000 | [diff] [blame] | 825 | status = NtQueryKey( hkey, KeyFullInformation, buffer, sizeof(buffer), &total_size ); |
Alexandre Julliard | c661583 | 2001-02-14 21:45:52 +0000 | [diff] [blame] | 826 | if (status && status != STATUS_BUFFER_OVERFLOW) goto done; |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 827 | |
Alexandre Julliard | 454355e | 2000-10-02 03:46:58 +0000 | [diff] [blame] | 828 | if (class || class_len) |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 829 | { |
Alexandre Julliard | 454355e | 2000-10-02 03:46:58 +0000 | [diff] [blame] | 830 | /* retry with a dynamically allocated buffer */ |
| 831 | while (status == STATUS_BUFFER_OVERFLOW) |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 832 | { |
Alexandre Julliard | 454355e | 2000-10-02 03:46:58 +0000 | [diff] [blame] | 833 | 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 Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 838 | } |
Alexandre Julliard | 454355e | 2000-10-02 03:46:58 +0000 | [diff] [blame] | 839 | |
Alexandre Julliard | c661583 | 2001-02-14 21:45:52 +0000 | [diff] [blame] | 840 | if (status) goto done; |
| 841 | |
Alexandre Julliard | 60fd03d | 2001-12-05 22:18:48 +0000 | [diff] [blame] | 842 | RtlUnicodeToMultiByteSize( &len, (WCHAR *)(buf_ptr + info->ClassOffset), info->ClassLength); |
Alexandre Julliard | c661583 | 2001-02-14 21:45:52 +0000 | [diff] [blame] | 843 | if (class_len) |
Alexandre Julliard | 454355e | 2000-10-02 03:46:58 +0000 | [diff] [blame] | 844 | { |
Alexandre Julliard | c661583 | 2001-02-14 21:45:52 +0000 | [diff] [blame] | 845 | if (len + 1 > *class_len) status = STATUS_BUFFER_OVERFLOW; |
| 846 | *class_len = len; |
| 847 | } |
| 848 | if (class && !status) |
| 849 | { |
Alexandre Julliard | 60fd03d | 2001-12-05 22:18:48 +0000 | [diff] [blame] | 850 | RtlUnicodeToMultiByteN( class, len, NULL, (WCHAR *)(buf_ptr + info->ClassOffset), |
| 851 | info->ClassLength ); |
Alexandre Julliard | c661583 | 2001-02-14 21:45:52 +0000 | [diff] [blame] | 852 | class[len] = 0; |
Alexandre Julliard | 454355e | 2000-10-02 03:46:58 +0000 | [diff] [blame] | 853 | } |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 854 | } |
Alexandre Julliard | c661583 | 2001-02-14 21:45:52 +0000 | [diff] [blame] | 855 | else status = STATUS_SUCCESS; |
Alexandre Julliard | 454355e | 2000-10-02 03:46:58 +0000 | [diff] [blame] | 856 | |
Alexandre Julliard | c661583 | 2001-02-14 21:45:52 +0000 | [diff] [blame] | 857 | 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 Timoshkov | 6b6596a | 2001-11-23 18:44:43 +0000 | [diff] [blame] | 863 | if (modif) *modif = *(FILETIME *)&info->LastWriteTime; |
Alexandre Julliard | 454355e | 2000-10-02 03:46:58 +0000 | [diff] [blame] | 864 | |
Alexandre Julliard | c661583 | 2001-02-14 21:45:52 +0000 | [diff] [blame] | 865 | done: |
Alexandre Julliard | 454355e | 2000-10-02 03:46:58 +0000 | [diff] [blame] | 866 | if (buf_ptr != buffer) HeapFree( GetProcessHeap(), 0, buf_ptr ); |
| 867 | return RtlNtStatusToDosError( status ); |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 868 | } |
| 869 | |
| 870 | |
| 871 | /****************************************************************************** |
James Hawkins | 6a358c4 | 2004-07-13 23:33:14 +0000 | [diff] [blame] | 872 | * RegCloseKey [ADVAPI32.@] |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 873 | * |
Jon Griffiths | 50ce084 | 2004-04-23 21:32:34 +0000 | [diff] [blame] | 874 | * Close an open registry key. |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 875 | * |
| 876 | * PARAMS |
James Hawkins | 6a358c4 | 2004-07-13 23:33:14 +0000 | [diff] [blame] | 877 | * hkey [I] Handle of key to close |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 878 | * |
| 879 | * RETURNS |
James Hawkins | 6a358c4 | 2004-07-13 23:33:14 +0000 | [diff] [blame] | 880 | * Success: ERROR_SUCCESS |
| 881 | * Failure: Error code |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 882 | */ |
| 883 | DWORD WINAPI RegCloseKey( HKEY hkey ) |
| 884 | { |
James Hawkins | e8d1e2f | 2005-02-25 16:52:10 +0000 | [diff] [blame] | 885 | if (!hkey) return ERROR_INVALID_HANDLE; |
James Hawkins | d5e2b7c | 2005-02-21 20:37:26 +0000 | [diff] [blame] | 886 | if (hkey >= (HKEY)0x80000000) return ERROR_SUCCESS; |
Alexandre Julliard | bcf393a | 2000-10-01 01:44:50 +0000 | [diff] [blame] | 887 | return RtlNtStatusToDosError( NtClose( hkey ) ); |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 888 | } |
| 889 | |
| 890 | |
| 891 | /****************************************************************************** |
James Hawkins | 6a358c4 | 2004-07-13 23:33:14 +0000 | [diff] [blame] | 892 | * RegDeleteKeyW [ADVAPI32.@] |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 893 | * |
Jon Griffiths | 50ce084 | 2004-04-23 21:32:34 +0000 | [diff] [blame] | 894 | * See RegDeleteKeyA. |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 895 | */ |
| 896 | DWORD WINAPI RegDeleteKeyW( HKEY hkey, LPCWSTR name ) |
| 897 | { |
| 898 | DWORD ret; |
Alexandre Julliard | bcf393a | 2000-10-01 01:44:50 +0000 | [diff] [blame] | 899 | HKEY tmp; |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 900 | |
James Hawkins | a9d5de8 | 2005-04-16 10:49:10 +0000 | [diff] [blame] | 901 | if (!name) return ERROR_INVALID_PARAMETER; |
| 902 | |
Alexandre Julliard | f2ef2c2 | 2002-09-13 21:42:28 +0000 | [diff] [blame] | 903 | if (!(hkey = get_special_root_hkey( hkey ))) return ERROR_INVALID_HANDLE; |
| 904 | |
Robert Shearman | 45d47c4 | 2005-05-05 16:47:33 +0000 | [diff] [blame] | 905 | if (!(ret = RegOpenKeyExW( hkey, name, 0, DELETE, &tmp ))) |
Mike McCormack | da00742 | 2002-06-14 23:35:37 +0000 | [diff] [blame] | 906 | { |
Alexandre Julliard | bcf393a | 2000-10-01 01:44:50 +0000 | [diff] [blame] | 907 | ret = RtlNtStatusToDosError( NtDeleteKey( tmp ) ); |
| 908 | RegCloseKey( tmp ); |
| 909 | } |
Mike McCormack | da00742 | 2002-06-14 23:35:37 +0000 | [diff] [blame] | 910 | TRACE("%s ret=%08lx\n", debugstr_w(name), ret); |
Alexandre Julliard | bcf393a | 2000-10-01 01:44:50 +0000 | [diff] [blame] | 911 | return ret; |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 912 | } |
| 913 | |
| 914 | |
| 915 | /****************************************************************************** |
James Hawkins | 6a358c4 | 2004-07-13 23:33:14 +0000 | [diff] [blame] | 916 | * RegDeleteKeyA [ADVAPI32.@] |
Jon Griffiths | 50ce084 | 2004-04-23 21:32:34 +0000 | [diff] [blame] | 917 | * |
| 918 | * Delete a registry key. |
| 919 | * |
| 920 | * PARAMS |
James Hawkins | 6a358c4 | 2004-07-13 23:33:14 +0000 | [diff] [blame] | 921 | * hkey [I] Handle to parent key containing the key to delete |
| 922 | * name [I] Name of the key user hkey to delete |
Jon Griffiths | 50ce084 | 2004-04-23 21:32:34 +0000 | [diff] [blame] | 923 | * |
Robert Shearman | 45d47c4 | 2005-05-05 16:47:33 +0000 | [diff] [blame] | 924 | * 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 Griffiths | 50ce084 | 2004-04-23 21:32:34 +0000 | [diff] [blame] | 929 | * RETURNS |
James Hawkins | 6a358c4 | 2004-07-13 23:33:14 +0000 | [diff] [blame] | 930 | * Success: ERROR_SUCCESS |
| 931 | * Failure: Error code |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 932 | */ |
| 933 | DWORD WINAPI RegDeleteKeyA( HKEY hkey, LPCSTR name ) |
| 934 | { |
| 935 | DWORD ret; |
Alexandre Julliard | bcf393a | 2000-10-01 01:44:50 +0000 | [diff] [blame] | 936 | HKEY tmp; |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 937 | |
James Hawkins | a9d5de8 | 2005-04-16 10:49:10 +0000 | [diff] [blame] | 938 | if (!name) return ERROR_INVALID_PARAMETER; |
| 939 | |
Alexandre Julliard | f2ef2c2 | 2002-09-13 21:42:28 +0000 | [diff] [blame] | 940 | if (!(hkey = get_special_root_hkey( hkey ))) return ERROR_INVALID_HANDLE; |
| 941 | |
Robert Shearman | 45d47c4 | 2005-05-05 16:47:33 +0000 | [diff] [blame] | 942 | if (!(ret = RegOpenKeyExA( hkey, name, 0, DELETE, &tmp ))) |
Mike McCormack | da00742 | 2002-06-14 23:35:37 +0000 | [diff] [blame] | 943 | { |
| 944 | if (!is_version_nt()) /* win95 does recursive key deletes */ |
| 945 | { |
| 946 | CHAR name[MAX_PATH]; |
| 947 | |
Francois Gouget | 9591836 | 2003-06-18 19:45:22 +0000 | [diff] [blame] | 948 | while(!RegEnumKeyA(tmp, 0, name, sizeof(name))) |
Mike McCormack | da00742 | 2002-06-14 23:35:37 +0000 | [diff] [blame] | 949 | { |
| 950 | if(RegDeleteKeyA(tmp, name)) /* recurse */ |
| 951 | break; |
| 952 | } |
| 953 | } |
Alexandre Julliard | bcf393a | 2000-10-01 01:44:50 +0000 | [diff] [blame] | 954 | ret = RtlNtStatusToDosError( NtDeleteKey( tmp ) ); |
| 955 | RegCloseKey( tmp ); |
| 956 | } |
Mike McCormack | da00742 | 2002-06-14 23:35:37 +0000 | [diff] [blame] | 957 | TRACE("%s ret=%08lx\n", debugstr_a(name), ret); |
Alexandre Julliard | bcf393a | 2000-10-01 01:44:50 +0000 | [diff] [blame] | 958 | return ret; |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 959 | } |
| 960 | |
| 961 | |
| 962 | |
| 963 | /****************************************************************************** |
James Hawkins | 6a358c4 | 2004-07-13 23:33:14 +0000 | [diff] [blame] | 964 | * RegSetValueExW [ADVAPI32.@] |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 965 | * |
Jon Griffiths | 50ce084 | 2004-04-23 21:32:34 +0000 | [diff] [blame] | 966 | * Set the data and contents of a registry value. |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 967 | * |
| 968 | * PARAMS |
James Hawkins | 6a358c4 | 2004-07-13 23:33:14 +0000 | [diff] [blame] | 969 | * 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 Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 975 | * |
| 976 | * RETURNS |
James Hawkins | 6a358c4 | 2004-07-13 23:33:14 +0000 | [diff] [blame] | 977 | * Success: ERROR_SUCCESS |
| 978 | * Failure: Error code |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 979 | */ |
| 980 | DWORD WINAPI RegSetValueExW( HKEY hkey, LPCWSTR name, DWORD reserved, |
| 981 | DWORD type, CONST BYTE *data, DWORD count ) |
| 982 | { |
Alexandre Julliard | bcf393a | 2000-10-01 01:44:50 +0000 | [diff] [blame] | 983 | UNICODE_STRING nameW; |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 984 | |
Alexandre Julliard | bba76fc | 2004-07-24 02:32:50 +0000 | [diff] [blame] | 985 | /* no need for version check, not implemented on win9x anyway */ |
| 986 | if (count && is_string(type)) |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 987 | { |
| 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 Julliard | f2ef2c2 | 2002-09-13 21:42:28 +0000 | [diff] [blame] | 993 | if (!(hkey = get_special_root_hkey( hkey ))) return ERROR_INVALID_HANDLE; |
Alexandre Julliard | a01004d | 2000-05-14 22:57:57 +0000 | [diff] [blame] | 994 | |
Alexandre Julliard | bcf393a | 2000-10-01 01:44:50 +0000 | [diff] [blame] | 995 | RtlInitUnicodeString( &nameW, name ); |
| 996 | return RtlNtStatusToDosError( NtSetValueKey( hkey, &nameW, 0, type, data, count ) ); |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 997 | } |
| 998 | |
| 999 | |
| 1000 | /****************************************************************************** |
James Hawkins | 6a358c4 | 2004-07-13 23:33:14 +0000 | [diff] [blame] | 1001 | * RegSetValueExA [ADVAPI32.@] |
| 1002 | * |
Markus Amsler | d45811c | 2005-11-04 11:43:27 +0000 | [diff] [blame] | 1003 | * See RegSetValueExW. |
Alexandre Julliard | bba76fc | 2004-07-24 02:32:50 +0000 | [diff] [blame] | 1004 | * |
| 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 Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 1008 | */ |
| 1009 | DWORD WINAPI RegSetValueExA( HKEY hkey, LPCSTR name, DWORD reserved, DWORD type, |
Alexandre Julliard | bcf393a | 2000-10-01 01:44:50 +0000 | [diff] [blame] | 1010 | CONST BYTE *data, DWORD count ) |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 1011 | { |
Alexandre Julliard | bcf393a | 2000-10-01 01:44:50 +0000 | [diff] [blame] | 1012 | ANSI_STRING nameA; |
| 1013 | WCHAR *dataW = NULL; |
| 1014 | NTSTATUS status; |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 1015 | |
Michael Cardenas | 7dbce65 | 2002-03-21 01:24:52 +0000 | [diff] [blame] | 1016 | if (!is_version_nt()) /* win95 */ |
Alexandre Julliard | 918da64 | 2001-04-10 21:30:24 +0000 | [diff] [blame] | 1017 | { |
Alexandre Julliard | bba76fc | 2004-07-24 02:32:50 +0000 | [diff] [blame] | 1018 | if (type == REG_SZ) |
| 1019 | { |
| 1020 | if (!data) return ERROR_INVALID_PARAMETER; |
Mike McCormack | 280bcf6 | 2005-08-27 10:00:38 +0000 | [diff] [blame] | 1021 | count = strlen((const char *)data) + 1; |
Alexandre Julliard | bba76fc | 2004-07-24 02:32:50 +0000 | [diff] [blame] | 1022 | } |
Alexandre Julliard | 918da64 | 2001-04-10 21:30:24 +0000 | [diff] [blame] | 1023 | } |
| 1024 | else if (count && is_string(type)) |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 1025 | { |
| 1026 | /* if user forgot to count terminating null, add it (yes NT does this) */ |
| 1027 | if (data[count-1] && !data[count]) count++; |
| 1028 | } |
Alexandre Julliard | bcf393a | 2000-10-01 01:44:50 +0000 | [diff] [blame] | 1029 | |
Alexandre Julliard | f2ef2c2 | 2002-09-13 21:42:28 +0000 | [diff] [blame] | 1030 | if (!(hkey = get_special_root_hkey( hkey ))) return ERROR_INVALID_HANDLE; |
| 1031 | |
Alexandre Julliard | a01004d | 2000-05-14 22:57:57 +0000 | [diff] [blame] | 1032 | if (is_string( type )) /* need to convert to Unicode */ |
Alexandre Julliard | a01004d | 2000-05-14 22:57:57 +0000 | [diff] [blame] | 1033 | { |
Alexandre Julliard | 60fd03d | 2001-12-05 22:18:48 +0000 | [diff] [blame] | 1034 | DWORD lenW; |
Mike McCormack | 280bcf6 | 2005-08-27 10:00:38 +0000 | [diff] [blame] | 1035 | RtlMultiByteToUnicodeSize( &lenW, (const char *)data, count ); |
Alexandre Julliard | 60fd03d | 2001-12-05 22:18:48 +0000 | [diff] [blame] | 1036 | if (!(dataW = HeapAlloc( GetProcessHeap(), 0, lenW ))) return ERROR_OUTOFMEMORY; |
Mike McCormack | 280bcf6 | 2005-08-27 10:00:38 +0000 | [diff] [blame] | 1037 | RtlMultiByteToUnicodeN( dataW, lenW, NULL, (const char *)data, count ); |
Alexandre Julliard | 60fd03d | 2001-12-05 22:18:48 +0000 | [diff] [blame] | 1038 | count = lenW; |
Alexandre Julliard | bcf393a | 2000-10-01 01:44:50 +0000 | [diff] [blame] | 1039 | data = (BYTE *)dataW; |
Alexandre Julliard | a01004d | 2000-05-14 22:57:57 +0000 | [diff] [blame] | 1040 | } |
Alexandre Julliard | bcf393a | 2000-10-01 01:44:50 +0000 | [diff] [blame] | 1041 | |
| 1042 | RtlInitAnsiString( &nameA, name ); |
Alexandre Julliard | ab5e975 | 2001-03-23 19:12:01 +0000 | [diff] [blame] | 1043 | if (!(status = RtlAnsiStringToUnicodeString( &NtCurrentTeb()->StaticUnicodeString, |
| 1044 | &nameA, FALSE ))) |
Alexandre Julliard | bcf393a | 2000-10-01 01:44:50 +0000 | [diff] [blame] | 1045 | { |
Alexandre Julliard | ab5e975 | 2001-03-23 19:12:01 +0000 | [diff] [blame] | 1046 | status = NtSetValueKey( hkey, &NtCurrentTeb()->StaticUnicodeString, 0, type, data, count ); |
Alexandre Julliard | bcf393a | 2000-10-01 01:44:50 +0000 | [diff] [blame] | 1047 | } |
Michael Stefaniuc | 5ad7d85 | 2004-12-23 17:06:43 +0000 | [diff] [blame] | 1048 | HeapFree( GetProcessHeap(), 0, dataW ); |
Alexandre Julliard | bcf393a | 2000-10-01 01:44:50 +0000 | [diff] [blame] | 1049 | return RtlNtStatusToDosError( status ); |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 1050 | } |
| 1051 | |
| 1052 | |
| 1053 | /****************************************************************************** |
James Hawkins | 6a358c4 | 2004-07-13 23:33:14 +0000 | [diff] [blame] | 1054 | * 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 Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 1068 | */ |
| 1069 | DWORD WINAPI RegSetValueW( HKEY hkey, LPCWSTR name, DWORD type, LPCWSTR data, DWORD count ) |
| 1070 | { |
| 1071 | HKEY subkey = hkey; |
| 1072 | DWORD ret; |
| 1073 | |
Michael Stefaniuc | cbacde5 | 2002-10-25 19:17:33 +0000 | [diff] [blame] | 1074 | TRACE("(%p,%s,%ld,%s,%ld)\n", hkey, debugstr_w(name), type, debugstr_w(data), count ); |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 1075 | |
| 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 Pouech | 0a25896 | 2004-11-30 21:38:57 +0000 | [diff] [blame] | 1083 | ret = RegSetValueExW( subkey, NULL, 0, REG_SZ, (const BYTE*)data, |
Alexandre Julliard | c7e7df8 | 2000-08-14 14:41:19 +0000 | [diff] [blame] | 1084 | (strlenW( data ) + 1) * sizeof(WCHAR) ); |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 1085 | if (subkey != hkey) RegCloseKey( subkey ); |
| 1086 | return ret; |
| 1087 | } |
| 1088 | |
| 1089 | |
| 1090 | /****************************************************************************** |
James Hawkins | 6a358c4 | 2004-07-13 23:33:14 +0000 | [diff] [blame] | 1091 | * RegSetValueA [ADVAPI32.@] |
| 1092 | * |
Markus Amsler | d45811c | 2005-11-04 11:43:27 +0000 | [diff] [blame] | 1093 | * See RegSetValueW. |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 1094 | */ |
| 1095 | DWORD WINAPI RegSetValueA( HKEY hkey, LPCSTR name, DWORD type, LPCSTR data, DWORD count ) |
| 1096 | { |
| 1097 | HKEY subkey = hkey; |
| 1098 | DWORD ret; |
| 1099 | |
Michael Stefaniuc | cbacde5 | 2002-10-25 19:17:33 +0000 | [diff] [blame] | 1100 | TRACE("(%p,%s,%ld,%s,%ld)\n", hkey, debugstr_a(name), type, debugstr_a(data), count ); |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 1101 | |
| 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 Pouech | 0a25896 | 2004-11-30 21:38:57 +0000 | [diff] [blame] | 1108 | ret = RegSetValueExA( subkey, NULL, 0, REG_SZ, (const BYTE*)data, strlen(data)+1 ); |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 1109 | if (subkey != hkey) RegCloseKey( subkey ); |
| 1110 | return ret; |
| 1111 | } |
| 1112 | |
| 1113 | |
| 1114 | |
| 1115 | /****************************************************************************** |
James Hawkins | 6a358c4 | 2004-07-13 23:33:14 +0000 | [diff] [blame] | 1116 | * RegQueryValueExW [ADVAPI32.@] |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 1117 | * |
Jon Griffiths | 50ce084 | 2004-04-23 21:32:34 +0000 | [diff] [blame] | 1118 | * See RegQueryValueExA. |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 1119 | */ |
| 1120 | DWORD WINAPI RegQueryValueExW( HKEY hkey, LPCWSTR name, LPDWORD reserved, LPDWORD type, |
Alexandre Julliard | bcf393a | 2000-10-01 01:44:50 +0000 | [diff] [blame] | 1121 | LPBYTE data, LPDWORD count ) |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 1122 | { |
Alexandre Julliard | bcf393a | 2000-10-01 01:44:50 +0000 | [diff] [blame] | 1123 | NTSTATUS status; |
| 1124 | UNICODE_STRING name_str; |
| 1125 | DWORD total_size; |
Alexandre Julliard | 454355e | 2000-10-02 03:46:58 +0000 | [diff] [blame] | 1126 | char buffer[256], *buf_ptr = buffer; |
Alexandre Julliard | bcf393a | 2000-10-01 01:44:50 +0000 | [diff] [blame] | 1127 | KEY_VALUE_PARTIAL_INFORMATION *info = (KEY_VALUE_PARTIAL_INFORMATION *)buffer; |
Alexandre Julliard | a010932 | 2002-07-05 21:30:38 +0000 | [diff] [blame] | 1128 | static const int info_size = offsetof( KEY_VALUE_PARTIAL_INFORMATION, Data ); |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 1129 | |
Michael Stefaniuc | cbacde5 | 2002-10-25 19:17:33 +0000 | [diff] [blame] | 1130 | TRACE("(%p,%s,%p,%p,%p,%p=%ld)\n", |
Francois Gouget | 8f63a71 | 2003-12-13 01:34:40 +0000 | [diff] [blame] | 1131 | hkey, debugstr_w(name), reserved, type, data, count, |
| 1132 | (count && data) ? *count : 0 ); |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 1133 | |
Eric Pouech | 2c655f5 | 1999-11-25 22:05:46 +0000 | [diff] [blame] | 1134 | if ((data && !count) || reserved) return ERROR_INVALID_PARAMETER; |
Alexandre Julliard | f2ef2c2 | 2002-09-13 21:42:28 +0000 | [diff] [blame] | 1135 | if (!(hkey = get_special_root_hkey( hkey ))) return ERROR_INVALID_HANDLE; |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 1136 | |
Alexandre Julliard | bcf393a | 2000-10-01 01:44:50 +0000 | [diff] [blame] | 1137 | 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 Julliard | a01004d | 2000-05-14 22:57:57 +0000 | [diff] [blame] | 1145 | |
| 1146 | if (data) |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 1147 | { |
Alexandre Julliard | bcf393a | 2000-10-01 01:44:50 +0000 | [diff] [blame] | 1148 | /* retry with a dynamically allocated buffer */ |
| 1149 | while (status == STATUS_BUFFER_OVERFLOW && total_size - info_size <= *count) |
Alexandre Julliard | a01004d | 2000-05-14 22:57:57 +0000 | [diff] [blame] | 1150 | { |
Alexandre Julliard | bcf393a | 2000-10-01 01:44:50 +0000 | [diff] [blame] | 1151 | if (buf_ptr != buffer) HeapFree( GetProcessHeap(), 0, buf_ptr ); |
| 1152 | if (!(buf_ptr = HeapAlloc( GetProcessHeap(), 0, total_size ))) |
Alexandre Julliard | 454355e | 2000-10-02 03:46:58 +0000 | [diff] [blame] | 1153 | 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 Julliard | bcf393a | 2000-10-01 01:44:50 +0000 | [diff] [blame] | 1157 | } |
| 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 Julliard | a01004d | 2000-05-14 22:57:57 +0000 | [diff] [blame] | 1165 | { |
Alexandre Julliard | bcf393a | 2000-10-01 01:44:50 +0000 | [diff] [blame] | 1166 | WCHAR *ptr = (WCHAR *)(data + total_size - info_size); |
| 1167 | if (ptr > (WCHAR *)data && ptr[-1]) *ptr = 0; |
Alexandre Julliard | a01004d | 2000-05-14 22:57:57 +0000 | [diff] [blame] | 1168 | } |
| 1169 | } |
Alexandre Julliard | 454355e | 2000-10-02 03:46:58 +0000 | [diff] [blame] | 1170 | else if (status != STATUS_BUFFER_OVERFLOW) goto done; |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 1171 | } |
Alexandre Julliard | c661583 | 2001-02-14 21:45:52 +0000 | [diff] [blame] | 1172 | else status = STATUS_SUCCESS; |
Alexandre Julliard | bcf393a | 2000-10-01 01:44:50 +0000 | [diff] [blame] | 1173 | |
| 1174 | if (type) *type = info->Type; |
| 1175 | if (count) *count = total_size - info_size; |
| 1176 | |
| 1177 | done: |
Alexandre Julliard | 454355e | 2000-10-02 03:46:58 +0000 | [diff] [blame] | 1178 | if (buf_ptr != buffer) HeapFree( GetProcessHeap(), 0, buf_ptr ); |
Alexandre Julliard | bcf393a | 2000-10-01 01:44:50 +0000 | [diff] [blame] | 1179 | return RtlNtStatusToDosError(status); |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 1180 | } |
| 1181 | |
| 1182 | |
| 1183 | /****************************************************************************** |
James Hawkins | 6a358c4 | 2004-07-13 23:33:14 +0000 | [diff] [blame] | 1184 | * RegQueryValueExA [ADVAPI32.@] |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 1185 | * |
Jon Griffiths | 50ce084 | 2004-04-23 21:32:34 +0000 | [diff] [blame] | 1186 | * Get the type and contents of a specified value under with a key. |
| 1187 | * |
| 1188 | * PARAMS |
James Hawkins | 6a358c4 | 2004-07-13 23:33:14 +0000 | [diff] [blame] | 1189 | * 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 Griffiths | 50ce084 | 2004-04-23 21:32:34 +0000 | [diff] [blame] | 1195 | * |
| 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 Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 1205 | */ |
| 1206 | DWORD WINAPI RegQueryValueExA( HKEY hkey, LPCSTR name, LPDWORD reserved, LPDWORD type, |
Alexandre Julliard | bcf393a | 2000-10-01 01:44:50 +0000 | [diff] [blame] | 1207 | LPBYTE data, LPDWORD count ) |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 1208 | { |
Alexandre Julliard | bcf393a | 2000-10-01 01:44:50 +0000 | [diff] [blame] | 1209 | NTSTATUS status; |
| 1210 | ANSI_STRING nameA; |
Alexandre Julliard | bcf393a | 2000-10-01 01:44:50 +0000 | [diff] [blame] | 1211 | DWORD total_size; |
Alexandre Julliard | 454355e | 2000-10-02 03:46:58 +0000 | [diff] [blame] | 1212 | char buffer[256], *buf_ptr = buffer; |
Alexandre Julliard | bcf393a | 2000-10-01 01:44:50 +0000 | [diff] [blame] | 1213 | KEY_VALUE_PARTIAL_INFORMATION *info = (KEY_VALUE_PARTIAL_INFORMATION *)buffer; |
Alexandre Julliard | a010932 | 2002-07-05 21:30:38 +0000 | [diff] [blame] | 1214 | static const int info_size = offsetof( KEY_VALUE_PARTIAL_INFORMATION, Data ); |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 1215 | |
Michael Stefaniuc | cbacde5 | 2002-10-25 19:17:33 +0000 | [diff] [blame] | 1216 | TRACE("(%p,%s,%p,%p,%p,%p=%ld)\n", |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 1217 | hkey, debugstr_a(name), reserved, type, data, count, count ? *count : 0 ); |
| 1218 | |
Eric Pouech | 2c655f5 | 1999-11-25 22:05:46 +0000 | [diff] [blame] | 1219 | if ((data && !count) || reserved) return ERROR_INVALID_PARAMETER; |
Alexandre Julliard | f2ef2c2 | 2002-09-13 21:42:28 +0000 | [diff] [blame] | 1220 | if (!(hkey = get_special_root_hkey( hkey ))) return ERROR_INVALID_HANDLE; |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 1221 | |
Alexandre Julliard | bcf393a | 2000-10-01 01:44:50 +0000 | [diff] [blame] | 1222 | RtlInitAnsiString( &nameA, name ); |
Alexandre Julliard | ab5e975 | 2001-03-23 19:12:01 +0000 | [diff] [blame] | 1223 | if ((status = RtlAnsiStringToUnicodeString( &NtCurrentTeb()->StaticUnicodeString, |
| 1224 | &nameA, FALSE ))) |
Alexandre Julliard | 454355e | 2000-10-02 03:46:58 +0000 | [diff] [blame] | 1225 | return RtlNtStatusToDosError(status); |
Alexandre Julliard | a01004d | 2000-05-14 22:57:57 +0000 | [diff] [blame] | 1226 | |
Alexandre Julliard | ab5e975 | 2001-03-23 19:12:01 +0000 | [diff] [blame] | 1227 | status = NtQueryValueKey( hkey, &NtCurrentTeb()->StaticUnicodeString, |
| 1228 | KeyValuePartialInformation, buffer, sizeof(buffer), &total_size ); |
Alexandre Julliard | bcf393a | 2000-10-01 01:44:50 +0000 | [diff] [blame] | 1229 | if (status && status != STATUS_BUFFER_OVERFLOW) goto done; |
Alexandre Julliard | a01004d | 2000-05-14 22:57:57 +0000 | [diff] [blame] | 1230 | |
Alexandre Julliard | bcf393a | 2000-10-01 01:44:50 +0000 | [diff] [blame] | 1231 | /* 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 Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 1234 | { |
Alexandre Julliard | bcf393a | 2000-10-01 01:44:50 +0000 | [diff] [blame] | 1235 | /* retry with a dynamically allocated buffer */ |
| 1236 | while (status == STATUS_BUFFER_OVERFLOW) |
Alexandre Julliard | a01004d | 2000-05-14 22:57:57 +0000 | [diff] [blame] | 1237 | { |
Alexandre Julliard | bcf393a | 2000-10-01 01:44:50 +0000 | [diff] [blame] | 1238 | if (buf_ptr != buffer) HeapFree( GetProcessHeap(), 0, buf_ptr ); |
| 1239 | if (!(buf_ptr = HeapAlloc( GetProcessHeap(), 0, total_size ))) |
Alexandre Julliard | 454355e | 2000-10-02 03:46:58 +0000 | [diff] [blame] | 1240 | { |
Alexandre Julliard | bcf393a | 2000-10-01 01:44:50 +0000 | [diff] [blame] | 1241 | status = STATUS_NO_MEMORY; |
Alexandre Julliard | 454355e | 2000-10-02 03:46:58 +0000 | [diff] [blame] | 1242 | goto done; |
| 1243 | } |
| 1244 | info = (KEY_VALUE_PARTIAL_INFORMATION *)buf_ptr; |
Alexandre Julliard | ab5e975 | 2001-03-23 19:12:01 +0000 | [diff] [blame] | 1245 | status = NtQueryValueKey( hkey, &NtCurrentTeb()->StaticUnicodeString, |
| 1246 | KeyValuePartialInformation, buf_ptr, total_size, &total_size ); |
Alexandre Julliard | bcf393a | 2000-10-01 01:44:50 +0000 | [diff] [blame] | 1247 | } |
| 1248 | |
Alexandre Julliard | c661583 | 2001-02-14 21:45:52 +0000 | [diff] [blame] | 1249 | if (status) goto done; |
| 1250 | |
| 1251 | if (is_string(info->Type)) |
Alexandre Julliard | bcf393a | 2000-10-01 01:44:50 +0000 | [diff] [blame] | 1252 | { |
Alexandre Julliard | 60fd03d | 2001-12-05 22:18:48 +0000 | [diff] [blame] | 1253 | DWORD len; |
| 1254 | |
| 1255 | RtlUnicodeToMultiByteSize( &len, (WCHAR *)(buf_ptr + info_size), |
| 1256 | total_size - info_size ); |
Alexandre Julliard | c661583 | 2001-02-14 21:45:52 +0000 | [diff] [blame] | 1257 | if (data && len) |
Alexandre Julliard | 57f05e1 | 2000-10-15 00:40:25 +0000 | [diff] [blame] | 1258 | { |
Alexandre Julliard | c661583 | 2001-02-14 21:45:52 +0000 | [diff] [blame] | 1259 | if (len > *count) status = STATUS_BUFFER_OVERFLOW; |
| 1260 | else |
| 1261 | { |
Mike McCormack | 280bcf6 | 2005-08-27 10:00:38 +0000 | [diff] [blame] | 1262 | RtlUnicodeToMultiByteN( (char*)data, len, NULL, (WCHAR *)(buf_ptr + info_size), |
Alexandre Julliard | 60fd03d | 2001-12-05 22:18:48 +0000 | [diff] [blame] | 1263 | total_size - info_size ); |
Alexandre Julliard | c661583 | 2001-02-14 21:45:52 +0000 | [diff] [blame] | 1264 | /* 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 Julliard | 57f05e1 | 2000-10-15 00:40:25 +0000 | [diff] [blame] | 1268 | } |
Alexandre Julliard | c661583 | 2001-02-14 21:45:52 +0000 | [diff] [blame] | 1269 | total_size = len + info_size; |
Alexandre Julliard | a01004d | 2000-05-14 22:57:57 +0000 | [diff] [blame] | 1270 | } |
Alexandre Julliard | c661583 | 2001-02-14 21:45:52 +0000 | [diff] [blame] | 1271 | 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 Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 1276 | } |
Alexandre Julliard | c661583 | 2001-02-14 21:45:52 +0000 | [diff] [blame] | 1277 | else status = STATUS_SUCCESS; |
Alexandre Julliard | a01004d | 2000-05-14 22:57:57 +0000 | [diff] [blame] | 1278 | |
Alexandre Julliard | bcf393a | 2000-10-01 01:44:50 +0000 | [diff] [blame] | 1279 | if (type) *type = info->Type; |
| 1280 | if (count) *count = total_size - info_size; |
Alexandre Julliard | bcf393a | 2000-10-01 01:44:50 +0000 | [diff] [blame] | 1281 | |
| 1282 | done: |
Alexandre Julliard | 454355e | 2000-10-02 03:46:58 +0000 | [diff] [blame] | 1283 | if (buf_ptr != buffer) HeapFree( GetProcessHeap(), 0, buf_ptr ); |
Alexandre Julliard | bcf393a | 2000-10-01 01:44:50 +0000 | [diff] [blame] | 1284 | return RtlNtStatusToDosError(status); |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 1285 | } |
| 1286 | |
| 1287 | |
| 1288 | /****************************************************************************** |
James Hawkins | 6a358c4 | 2004-07-13 23:33:14 +0000 | [diff] [blame] | 1289 | * RegQueryValueW [ADVAPI32.@] |
| 1290 | * |
| 1291 | * Retrieves the data associated with the default or unnamed value of a key. |
| 1292 | * |
| 1293 | * PARAMS |
Alexandre Julliard | bbde53f | 2004-10-19 21:14:09 +0000 | [diff] [blame] | 1294 | * 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 Hawkins | 6a358c4 | 2004-07-13 23:33:14 +0000 | [diff] [blame] | 1297 | * of the key. |
Alexandre Julliard | bbde53f | 2004-10-19 21:14:09 +0000 | [diff] [blame] | 1298 | * count [I/O] Size of lpValue in bytes. |
James Hawkins | 6a358c4 | 2004-07-13 23:33:14 +0000 | [diff] [blame] | 1299 | * |
| 1300 | * RETURNS |
| 1301 | * Success: ERROR_SUCCESS |
| 1302 | * Failure: nonzero error code from Winerror.h |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 1303 | */ |
| 1304 | DWORD WINAPI RegQueryValueW( HKEY hkey, LPCWSTR name, LPWSTR data, LPLONG count ) |
| 1305 | { |
| 1306 | DWORD ret; |
| 1307 | HKEY subkey = hkey; |
| 1308 | |
Michael Stefaniuc | cbacde5 | 2002-10-25 19:17:33 +0000 | [diff] [blame] | 1309 | TRACE("(%p,%s,%p,%ld)\n", hkey, debugstr_w(name), data, count ? *count : 0 ); |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 1310 | |
| 1311 | if (name && name[0]) |
| 1312 | { |
| 1313 | if ((ret = RegOpenKeyW( hkey, name, &subkey )) != ERROR_SUCCESS) return ret; |
| 1314 | } |
Mike McCormack | 280bcf6 | 2005-08-27 10:00:38 +0000 | [diff] [blame] | 1315 | ret = RegQueryValueExW( subkey, NULL, NULL, NULL, (LPBYTE)data, (LPDWORD)count ); |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 1316 | 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 Julliard | bbde53f | 2004-10-19 21:14:09 +0000 | [diff] [blame] | 1321 | if (count) *count = sizeof(WCHAR); |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 1322 | ret = ERROR_SUCCESS; |
| 1323 | } |
| 1324 | return ret; |
| 1325 | } |
| 1326 | |
| 1327 | |
| 1328 | /****************************************************************************** |
James Hawkins | 6a358c4 | 2004-07-13 23:33:14 +0000 | [diff] [blame] | 1329 | * RegQueryValueA [ADVAPI32.@] |
| 1330 | * |
Markus Amsler | d45811c | 2005-11-04 11:43:27 +0000 | [diff] [blame] | 1331 | * See RegQueryValueW. |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 1332 | */ |
| 1333 | DWORD WINAPI RegQueryValueA( HKEY hkey, LPCSTR name, LPSTR data, LPLONG count ) |
| 1334 | { |
| 1335 | DWORD ret; |
| 1336 | HKEY subkey = hkey; |
| 1337 | |
Michael Stefaniuc | cbacde5 | 2002-10-25 19:17:33 +0000 | [diff] [blame] | 1338 | TRACE("(%p,%s,%p,%ld)\n", hkey, debugstr_a(name), data, count ? *count : 0 ); |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 1339 | |
| 1340 | if (name && name[0]) |
| 1341 | { |
| 1342 | if ((ret = RegOpenKeyA( hkey, name, &subkey )) != ERROR_SUCCESS) return ret; |
| 1343 | } |
Mike McCormack | 280bcf6 | 2005-08-27 10:00:38 +0000 | [diff] [blame] | 1344 | ret = RegQueryValueExA( subkey, NULL, NULL, NULL, (LPBYTE)data, (LPDWORD)count ); |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 1345 | 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 Nawothnig | 48533ae | 2005-07-18 15:10:22 +0000 | [diff] [blame] | 1358 | * ADVAPI_ApplyRestrictions [internal] |
| 1359 | * |
| 1360 | * Helper function for RegGetValueA/W. |
| 1361 | */ |
| 1362 | VOID 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 | */ |
| 1428 | LONG 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 | */ |
| 1520 | LONG 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 Hawkins | 6a358c4 | 2004-07-13 23:33:14 +0000 | [diff] [blame] | 1608 | * RegEnumValueW [ADVAPI32.@] |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 1609 | * |
Markus Amsler | d45811c | 2005-11-04 11:43:27 +0000 | [diff] [blame] | 1610 | * Enumerates the values for the specified open registry key. |
| 1611 | * |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 1612 | * PARAMS |
James Hawkins | 6a358c4 | 2004-07-13 23:33:14 +0000 | [diff] [blame] | 1613 | * 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 Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 1625 | */ |
| 1626 | |
| 1627 | DWORD WINAPI RegEnumValueW( HKEY hkey, DWORD index, LPWSTR value, LPDWORD val_count, |
| 1628 | LPDWORD reserved, LPDWORD type, LPBYTE data, LPDWORD count ) |
| 1629 | { |
Alexandre Julliard | 0b6a79c | 2000-12-15 20:57:00 +0000 | [diff] [blame] | 1630 | 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 Julliard | a010932 | 2002-07-05 21:30:38 +0000 | [diff] [blame] | 1634 | static const int info_size = offsetof( KEY_VALUE_FULL_INFORMATION, Name ); |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 1635 | |
Michael Stefaniuc | cbacde5 | 2002-10-25 19:17:33 +0000 | [diff] [blame] | 1636 | TRACE("(%p,%ld,%p,%p,%p,%p,%p,%p)\n", |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 1637 | hkey, index, value, val_count, reserved, type, data, count ); |
| 1638 | |
| 1639 | /* NT only checks count, not val_count */ |
Eric Pouech | 2c655f5 | 1999-11-25 22:05:46 +0000 | [diff] [blame] | 1640 | if ((data && !count) || reserved) return ERROR_INVALID_PARAMETER; |
Alexandre Julliard | f2ef2c2 | 2002-09-13 21:42:28 +0000 | [diff] [blame] | 1641 | if (!(hkey = get_special_root_hkey( hkey ))) return ERROR_INVALID_HANDLE; |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 1642 | |
Alexandre Julliard | 0b6a79c | 2000-12-15 20:57:00 +0000 | [diff] [blame] | 1643 | total_size = info_size + (MAX_PATH + 1) * sizeof(WCHAR); |
| 1644 | if (data) total_size += *count; |
| 1645 | total_size = min( sizeof(buffer), total_size ); |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 1646 | |
Alexandre Julliard | 0b6a79c | 2000-12-15 20:57:00 +0000 | [diff] [blame] | 1647 | status = NtEnumerateValueKey( hkey, index, KeyValueFullInformation, |
| 1648 | buffer, total_size, &total_size ); |
| 1649 | if (status && status != STATUS_BUFFER_OVERFLOW) goto done; |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 1650 | |
Alexandre Julliard | 0b6a79c | 2000-12-15 20:57:00 +0000 | [diff] [blame] | 1651 | if (value || data) |
Alexandre Julliard | a01004d | 2000-05-14 22:57:57 +0000 | [diff] [blame] | 1652 | { |
Alexandre Julliard | 0b6a79c | 2000-12-15 20:57:00 +0000 | [diff] [blame] | 1653 | /* retry with a dynamically allocated buffer */ |
| 1654 | while (status == STATUS_BUFFER_OVERFLOW) |
Alexandre Julliard | a01004d | 2000-05-14 22:57:57 +0000 | [diff] [blame] | 1655 | { |
Alexandre Julliard | 0b6a79c | 2000-12-15 20:57:00 +0000 | [diff] [blame] | 1656 | 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 Julliard | a01004d | 2000-05-14 22:57:57 +0000 | [diff] [blame] | 1669 | { |
Alexandre Julliard | 0b6a79c | 2000-12-15 20:57:00 +0000 | [diff] [blame] | 1670 | status = STATUS_BUFFER_OVERFLOW; |
Alexandre Julliard | c1dddbe | 2002-07-10 03:27:35 +0000 | [diff] [blame] | 1671 | goto overflow; |
Alexandre Julliard | 0b6a79c | 2000-12-15 20:57:00 +0000 | [diff] [blame] | 1672 | } |
| 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 Julliard | c1dddbe | 2002-07-10 03:27:35 +0000 | [diff] [blame] | 1683 | goto overflow; |
Alexandre Julliard | 0b6a79c | 2000-12-15 20:57:00 +0000 | [diff] [blame] | 1684 | } |
| 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 Julliard | a01004d | 2000-05-14 22:57:57 +0000 | [diff] [blame] | 1692 | } |
| 1693 | } |
Alexandre Julliard | a01004d | 2000-05-14 22:57:57 +0000 | [diff] [blame] | 1694 | } |
Alexandre Julliard | c661583 | 2001-02-14 21:45:52 +0000 | [diff] [blame] | 1695 | else status = STATUS_SUCCESS; |
Alexandre Julliard | 0b6a79c | 2000-12-15 20:57:00 +0000 | [diff] [blame] | 1696 | |
Alexandre Julliard | c1dddbe | 2002-07-10 03:27:35 +0000 | [diff] [blame] | 1697 | overflow: |
Alexandre Julliard | 0b6a79c | 2000-12-15 20:57:00 +0000 | [diff] [blame] | 1698 | 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 Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 1704 | } |
| 1705 | |
| 1706 | |
| 1707 | /****************************************************************************** |
James Hawkins | 6a358c4 | 2004-07-13 23:33:14 +0000 | [diff] [blame] | 1708 | * RegEnumValueA [ADVAPI32.@] |
| 1709 | * |
Markus Amsler | d45811c | 2005-11-04 11:43:27 +0000 | [diff] [blame] | 1710 | * See RegEnumValueW. |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 1711 | */ |
| 1712 | DWORD WINAPI RegEnumValueA( HKEY hkey, DWORD index, LPSTR value, LPDWORD val_count, |
| 1713 | LPDWORD reserved, LPDWORD type, LPBYTE data, LPDWORD count ) |
| 1714 | { |
Alexandre Julliard | 0b6a79c | 2000-12-15 20:57:00 +0000 | [diff] [blame] | 1715 | 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 Julliard | a010932 | 2002-07-05 21:30:38 +0000 | [diff] [blame] | 1719 | static const int info_size = offsetof( KEY_VALUE_FULL_INFORMATION, Name ); |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 1720 | |
Michael Stefaniuc | cbacde5 | 2002-10-25 19:17:33 +0000 | [diff] [blame] | 1721 | TRACE("(%p,%ld,%p,%p,%p,%p,%p,%p)\n", |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 1722 | hkey, index, value, val_count, reserved, type, data, count ); |
| 1723 | |
| 1724 | /* NT only checks count, not val_count */ |
Eric Pouech | 2c655f5 | 1999-11-25 22:05:46 +0000 | [diff] [blame] | 1725 | if ((data && !count) || reserved) return ERROR_INVALID_PARAMETER; |
Alexandre Julliard | f2ef2c2 | 2002-09-13 21:42:28 +0000 | [diff] [blame] | 1726 | if (!(hkey = get_special_root_hkey( hkey ))) return ERROR_INVALID_HANDLE; |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 1727 | |
Alexandre Julliard | 0b6a79c | 2000-12-15 20:57:00 +0000 | [diff] [blame] | 1728 | total_size = info_size + (MAX_PATH + 1) * sizeof(WCHAR); |
| 1729 | if (data) total_size += *count; |
| 1730 | total_size = min( sizeof(buffer), total_size ); |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 1731 | |
Alexandre Julliard | 0b6a79c | 2000-12-15 20:57:00 +0000 | [diff] [blame] | 1732 | status = NtEnumerateValueKey( hkey, index, KeyValueFullInformation, |
| 1733 | buffer, total_size, &total_size ); |
| 1734 | if (status && status != STATUS_BUFFER_OVERFLOW) goto done; |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 1735 | |
Alexandre Julliard | 0b6a79c | 2000-12-15 20:57:00 +0000 | [diff] [blame] | 1736 | /* 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 Julliard | a01004d | 2000-05-14 22:57:57 +0000 | [diff] [blame] | 1739 | { |
Alexandre Julliard | 0b6a79c | 2000-12-15 20:57:00 +0000 | [diff] [blame] | 1740 | /* retry with a dynamically allocated buffer */ |
| 1741 | while (status == STATUS_BUFFER_OVERFLOW) |
Alexandre Julliard | a01004d | 2000-05-14 22:57:57 +0000 | [diff] [blame] | 1742 | { |
Alexandre Julliard | 0b6a79c | 2000-12-15 20:57:00 +0000 | [diff] [blame] | 1743 | 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 Julliard | a01004d | 2000-05-14 22:57:57 +0000 | [diff] [blame] | 1749 | } |
Alexandre Julliard | 0b6a79c | 2000-12-15 20:57:00 +0000 | [diff] [blame] | 1750 | |
| 1751 | if (status) goto done; |
| 1752 | |
Alexandre Julliard | 0b6a79c | 2000-12-15 20:57:00 +0000 | [diff] [blame] | 1753 | if (is_string(info->Type)) |
| 1754 | { |
Alexandre Julliard | 60fd03d | 2001-12-05 22:18:48 +0000 | [diff] [blame] | 1755 | DWORD len; |
| 1756 | RtlUnicodeToMultiByteSize( &len, (WCHAR *)(buf_ptr + info->DataOffset), |
| 1757 | total_size - info->DataOffset ); |
Alexandre Julliard | 0b6a79c | 2000-12-15 20:57:00 +0000 | [diff] [blame] | 1758 | if (data && len) |
| 1759 | { |
Alexandre Julliard | c1dddbe | 2002-07-10 03:27:35 +0000 | [diff] [blame] | 1760 | if (len > *count) status = STATUS_BUFFER_OVERFLOW; |
| 1761 | else |
Alexandre Julliard | 0b6a79c | 2000-12-15 20:57:00 +0000 | [diff] [blame] | 1762 | { |
Mike McCormack | 280bcf6 | 2005-08-27 10:00:38 +0000 | [diff] [blame] | 1763 | RtlUnicodeToMultiByteN( (char*)data, len, NULL, (WCHAR *)(buf_ptr + info->DataOffset), |
Alexandre Julliard | c1dddbe | 2002-07-10 03:27:35 +0000 | [diff] [blame] | 1764 | 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 Julliard | 0b6a79c | 2000-12-15 20:57:00 +0000 | [diff] [blame] | 1768 | } |
Alexandre Julliard | 0b6a79c | 2000-12-15 20:57:00 +0000 | [diff] [blame] | 1769 | } |
| 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 Julliard | c1dddbe | 2002-07-10 03:27:35 +0000 | [diff] [blame] | 1777 | |
| 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 Julliard | a01004d | 2000-05-14 22:57:57 +0000 | [diff] [blame] | 1800 | } |
Alexandre Julliard | c661583 | 2001-02-14 21:45:52 +0000 | [diff] [blame] | 1801 | else status = STATUS_SUCCESS; |
Alexandre Julliard | a01004d | 2000-05-14 22:57:57 +0000 | [diff] [blame] | 1802 | |
Alexandre Julliard | 0b6a79c | 2000-12-15 20:57:00 +0000 | [diff] [blame] | 1803 | 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 Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 1809 | } |
| 1810 | |
| 1811 | |
| 1812 | |
| 1813 | /****************************************************************************** |
James Hawkins | 6a358c4 | 2004-07-13 23:33:14 +0000 | [diff] [blame] | 1814 | * RegDeleteValueW [ADVAPI32.@] |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 1815 | * |
Jon Griffiths | cd4234a | 2003-03-18 18:35:48 +0000 | [diff] [blame] | 1816 | * See RegDeleteValueA. |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 1817 | */ |
| 1818 | DWORD WINAPI RegDeleteValueW( HKEY hkey, LPCWSTR name ) |
| 1819 | { |
Alexandre Julliard | bcf393a | 2000-10-01 01:44:50 +0000 | [diff] [blame] | 1820 | UNICODE_STRING nameW; |
Alexandre Julliard | f2ef2c2 | 2002-09-13 21:42:28 +0000 | [diff] [blame] | 1821 | |
| 1822 | if (!(hkey = get_special_root_hkey( hkey ))) return ERROR_INVALID_HANDLE; |
| 1823 | |
Alexandre Julliard | bcf393a | 2000-10-01 01:44:50 +0000 | [diff] [blame] | 1824 | RtlInitUnicodeString( &nameW, name ); |
| 1825 | return RtlNtStatusToDosError( NtDeleteValueKey( hkey, &nameW ) ); |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 1826 | } |
| 1827 | |
| 1828 | |
| 1829 | /****************************************************************************** |
James Hawkins | 6a358c4 | 2004-07-13 23:33:14 +0000 | [diff] [blame] | 1830 | * RegDeleteValueA [ADVAPI32.@] |
Jon Griffiths | cd4234a | 2003-03-18 18:35:48 +0000 | [diff] [blame] | 1831 | * |
| 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 Hawkins | 6a358c4 | 2004-07-13 23:33:14 +0000 | [diff] [blame] | 1839 | * Success: ERROR_SUCCESS |
| 1840 | * Failure: nonzero error code from Winerror.h |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 1841 | */ |
| 1842 | DWORD WINAPI RegDeleteValueA( HKEY hkey, LPCSTR name ) |
| 1843 | { |
Alexandre Julliard | bcf393a | 2000-10-01 01:44:50 +0000 | [diff] [blame] | 1844 | STRING nameA; |
| 1845 | NTSTATUS status; |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 1846 | |
Alexandre Julliard | f2ef2c2 | 2002-09-13 21:42:28 +0000 | [diff] [blame] | 1847 | if (!(hkey = get_special_root_hkey( hkey ))) return ERROR_INVALID_HANDLE; |
| 1848 | |
Alexandre Julliard | bcf393a | 2000-10-01 01:44:50 +0000 | [diff] [blame] | 1849 | RtlInitAnsiString( &nameA, name ); |
Alexandre Julliard | ab5e975 | 2001-03-23 19:12:01 +0000 | [diff] [blame] | 1850 | if (!(status = RtlAnsiStringToUnicodeString( &NtCurrentTeb()->StaticUnicodeString, |
| 1851 | &nameA, FALSE ))) |
Alexandre Julliard | ab5e975 | 2001-03-23 19:12:01 +0000 | [diff] [blame] | 1852 | status = NtDeleteValueKey( hkey, &NtCurrentTeb()->StaticUnicodeString ); |
Alexandre Julliard | bcf393a | 2000-10-01 01:44:50 +0000 | [diff] [blame] | 1853 | return RtlNtStatusToDosError( status ); |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 1854 | } |
| 1855 | |
| 1856 | |
| 1857 | /****************************************************************************** |
James Hawkins | 6a358c4 | 2004-07-13 23:33:14 +0000 | [diff] [blame] | 1858 | * RegLoadKeyW [ADVAPI32.@] |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 1859 | * |
Markus Amsler | ec35052 | 2005-11-12 19:12:03 +0000 | [diff] [blame] | 1860 | * Create a subkey under HKEY_USERS or HKEY_LOCAL_MACHINE and store |
| 1861 | * registration information from a specified file into that subkey. |
| 1862 | * |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 1863 | * PARAMS |
James Hawkins | 6a358c4 | 2004-07-13 23:33:14 +0000 | [diff] [blame] | 1864 | * 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 Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 1871 | */ |
| 1872 | LONG WINAPI RegLoadKeyW( HKEY hkey, LPCWSTR subkey, LPCWSTR filename ) |
| 1873 | { |
James Hawkins | 580ded6 | 2005-03-29 11:38:58 +0000 | [diff] [blame] | 1874 | OBJECT_ATTRIBUTES destkey, file; |
| 1875 | UNICODE_STRING subkeyW, filenameW; |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 1876 | |
James Hawkins | 580ded6 | 2005-03-29 11:38:58 +0000 | [diff] [blame] | 1877 | if (!(hkey = get_special_root_hkey(hkey))) return ERROR_INVALID_HANDLE; |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 1878 | |
James Hawkins | 580ded6 | 2005-03-29 11:38:58 +0000 | [diff] [blame] | 1879 | 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 Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 1886 | |
James Hawkins | 580ded6 | 2005-03-29 11:38:58 +0000 | [diff] [blame] | 1887 | 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 Julliard | 57f05e1 | 2000-10-15 00:40:25 +0000 | [diff] [blame] | 1894 | |
James Hawkins | 580ded6 | 2005-03-29 11:38:58 +0000 | [diff] [blame] | 1895 | return RtlNtStatusToDosError( NtLoadKey(&destkey, &file) ); |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 1896 | } |
| 1897 | |
| 1898 | |
| 1899 | /****************************************************************************** |
James Hawkins | 6a358c4 | 2004-07-13 23:33:14 +0000 | [diff] [blame] | 1900 | * RegLoadKeyA [ADVAPI32.@] |
| 1901 | * |
Markus Amsler | d45811c | 2005-11-04 11:43:27 +0000 | [diff] [blame] | 1902 | * See RegLoadKeyW. |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 1903 | */ |
| 1904 | LONG WINAPI RegLoadKeyA( HKEY hkey, LPCSTR subkey, LPCSTR filename ) |
| 1905 | { |
James Hawkins | 580ded6 | 2005-03-29 11:38:58 +0000 | [diff] [blame] | 1906 | UNICODE_STRING subkeyW, filenameW; |
| 1907 | STRING subkeyA, filenameA; |
| 1908 | NTSTATUS status; |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 1909 | |
James Hawkins | 580ded6 | 2005-03-29 11:38:58 +0000 | [diff] [blame] | 1910 | RtlInitAnsiString(&subkeyA, subkey); |
| 1911 | RtlInitAnsiString(&filenameA, filename); |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 1912 | |
James Hawkins | 580ded6 | 2005-03-29 11:38:58 +0000 | [diff] [blame] | 1913 | if ((status = RtlAnsiStringToUnicodeString(&subkeyW, &subkeyA, TRUE))) |
| 1914 | return RtlNtStatusToDosError(status); |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 1915 | |
James Hawkins | 580ded6 | 2005-03-29 11:38:58 +0000 | [diff] [blame] | 1916 | if ((status = RtlAnsiStringToUnicodeString(&filenameW, &filenameA, TRUE))) |
| 1917 | return RtlNtStatusToDosError(status); |
Alexandre Julliard | 57f05e1 | 2000-10-15 00:40:25 +0000 | [diff] [blame] | 1918 | |
James Hawkins | 580ded6 | 2005-03-29 11:38:58 +0000 | [diff] [blame] | 1919 | return RegLoadKeyW(hkey, subkeyW.Buffer, filenameW.Buffer); |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 1920 | } |
| 1921 | |
| 1922 | |
| 1923 | /****************************************************************************** |
James Hawkins | 6a358c4 | 2004-07-13 23:33:14 +0000 | [diff] [blame] | 1924 | * RegSaveKeyW [ADVAPI32.@] |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 1925 | * |
Markus Amsler | ec35052 | 2005-11-12 19:12:03 +0000 | [diff] [blame] | 1926 | * Save a key and all of its subkeys and values to a new file in the standard format. |
| 1927 | * |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 1928 | * PARAMS |
James Hawkins | 6a358c4 | 2004-07-13 23:33:14 +0000 | [diff] [blame] | 1929 | * 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 Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 1936 | */ |
Tony Lambregts | 4550b8b | 2003-03-14 04:50:34 +0000 | [diff] [blame] | 1937 | LONG WINAPI RegSaveKeyW( HKEY hkey, LPCWSTR file, LPSECURITY_ATTRIBUTES sa ) |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 1938 | { |
Tony Lambregts | 4550b8b | 2003-03-14 04:50:34 +0000 | [diff] [blame] | 1939 | static const WCHAR format[] = |
| 1940 | {'r','e','g','%','0','4','x','.','t','m','p',0}; |
| 1941 | WCHAR buffer[MAX_PATH]; |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 1942 | int count = 0; |
Tony Lambregts | 4550b8b | 2003-03-14 04:50:34 +0000 | [diff] [blame] | 1943 | LPWSTR nameW; |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 1944 | DWORD ret, err; |
Alexandre Julliard | 7375597 | 2002-07-31 19:26:03 +0000 | [diff] [blame] | 1945 | HANDLE handle; |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 1946 | |
Tony Lambregts | 4550b8b | 2003-03-14 04:50:34 +0000 | [diff] [blame] | 1947 | TRACE( "(%p,%s,%p)\n", hkey, debugstr_w(file), sa ); |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 1948 | |
| 1949 | if (!file || !*file) return ERROR_INVALID_PARAMETER; |
Alexandre Julliard | f2ef2c2 | 2002-09-13 21:42:28 +0000 | [diff] [blame] | 1950 | if (!(hkey = get_special_root_hkey( hkey ))) return ERROR_INVALID_HANDLE; |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 1951 | |
| 1952 | err = GetLastError(); |
Tony Lambregts | 4550b8b | 2003-03-14 04:50:34 +0000 | [diff] [blame] | 1953 | GetFullPathNameW( file, sizeof(buffer)/sizeof(WCHAR), buffer, &nameW ); |
| 1954 | |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 1955 | for (;;) |
| 1956 | { |
Tony Lambregts | 4550b8b | 2003-03-14 04:50:34 +0000 | [diff] [blame] | 1957 | snprintfW( nameW, 16, format, count++ ); |
| 1958 | handle = CreateFileW( buffer, GENERIC_WRITE, 0, NULL, |
François Gouget | da2b6a9 | 2001-01-06 01:29:18 +0000 | [diff] [blame] | 1959 | CREATE_NEW, FILE_ATTRIBUTE_NORMAL, 0 ); |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 1960 | if (handle != INVALID_HANDLE_VALUE) break; |
Alexandre Julliard | 5354417 | 2000-03-26 18:18:03 +0000 | [diff] [blame] | 1961 | if ((ret = GetLastError()) != ERROR_ALREADY_EXISTS) goto done; |
Andreas Mohr | 6297451 | 2000-05-09 22:31:43 +0000 | [diff] [blame] | 1962 | |
| 1963 | /* Something gone haywire ? Please report if this happens abnormally */ |
| 1964 | if (count >= 100) |
Tony Lambregts | 4550b8b | 2003-03-14 04:50:34 +0000 | [diff] [blame] | 1965 | 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 Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 1966 | } |
| 1967 | |
Robert Shearman | f74b0ad | 2005-03-30 10:21:15 +0000 | [diff] [blame] | 1968 | ret = RtlNtStatusToDosError(NtSaveKey(hkey, handle)); |
Alexandre Julliard | 57f05e1 | 2000-10-15 00:40:25 +0000 | [diff] [blame] | 1969 | |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 1970 | CloseHandle( handle ); |
| 1971 | if (!ret) |
| 1972 | { |
Tony Lambregts | 4550b8b | 2003-03-14 04:50:34 +0000 | [diff] [blame] | 1973 | if (!MoveFileExW( buffer, file, MOVEFILE_REPLACE_EXISTING )) |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 1974 | { |
Tony Lambregts | 4550b8b | 2003-03-14 04:50:34 +0000 | [diff] [blame] | 1975 | ERR( "Failed to move %s to %s\n", debugstr_w(buffer), |
| 1976 | debugstr_w(file) ); |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 1977 | ret = GetLastError(); |
| 1978 | } |
| 1979 | } |
Tony Lambregts | 4550b8b | 2003-03-14 04:50:34 +0000 | [diff] [blame] | 1980 | if (ret) DeleteFileW( buffer ); |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 1981 | |
| 1982 | done: |
| 1983 | SetLastError( err ); /* restore last error code */ |
| 1984 | return ret; |
| 1985 | } |
| 1986 | |
| 1987 | |
| 1988 | /****************************************************************************** |
James Hawkins | 6a358c4 | 2004-07-13 23:33:14 +0000 | [diff] [blame] | 1989 | * RegSaveKeyA [ADVAPI32.@] |
| 1990 | * |
Markus Amsler | d45811c | 2005-11-04 11:43:27 +0000 | [diff] [blame] | 1991 | * See RegSaveKeyW. |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 1992 | */ |
Tony Lambregts | 4550b8b | 2003-03-14 04:50:34 +0000 | [diff] [blame] | 1993 | LONG WINAPI RegSaveKeyA( HKEY hkey, LPCSTR file, LPSECURITY_ATTRIBUTES sa ) |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 1994 | { |
Tony Lambregts | 4550b8b | 2003-03-14 04:50:34 +0000 | [diff] [blame] | 1995 | 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 Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 2003 | } |
Alexandre Julliard | 5ce2329 | 2000-11-30 20:31:41 +0000 | [diff] [blame] | 2004 | |
| 2005 | |
| 2006 | /****************************************************************************** |
Patrik Stridvall | d0a4177 | 2001-02-14 23:11:17 +0000 | [diff] [blame] | 2007 | * RegRestoreKeyW [ADVAPI32.@] |
Alexandre Julliard | 5ce2329 | 2000-11-30 20:31:41 +0000 | [diff] [blame] | 2008 | * |
Markus Amsler | ec35052 | 2005-11-12 19:12:03 +0000 | [diff] [blame] | 2009 | * Read the registry information from a file and copy it over a key. |
| 2010 | * |
Alexandre Julliard | 5ce2329 | 2000-11-30 20:31:41 +0000 | [diff] [blame] | 2011 | * PARAMS |
James Hawkins | 6a358c4 | 2004-07-13 23:33:14 +0000 | [diff] [blame] | 2012 | * 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 Julliard | 5ce2329 | 2000-11-30 20:31:41 +0000 | [diff] [blame] | 2019 | */ |
| 2020 | LONG WINAPI RegRestoreKeyW( HKEY hkey, LPCWSTR lpFile, DWORD dwFlags ) |
| 2021 | { |
Michael Stefaniuc | cbacde5 | 2002-10-25 19:17:33 +0000 | [diff] [blame] | 2022 | TRACE("(%p,%s,%ld)\n",hkey,debugstr_w(lpFile),dwFlags); |
Alexandre Julliard | 5ce2329 | 2000-11-30 20:31:41 +0000 | [diff] [blame] | 2023 | |
| 2024 | /* It seems to do this check before the hkey check */ |
| 2025 | if (!lpFile || !*lpFile) |
| 2026 | return ERROR_INVALID_PARAMETER; |
| 2027 | |
Michael Stefaniuc | cbacde5 | 2002-10-25 19:17:33 +0000 | [diff] [blame] | 2028 | FIXME("(%p,%s,%ld): stub\n",hkey,debugstr_w(lpFile),dwFlags); |
Alexandre Julliard | 5ce2329 | 2000-11-30 20:31:41 +0000 | [diff] [blame] | 2029 | |
| 2030 | /* Check for file existence */ |
| 2031 | |
| 2032 | return ERROR_SUCCESS; |
| 2033 | } |
| 2034 | |
| 2035 | |
| 2036 | /****************************************************************************** |
Patrik Stridvall | d0a4177 | 2001-02-14 23:11:17 +0000 | [diff] [blame] | 2037 | * RegRestoreKeyA [ADVAPI32.@] |
James Hawkins | 6a358c4 | 2004-07-13 23:33:14 +0000 | [diff] [blame] | 2038 | * |
Markus Amsler | d45811c | 2005-11-04 11:43:27 +0000 | [diff] [blame] | 2039 | * See RegRestoreKeyW. |
Alexandre Julliard | 5ce2329 | 2000-11-30 20:31:41 +0000 | [diff] [blame] | 2040 | */ |
| 2041 | LONG WINAPI RegRestoreKeyA( HKEY hkey, LPCSTR lpFile, DWORD dwFlags ) |
| 2042 | { |
Matthew Davison | 6f2a071 | 2003-01-20 23:23:12 +0000 | [diff] [blame] | 2043 | UNICODE_STRING lpFileW; |
| 2044 | LONG ret; |
| 2045 | |
| 2046 | RtlCreateUnicodeStringFromAsciiz( &lpFileW, lpFile ); |
| 2047 | ret = RegRestoreKeyW( hkey, lpFileW.Buffer, dwFlags ); |
| 2048 | RtlFreeUnicodeString( &lpFileW ); |
Alexandre Julliard | 5ce2329 | 2000-11-30 20:31:41 +0000 | [diff] [blame] | 2049 | return ret; |
| 2050 | } |
| 2051 | |
| 2052 | |
| 2053 | /****************************************************************************** |
Patrik Stridvall | d0a4177 | 2001-02-14 23:11:17 +0000 | [diff] [blame] | 2054 | * RegUnLoadKeyW [ADVAPI32.@] |
Alexandre Julliard | 5ce2329 | 2000-11-30 20:31:41 +0000 | [diff] [blame] | 2055 | * |
Markus Amsler | ec35052 | 2005-11-12 19:12:03 +0000 | [diff] [blame] | 2056 | * Unload a registry key and its subkeys from the registry. |
| 2057 | * |
Alexandre Julliard | 5ce2329 | 2000-11-30 20:31:41 +0000 | [diff] [blame] | 2058 | * PARAMS |
James Hawkins | 6a358c4 | 2004-07-13 23:33:14 +0000 | [diff] [blame] | 2059 | * 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 Julliard | 5ce2329 | 2000-11-30 20:31:41 +0000 | [diff] [blame] | 2065 | */ |
| 2066 | LONG WINAPI RegUnLoadKeyW( HKEY hkey, LPCWSTR lpSubKey ) |
| 2067 | { |
Mike McCormack | 5ac945c | 2003-08-19 03:08:17 +0000 | [diff] [blame] | 2068 | 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 Shearman | f74b0ad | 2005-03-30 10:21:15 +0000 | [diff] [blame] | 2077 | ret = RtlNtStatusToDosError(NtUnloadKey(shkey)); |
| 2078 | |
Mike McCormack | 5ac945c | 2003-08-19 03:08:17 +0000 | [diff] [blame] | 2079 | RegCloseKey(shkey); |
| 2080 | |
| 2081 | return ret; |
Alexandre Julliard | 5ce2329 | 2000-11-30 20:31:41 +0000 | [diff] [blame] | 2082 | } |
| 2083 | |
| 2084 | |
| 2085 | /****************************************************************************** |
Patrik Stridvall | d0a4177 | 2001-02-14 23:11:17 +0000 | [diff] [blame] | 2086 | * RegUnLoadKeyA [ADVAPI32.@] |
James Hawkins | 6a358c4 | 2004-07-13 23:33:14 +0000 | [diff] [blame] | 2087 | * |
Markus Amsler | d45811c | 2005-11-04 11:43:27 +0000 | [diff] [blame] | 2088 | * See RegUnLoadKeyW. |
Alexandre Julliard | 5ce2329 | 2000-11-30 20:31:41 +0000 | [diff] [blame] | 2089 | */ |
| 2090 | LONG WINAPI RegUnLoadKeyA( HKEY hkey, LPCSTR lpSubKey ) |
| 2091 | { |
Matthew Davison | 6f2a071 | 2003-01-20 23:23:12 +0000 | [diff] [blame] | 2092 | UNICODE_STRING lpSubKeyW; |
| 2093 | LONG ret; |
| 2094 | |
| 2095 | RtlCreateUnicodeStringFromAsciiz( &lpSubKeyW, lpSubKey ); |
| 2096 | ret = RegUnLoadKeyW( hkey, lpSubKeyW.Buffer ); |
| 2097 | RtlFreeUnicodeString( &lpSubKeyW ); |
Alexandre Julliard | 5ce2329 | 2000-11-30 20:31:41 +0000 | [diff] [blame] | 2098 | return ret; |
| 2099 | } |
| 2100 | |
| 2101 | |
| 2102 | /****************************************************************************** |
Patrik Stridvall | d0a4177 | 2001-02-14 23:11:17 +0000 | [diff] [blame] | 2103 | * RegReplaceKeyW [ADVAPI32.@] |
Alexandre Julliard | 5ce2329 | 2000-11-30 20:31:41 +0000 | [diff] [blame] | 2104 | * |
Markus Amsler | ec35052 | 2005-11-12 19:12:03 +0000 | [diff] [blame] | 2105 | * Replace the file backing a registry key and all its subkeys with another file. |
| 2106 | * |
Alexandre Julliard | 5ce2329 | 2000-11-30 20:31:41 +0000 | [diff] [blame] | 2107 | * PARAMS |
James Hawkins | 6a358c4 | 2004-07-13 23:33:14 +0000 | [diff] [blame] | 2108 | * 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 Julliard | 5ce2329 | 2000-11-30 20:31:41 +0000 | [diff] [blame] | 2116 | */ |
| 2117 | LONG WINAPI RegReplaceKeyW( HKEY hkey, LPCWSTR lpSubKey, LPCWSTR lpNewFile, |
| 2118 | LPCWSTR lpOldFile ) |
| 2119 | { |
Michael Stefaniuc | cbacde5 | 2002-10-25 19:17:33 +0000 | [diff] [blame] | 2120 | FIXME("(%p,%s,%s,%s): stub\n", hkey, debugstr_w(lpSubKey), |
Alexandre Julliard | 5ce2329 | 2000-11-30 20:31:41 +0000 | [diff] [blame] | 2121 | debugstr_w(lpNewFile),debugstr_w(lpOldFile)); |
| 2122 | return ERROR_SUCCESS; |
| 2123 | } |
| 2124 | |
| 2125 | |
| 2126 | /****************************************************************************** |
Patrik Stridvall | d0a4177 | 2001-02-14 23:11:17 +0000 | [diff] [blame] | 2127 | * RegReplaceKeyA [ADVAPI32.@] |
James Hawkins | 6a358c4 | 2004-07-13 23:33:14 +0000 | [diff] [blame] | 2128 | * |
Markus Amsler | d45811c | 2005-11-04 11:43:27 +0000 | [diff] [blame] | 2129 | * See RegReplaceKeyW. |
Alexandre Julliard | 5ce2329 | 2000-11-30 20:31:41 +0000 | [diff] [blame] | 2130 | */ |
| 2131 | LONG WINAPI RegReplaceKeyA( HKEY hkey, LPCSTR lpSubKey, LPCSTR lpNewFile, |
| 2132 | LPCSTR lpOldFile ) |
| 2133 | { |
Matthew Davison | 6f2a071 | 2003-01-20 23:23:12 +0000 | [diff] [blame] | 2134 | 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 Julliard | 5ce2329 | 2000-11-30 20:31:41 +0000 | [diff] [blame] | 2146 | return ret; |
| 2147 | } |
| 2148 | |
| 2149 | |
| 2150 | /****************************************************************************** |
Patrik Stridvall | d0a4177 | 2001-02-14 23:11:17 +0000 | [diff] [blame] | 2151 | * RegSetKeySecurity [ADVAPI32.@] |
Alexandre Julliard | 5ce2329 | 2000-11-30 20:31:41 +0000 | [diff] [blame] | 2152 | * |
Markus Amsler | ec35052 | 2005-11-12 19:12:03 +0000 | [diff] [blame] | 2153 | * Set the security of an open registry key. |
| 2154 | * |
Alexandre Julliard | 5ce2329 | 2000-11-30 20:31:41 +0000 | [diff] [blame] | 2155 | * PARAMS |
James Hawkins | 6a358c4 | 2004-07-13 23:33:14 +0000 | [diff] [blame] | 2156 | * 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 Julliard | 5ce2329 | 2000-11-30 20:31:41 +0000 | [diff] [blame] | 2163 | */ |
| 2164 | LONG WINAPI RegSetKeySecurity( HKEY hkey, SECURITY_INFORMATION SecurityInfo, |
| 2165 | PSECURITY_DESCRIPTOR pSecurityDesc ) |
| 2166 | { |
Michael Stefaniuc | cbacde5 | 2002-10-25 19:17:33 +0000 | [diff] [blame] | 2167 | TRACE("(%p,%ld,%p)\n",hkey,SecurityInfo,pSecurityDesc); |
Alexandre Julliard | 5ce2329 | 2000-11-30 20:31:41 +0000 | [diff] [blame] | 2168 | |
| 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 Stefaniuc | cbacde5 | 2002-10-25 19:17:33 +0000 | [diff] [blame] | 2181 | FIXME(":(%p,%ld,%p): stub\n",hkey,SecurityInfo,pSecurityDesc); |
Alexandre Julliard | 5ce2329 | 2000-11-30 20:31:41 +0000 | [diff] [blame] | 2182 | |
| 2183 | return ERROR_SUCCESS; |
| 2184 | } |
| 2185 | |
| 2186 | |
| 2187 | /****************************************************************************** |
Patrik Stridvall | d0a4177 | 2001-02-14 23:11:17 +0000 | [diff] [blame] | 2188 | * RegGetKeySecurity [ADVAPI32.@] |
Jon Griffiths | 50ce084 | 2004-04-23 21:32:34 +0000 | [diff] [blame] | 2189 | * |
| 2190 | * Get a copy of the security descriptor for a given registry key. |
Alexandre Julliard | 5ce2329 | 2000-11-30 20:31:41 +0000 | [diff] [blame] | 2191 | * |
| 2192 | * PARAMS |
James Hawkins | 6a358c4 | 2004-07-13 23:33:14 +0000 | [diff] [blame] | 2193 | * 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 Julliard | 5ce2329 | 2000-11-30 20:31:41 +0000 | [diff] [blame] | 2197 | * |
| 2198 | * RETURNS |
James Hawkins | 6a358c4 | 2004-07-13 23:33:14 +0000 | [diff] [blame] | 2199 | * Success: ERROR_SUCCESS |
| 2200 | * Failure: Error code |
Alexandre Julliard | 5ce2329 | 2000-11-30 20:31:41 +0000 | [diff] [blame] | 2201 | */ |
| 2202 | LONG WINAPI RegGetKeySecurity( HKEY hkey, SECURITY_INFORMATION SecurityInformation, |
| 2203 | PSECURITY_DESCRIPTOR pSecurityDescriptor, |
| 2204 | LPDWORD lpcbSecurityDescriptor ) |
| 2205 | { |
Michael Stefaniuc | cbacde5 | 2002-10-25 19:17:33 +0000 | [diff] [blame] | 2206 | TRACE("(%p,%ld,%p,%ld)\n",hkey,SecurityInformation,pSecurityDescriptor, |
Alexandre Julliard | 5ce2329 | 2000-11-30 20:31:41 +0000 | [diff] [blame] | 2207 | 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 Stefaniuc | cbacde5 | 2002-10-25 19:17:33 +0000 | [diff] [blame] | 2214 | FIXME("(%p,%ld,%p,%ld): stub\n",hkey,SecurityInformation, |
Alexandre Julliard | 5ce2329 | 2000-11-30 20:31:41 +0000 | [diff] [blame] | 2215 | pSecurityDescriptor,lpcbSecurityDescriptor?*lpcbSecurityDescriptor:0); |
| 2216 | |
Dmitry Timoshkov | 79313d3 | 2002-04-02 02:41:27 +0000 | [diff] [blame] | 2217 | /* Do not leave security descriptor filled with garbage */ |
| 2218 | RtlCreateSecurityDescriptor(pSecurityDescriptor, SECURITY_DESCRIPTOR_REVISION); |
| 2219 | |
Alexandre Julliard | 5ce2329 | 2000-11-30 20:31:41 +0000 | [diff] [blame] | 2220 | return ERROR_SUCCESS; |
| 2221 | } |
| 2222 | |
| 2223 | |
| 2224 | /****************************************************************************** |
Patrik Stridvall | d0a4177 | 2001-02-14 23:11:17 +0000 | [diff] [blame] | 2225 | * RegFlushKey [ADVAPI32.@] |
Jon Griffiths | 50ce084 | 2004-04-23 21:32:34 +0000 | [diff] [blame] | 2226 | * |
| 2227 | * Immediately write a registry key to registry. |
Alexandre Julliard | 5ce2329 | 2000-11-30 20:31:41 +0000 | [diff] [blame] | 2228 | * |
| 2229 | * PARAMS |
James Hawkins | 6a358c4 | 2004-07-13 23:33:14 +0000 | [diff] [blame] | 2230 | * hkey [I] Handle of key to write |
Alexandre Julliard | 5ce2329 | 2000-11-30 20:31:41 +0000 | [diff] [blame] | 2231 | * |
| 2232 | * RETURNS |
James Hawkins | 6a358c4 | 2004-07-13 23:33:14 +0000 | [diff] [blame] | 2233 | * Success: ERROR_SUCCESS |
| 2234 | * Failure: Error code |
Alexandre Julliard | 5ce2329 | 2000-11-30 20:31:41 +0000 | [diff] [blame] | 2235 | */ |
| 2236 | DWORD WINAPI RegFlushKey( HKEY hkey ) |
| 2237 | { |
Mike Hearn | 43cb03b | 2004-01-03 00:38:30 +0000 | [diff] [blame] | 2238 | hkey = get_special_root_hkey( hkey ); |
| 2239 | if (!hkey) return ERROR_INVALID_HANDLE; |
| 2240 | |
| 2241 | return RtlNtStatusToDosError( NtFlushKey( hkey ) ); |
Alexandre Julliard | 5ce2329 | 2000-11-30 20:31:41 +0000 | [diff] [blame] | 2242 | } |
| 2243 | |
| 2244 | |
| 2245 | /****************************************************************************** |
Patrik Stridvall | d0a4177 | 2001-02-14 23:11:17 +0000 | [diff] [blame] | 2246 | * RegConnectRegistryW [ADVAPI32.@] |
Alexandre Julliard | 5ce2329 | 2000-11-30 20:31:41 +0000 | [diff] [blame] | 2247 | * |
Markus Amsler | ec35052 | 2005-11-12 19:12:03 +0000 | [diff] [blame] | 2248 | * Establishe a connection to a predefined registry key on another computer. |
| 2249 | * |
Alexandre Julliard | 5ce2329 | 2000-11-30 20:31:41 +0000 | [diff] [blame] | 2250 | * PARAMS |
James Hawkins | 6a358c4 | 2004-07-13 23:33:14 +0000 | [diff] [blame] | 2251 | * 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 Julliard | 5ce2329 | 2000-11-30 20:31:41 +0000 | [diff] [blame] | 2258 | */ |
Vincent Béron | 9a62491 | 2002-05-31 23:06:46 +0000 | [diff] [blame] | 2259 | LONG WINAPI RegConnectRegistryW( LPCWSTR lpMachineName, HKEY hKey, |
Alexandre Julliard | 5cf56a3 | 2002-10-03 19:46:27 +0000 | [diff] [blame] | 2260 | PHKEY phkResult ) |
Alexandre Julliard | 5ce2329 | 2000-11-30 20:31:41 +0000 | [diff] [blame] | 2261 | { |
Juan Lang | ae176d1 | 2004-03-18 01:34:23 +0000 | [diff] [blame] | 2262 | LONG ret; |
| 2263 | |
Michael Stefaniuc | cbacde5 | 2002-10-25 19:17:33 +0000 | [diff] [blame] | 2264 | TRACE("(%s,%p,%p): stub\n",debugstr_w(lpMachineName),hKey,phkResult); |
Alexandre Julliard | 5ce2329 | 2000-11-30 20:31:41 +0000 | [diff] [blame] | 2265 | |
| 2266 | if (!lpMachineName || !*lpMachineName) { |
| 2267 | /* Use the local machine name */ |
Juan Lang | ae176d1 | 2004-03-18 01:34:23 +0000 | [diff] [blame] | 2268 | ret = RegOpenKeyW( hKey, NULL, phkResult ); |
Alexandre Julliard | 5ce2329 | 2000-11-30 20:31:41 +0000 | [diff] [blame] | 2269 | } |
Rein Klazes | c16e705 | 2005-09-15 09:31:05 +0000 | [diff] [blame] | 2270 | else { |
Juan Lang | ae176d1 | 2004-03-18 01:34:23 +0000 | [diff] [blame] | 2271 | WCHAR compName[MAX_COMPUTERNAME_LENGTH + 1]; |
| 2272 | DWORD len = sizeof(compName) / sizeof(WCHAR); |
Alexandre Julliard | 5ce2329 | 2000-11-30 20:31:41 +0000 | [diff] [blame] | 2273 | |
Rein Klazes | c16e705 | 2005-09-15 09:31:05 +0000 | [diff] [blame] | 2274 | /* MSDN says lpMachineName must start with \\ : not so */ |
| 2275 | if( lpMachineName[0] == '\\' && lpMachineName[1] == '\\') |
| 2276 | lpMachineName += 2; |
Juan Lang | ae176d1 | 2004-03-18 01:34:23 +0000 | [diff] [blame] | 2277 | if (GetComputerNameW(compName, &len)) |
| 2278 | { |
Rein Klazes | c16e705 | 2005-09-15 09:31:05 +0000 | [diff] [blame] | 2279 | if (!strcmpiW(lpMachineName, compName)) |
Juan Lang | ae176d1 | 2004-03-18 01:34:23 +0000 | [diff] [blame] | 2280 | ret = RegOpenKeyW(hKey, NULL, phkResult); |
| 2281 | else |
| 2282 | { |
Rein Klazes | c16e705 | 2005-09-15 09:31:05 +0000 | [diff] [blame] | 2283 | FIXME("Connect to %s is not supported.\n",debugstr_w(lpMachineName)); |
Juan Lang | ae176d1 | 2004-03-18 01:34:23 +0000 | [diff] [blame] | 2284 | ret = ERROR_BAD_NETPATH; |
| 2285 | } |
| 2286 | } |
| 2287 | else |
| 2288 | ret = GetLastError(); |
| 2289 | } |
| 2290 | return ret; |
Alexandre Julliard | 5ce2329 | 2000-11-30 20:31:41 +0000 | [diff] [blame] | 2291 | } |
| 2292 | |
| 2293 | |
| 2294 | /****************************************************************************** |
Patrik Stridvall | d0a4177 | 2001-02-14 23:11:17 +0000 | [diff] [blame] | 2295 | * RegConnectRegistryA [ADVAPI32.@] |
James Hawkins | 6a358c4 | 2004-07-13 23:33:14 +0000 | [diff] [blame] | 2296 | * |
Markus Amsler | d45811c | 2005-11-04 11:43:27 +0000 | [diff] [blame] | 2297 | * See RegConnectRegistryW. |
Alexandre Julliard | 5ce2329 | 2000-11-30 20:31:41 +0000 | [diff] [blame] | 2298 | */ |
Alexandre Julliard | 5cf56a3 | 2002-10-03 19:46:27 +0000 | [diff] [blame] | 2299 | LONG WINAPI RegConnectRegistryA( LPCSTR machine, HKEY hkey, PHKEY reskey ) |
Alexandre Julliard | 5ce2329 | 2000-11-30 20:31:41 +0000 | [diff] [blame] | 2300 | { |
Matthew Davison | 6f2a071 | 2003-01-20 23:23:12 +0000 | [diff] [blame] | 2301 | UNICODE_STRING machineW; |
| 2302 | LONG ret; |
| 2303 | |
| 2304 | RtlCreateUnicodeStringFromAsciiz( &machineW, machine ); |
| 2305 | ret = RegConnectRegistryW( machineW.Buffer, hkey, reskey ); |
| 2306 | RtlFreeUnicodeString( &machineW ); |
Alexandre Julliard | 5ce2329 | 2000-11-30 20:31:41 +0000 | [diff] [blame] | 2307 | return ret; |
| 2308 | } |
| 2309 | |
| 2310 | |
| 2311 | /****************************************************************************** |
Patrik Stridvall | d0a4177 | 2001-02-14 23:11:17 +0000 | [diff] [blame] | 2312 | * RegNotifyChangeKeyValue [ADVAPI32.@] |
Alexandre Julliard | 5ce2329 | 2000-11-30 20:31:41 +0000 | [diff] [blame] | 2313 | * |
Markus Amsler | ec35052 | 2005-11-12 19:12:03 +0000 | [diff] [blame] | 2314 | * Notify the caller about changes to the attributes or contents of a registry key. |
| 2315 | * |
Alexandre Julliard | 5ce2329 | 2000-11-30 20:31:41 +0000 | [diff] [blame] | 2316 | * PARAMS |
James Hawkins | 6a358c4 | 2004-07-13 23:33:14 +0000 | [diff] [blame] | 2317 | * 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 Julliard | 5ce2329 | 2000-11-30 20:31:41 +0000 | [diff] [blame] | 2326 | */ |
Vincent Béron | 9a62491 | 2002-05-31 23:06:46 +0000 | [diff] [blame] | 2327 | LONG WINAPI RegNotifyChangeKeyValue( HKEY hkey, BOOL fWatchSubTree, |
Alexandre Julliard | 5ce2329 | 2000-11-30 20:31:41 +0000 | [diff] [blame] | 2328 | DWORD fdwNotifyFilter, HANDLE hEvent, |
| 2329 | BOOL fAsync ) |
| 2330 | { |
Robert Shearman | efbea2e | 2005-05-16 14:08:11 +0000 | [diff] [blame] | 2331 | NTSTATUS status; |
| 2332 | IO_STATUS_BLOCK iosb; |
Mike McCormack | 11f4b44 | 2002-11-25 02:47:32 +0000 | [diff] [blame] | 2333 | |
Robert Shearman | efbea2e | 2005-05-16 14:08:11 +0000 | [diff] [blame] | 2334 | hkey = get_special_root_hkey( hkey ); |
| 2335 | if (!hkey) return ERROR_INVALID_HANDLE; |
Mike McCormack | 11f4b44 | 2002-11-25 02:47:32 +0000 | [diff] [blame] | 2336 | |
Robert Shearman | efbea2e | 2005-05-16 14:08:11 +0000 | [diff] [blame] | 2337 | TRACE("(%p,%i,%ld,%p,%i)\n", hkey, fWatchSubTree, fdwNotifyFilter, |
| 2338 | hEvent, fAsync); |
Mike McCormack | 11f4b44 | 2002-11-25 02:47:32 +0000 | [diff] [blame] | 2339 | |
Robert Shearman | efbea2e | 2005-05-16 14:08:11 +0000 | [diff] [blame] | 2340 | status = NtNotifyChangeKey( hkey, hEvent, NULL, NULL, &iosb, |
Aric Stewart | 9108063 | 2006-02-09 12:08:47 +0100 | [diff] [blame] | 2341 | fdwNotifyFilter, fAsync, NULL, 0, |
| 2342 | fWatchSubTree); |
Mike McCormack | 11f4b44 | 2002-11-25 02:47:32 +0000 | [diff] [blame] | 2343 | |
Robert Shearman | efbea2e | 2005-05-16 14:08:11 +0000 | [diff] [blame] | 2344 | if (status && status != STATUS_TIMEOUT) |
| 2345 | return RtlNtStatusToDosError( status ); |
| 2346 | |
| 2347 | return ERROR_SUCCESS; |
Alexandre Julliard | 5ce2329 | 2000-11-30 20:31:41 +0000 | [diff] [blame] | 2348 | } |
Robert Shearman | 65e8182 | 2004-01-16 04:40:33 +0000 | [diff] [blame] | 2349 | |
| 2350 | /****************************************************************************** |
| 2351 | * RegOpenUserClassesRoot [ADVAPI32.@] |
Jon Griffiths | 50ce084 | 2004-04-23 21:32:34 +0000 | [diff] [blame] | 2352 | * |
| 2353 | * Open the HKEY_CLASSES_ROOT key for a user. |
Robert Shearman | 65e8182 | 2004-01-16 04:40:33 +0000 | [diff] [blame] | 2354 | * |
| 2355 | * PARAMS |
James Hawkins | 6a358c4 | 2004-07-13 23:33:14 +0000 | [diff] [blame] | 2356 | * 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 Shearman | 65e8182 | 2004-01-16 04:40:33 +0000 | [diff] [blame] | 2360 | * |
James Hawkins | 6a358c4 | 2004-07-13 23:33:14 +0000 | [diff] [blame] | 2361 | * RETURNS |
| 2362 | * Success: ERROR_SUCCESS |
| 2363 | * Failure: nonzero error code from Winerror.h |
| 2364 | * |
Jon Griffiths | 50ce084 | 2004-04-23 21:32:34 +0000 | [diff] [blame] | 2365 | * NOTES |
James Hawkins | 6a358c4 | 2004-07-13 23:33:14 +0000 | [diff] [blame] | 2366 | * 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 Shearman | 65e8182 | 2004-01-16 04:40:33 +0000 | [diff] [blame] | 2369 | */ |
| 2370 | LONG 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 Jung | ac615ce | 2006-02-14 10:41:18 +0100 | [diff] [blame] | 2382 | |
| 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 | */ |
| 2390 | static 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 | */ |
| 2449 | LONG 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 | |
| 2524 | cleanup: |
| 2525 | HeapFree(GetProcessHeap(), 0, pwszTempBuffer); |
| 2526 | HeapFree(GetProcessHeap(), 0, pwszExpandedBuffer); |
| 2527 | return result; |
| 2528 | } |
| 2529 | |
| 2530 | /****************************************************************************** |
| 2531 | * RegLoadMUIStringA [ADVAPI32.@] |
| 2532 | * |
| 2533 | * See RegLoadMUIStringW |
| 2534 | */ |
| 2535 | LONG 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 | |
| 2561 | cleanup: |
| 2562 | HeapFree(GetProcessHeap(), 0, pwszBuffer); |
| 2563 | RtlFreeUnicodeString(&baseDirW); |
| 2564 | RtlFreeUnicodeString(&valueW); |
| 2565 | |
| 2566 | return result; |
| 2567 | } |