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 | |
Alexandre Julliard | e37c6e1 | 2003-09-05 23:08:26 +0000 | [diff] [blame] | 33 | #include "windef.h" |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 34 | #include "winbase.h" |
| 35 | #include "winreg.h" |
| 36 | #include "winerror.h" |
Alexandre Julliard | e37c6e1 | 2003-09-05 23:08:26 +0000 | [diff] [blame] | 37 | #include "ntstatus.h" |
Alexandre Julliard | c7e7df8 | 2000-08-14 14:41:19 +0000 | [diff] [blame] | 38 | #include "wine/unicode.h" |
Alexandre Julliard | 37e9503 | 2001-07-19 00:39:09 +0000 | [diff] [blame] | 39 | #include "wine/server.h" |
Alexandre Julliard | 0799c1a | 2002-03-09 23:29:33 +0000 | [diff] [blame] | 40 | #include "wine/debug.h" |
Matthew Davison | 6f2a071 | 2003-01-20 23:23:12 +0000 | [diff] [blame] | 41 | #include "winternl.h" |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 42 | |
Alexandre Julliard | 0799c1a | 2002-03-09 23:29:33 +0000 | [diff] [blame] | 43 | WINE_DEFAULT_DEBUG_CHANNEL(reg); |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 44 | |
Alexandre Julliard | f2ef2c2 | 2002-09-13 21:42:28 +0000 | [diff] [blame] | 45 | /* allowed bits for access mask */ |
| 46 | #define KEY_ACCESS_MASK (KEY_ALL_ACCESS | MAXIMUM_ALLOWED) |
| 47 | |
| 48 | #define HKEY_SPECIAL_ROOT_FIRST HKEY_CLASSES_ROOT |
| 49 | #define HKEY_SPECIAL_ROOT_LAST HKEY_DYN_DATA |
| 50 | #define NB_SPECIAL_ROOT_KEYS ((UINT)HKEY_SPECIAL_ROOT_LAST - (UINT)HKEY_SPECIAL_ROOT_FIRST + 1) |
| 51 | |
| 52 | static HKEY special_root_keys[NB_SPECIAL_ROOT_KEYS]; |
| 53 | |
| 54 | static const WCHAR name_CLASSES_ROOT[] = |
| 55 | {'M','a','c','h','i','n','e','\\', |
| 56 | 'S','o','f','t','w','a','r','e','\\', |
| 57 | 'C','l','a','s','s','e','s',0}; |
| 58 | static const WCHAR name_LOCAL_MACHINE[] = |
| 59 | {'M','a','c','h','i','n','e',0}; |
| 60 | static const WCHAR name_USERS[] = |
| 61 | {'U','s','e','r',0}; |
| 62 | static const WCHAR name_PERFORMANCE_DATA[] = |
| 63 | {'P','e','r','f','D','a','t','a',0}; |
| 64 | static const WCHAR name_CURRENT_CONFIG[] = |
| 65 | {'M','a','c','h','i','n','e','\\', |
| 66 | 'S','y','s','t','e','m','\\', |
| 67 | 'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\', |
| 68 | 'H','a','r','d','w','a','r','e','P','r','o','f','i','l','e','s','\\', |
| 69 | 'C','u','r','r','e','n','t',0}; |
| 70 | static const WCHAR name_DYN_DATA[] = |
| 71 | {'D','y','n','D','a','t','a',0}; |
| 72 | |
| 73 | #define DECL_STR(key) { sizeof(name_##key)-sizeof(WCHAR), sizeof(name_##key), (LPWSTR)name_##key } |
| 74 | static UNICODE_STRING root_key_names[NB_SPECIAL_ROOT_KEYS] = |
| 75 | { |
| 76 | DECL_STR(CLASSES_ROOT), |
| 77 | { 0, 0, NULL }, /* HKEY_CURRENT_USER is determined dynamically */ |
| 78 | DECL_STR(LOCAL_MACHINE), |
| 79 | DECL_STR(USERS), |
| 80 | DECL_STR(PERFORMANCE_DATA), |
| 81 | DECL_STR(CURRENT_CONFIG), |
| 82 | DECL_STR(DYN_DATA) |
| 83 | }; |
| 84 | #undef DECL_STR |
| 85 | |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 86 | |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 87 | /* check if value type needs string conversion (Ansi<->Unicode) */ |
Michael Cardenas | 7dbce65 | 2002-03-21 01:24:52 +0000 | [diff] [blame] | 88 | inline static int is_string( DWORD type ) |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 89 | { |
| 90 | return (type == REG_SZ) || (type == REG_EXPAND_SZ) || (type == REG_MULTI_SZ); |
| 91 | } |
| 92 | |
Michael Cardenas | 7dbce65 | 2002-03-21 01:24:52 +0000 | [diff] [blame] | 93 | /* check if current version is NT or Win95 */ |
| 94 | inline static int is_version_nt(void) |
| 95 | { |
| 96 | return !(GetVersion() & 0x80000000); |
| 97 | } |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 98 | |
Alexandre Julliard | f2ef2c2 | 2002-09-13 21:42:28 +0000 | [diff] [blame] | 99 | /* create one of the HKEY_* special root keys */ |
| 100 | static HKEY create_special_root_hkey( HKEY hkey, DWORD access ) |
| 101 | { |
| 102 | HKEY ret = 0; |
| 103 | int idx = (UINT)hkey - (UINT)HKEY_SPECIAL_ROOT_FIRST; |
| 104 | |
| 105 | if (hkey == HKEY_CURRENT_USER) |
| 106 | { |
| 107 | if (RtlOpenCurrentUser( access, &hkey )) return 0; |
Michael Stefaniuc | cbacde5 | 2002-10-25 19:17:33 +0000 | [diff] [blame] | 108 | TRACE( "HKEY_CURRENT_USER -> %p\n", hkey ); |
Alexandre Julliard | f2ef2c2 | 2002-09-13 21:42:28 +0000 | [diff] [blame] | 109 | } |
| 110 | else |
| 111 | { |
| 112 | OBJECT_ATTRIBUTES attr; |
| 113 | |
| 114 | attr.Length = sizeof(attr); |
| 115 | attr.RootDirectory = 0; |
| 116 | attr.ObjectName = &root_key_names[idx]; |
| 117 | attr.Attributes = 0; |
| 118 | attr.SecurityDescriptor = NULL; |
| 119 | attr.SecurityQualityOfService = NULL; |
| 120 | if (NtCreateKey( &hkey, access, &attr, 0, NULL, 0, NULL )) return 0; |
Michael Stefaniuc | cbacde5 | 2002-10-25 19:17:33 +0000 | [diff] [blame] | 121 | TRACE( "%s -> %p\n", debugstr_w(attr.ObjectName->Buffer), hkey ); |
Alexandre Julliard | f2ef2c2 | 2002-09-13 21:42:28 +0000 | [diff] [blame] | 122 | } |
| 123 | |
Michael Stefaniuc | cbacde5 | 2002-10-25 19:17:33 +0000 | [diff] [blame] | 124 | if (!(ret = InterlockedCompareExchangePointer( (void **)&special_root_keys[idx], hkey, 0 ))) |
Alexandre Julliard | f2ef2c2 | 2002-09-13 21:42:28 +0000 | [diff] [blame] | 125 | ret = hkey; |
| 126 | else |
| 127 | NtClose( hkey ); /* somebody beat us to it */ |
| 128 | return ret; |
| 129 | } |
| 130 | |
| 131 | /* map the hkey from special root to normal key if necessary */ |
| 132 | inline static HKEY get_special_root_hkey( HKEY hkey ) |
| 133 | { |
| 134 | HKEY ret = hkey; |
| 135 | |
| 136 | if ((hkey >= HKEY_SPECIAL_ROOT_FIRST) && (hkey <= HKEY_SPECIAL_ROOT_LAST)) |
| 137 | { |
| 138 | if (!(ret = special_root_keys[(UINT)hkey - (UINT)HKEY_SPECIAL_ROOT_FIRST])) |
| 139 | ret = create_special_root_hkey( hkey, KEY_ALL_ACCESS ); |
| 140 | } |
| 141 | return ret; |
| 142 | } |
| 143 | |
Juergen Schmied | a44e0b0 | 2002-05-09 19:39:10 +0000 | [diff] [blame] | 144 | |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 145 | /****************************************************************************** |
James Hawkins | 6a358c4 | 2004-07-13 23:33:14 +0000 | [diff] [blame^] | 146 | * RegCreateKeyExW [ADVAPI32.@] |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 147 | * |
Jon Griffiths | 50ce084 | 2004-04-23 21:32:34 +0000 | [diff] [blame] | 148 | * See RegCreateKeyExA. |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 149 | */ |
Daniel Marmier | c33e4c4 | 2003-10-21 23:44:37 +0000 | [diff] [blame] | 150 | DWORD WINAPI RegCreateKeyExW( HKEY hkey, LPCWSTR name, DWORD reserved, LPCWSTR class, |
Vincent Béron | 9a62491 | 2002-05-31 23:06:46 +0000 | [diff] [blame] | 151 | DWORD options, REGSAM access, SECURITY_ATTRIBUTES *sa, |
Alexandre Julliard | 5cf56a3 | 2002-10-03 19:46:27 +0000 | [diff] [blame] | 152 | PHKEY retkey, LPDWORD dispos ) |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 153 | { |
Alexandre Julliard | bcf393a | 2000-10-01 01:44:50 +0000 | [diff] [blame] | 154 | OBJECT_ATTRIBUTES attr; |
| 155 | UNICODE_STRING nameW, classW; |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 156 | |
| 157 | if (reserved) return ERROR_INVALID_PARAMETER; |
Juergen Schmied | a44e0b0 | 2002-05-09 19:39:10 +0000 | [diff] [blame] | 158 | 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] | 159 | if (!(hkey = get_special_root_hkey( hkey ))) return ERROR_INVALID_HANDLE; |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 160 | |
Alexandre Julliard | bcf393a | 2000-10-01 01:44:50 +0000 | [diff] [blame] | 161 | attr.Length = sizeof(attr); |
| 162 | attr.RootDirectory = hkey; |
| 163 | attr.ObjectName = &nameW; |
| 164 | attr.Attributes = 0; |
| 165 | attr.SecurityDescriptor = NULL; |
| 166 | attr.SecurityQualityOfService = NULL; |
| 167 | RtlInitUnicodeString( &nameW, name ); |
| 168 | RtlInitUnicodeString( &classW, class ); |
| 169 | |
| 170 | return RtlNtStatusToDosError( NtCreateKey( retkey, access, &attr, 0, |
| 171 | &classW, options, dispos ) ); |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 172 | } |
| 173 | |
| 174 | |
| 175 | /****************************************************************************** |
James Hawkins | 6a358c4 | 2004-07-13 23:33:14 +0000 | [diff] [blame^] | 176 | * RegCreateKeyExA [ADVAPI32.@] |
Juergen Schmied | a44e0b0 | 2002-05-09 19:39:10 +0000 | [diff] [blame] | 177 | * |
Jon Griffiths | 50ce084 | 2004-04-23 21:32:34 +0000 | [diff] [blame] | 178 | * Open a registry key, creating it if it doesn't exist. |
| 179 | * |
| 180 | * PARAMS |
James Hawkins | 6a358c4 | 2004-07-13 23:33:14 +0000 | [diff] [blame^] | 181 | * hkey [I] Handle of the parent registry key |
| 182 | * name [I] Name of the new key to open or create |
| 183 | * reserved [I] Reserved, pass 0 |
| 184 | * class [I] The object type of the new key |
| 185 | * options [I] Flags controlling the key creation (REG_OPTION_* flags from "winnt.h") |
| 186 | * access [I] Access level desired |
| 187 | * sa [I] Security attributes for the key |
| 188 | * retkey [O] Destination for the resulting handle |
| 189 | * dispos [O] Receives REG_CREATED_NEW_KEY or REG_OPENED_EXISTING_KEY |
Jon Griffiths | 50ce084 | 2004-04-23 21:32:34 +0000 | [diff] [blame] | 190 | * |
| 191 | * RETURNS |
James Hawkins | 6a358c4 | 2004-07-13 23:33:14 +0000 | [diff] [blame^] | 192 | * Success: ERROR_SUCCESS. |
| 193 | * Failure: A standard Win32 error code. retkey remains untouched. |
Jon Griffiths | 50ce084 | 2004-04-23 21:32:34 +0000 | [diff] [blame] | 194 | * |
| 195 | * FIXME |
James Hawkins | 6a358c4 | 2004-07-13 23:33:14 +0000 | [diff] [blame^] | 196 | * MAXIMUM_ALLOWED in access mask not supported by server |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 197 | */ |
Daniel Marmier | c33e4c4 | 2003-10-21 23:44:37 +0000 | [diff] [blame] | 198 | DWORD WINAPI RegCreateKeyExA( HKEY hkey, LPCSTR name, DWORD reserved, LPCSTR class, |
Vincent Béron | 9a62491 | 2002-05-31 23:06:46 +0000 | [diff] [blame] | 199 | DWORD options, REGSAM access, SECURITY_ATTRIBUTES *sa, |
Alexandre Julliard | 5cf56a3 | 2002-10-03 19:46:27 +0000 | [diff] [blame] | 200 | PHKEY retkey, LPDWORD dispos ) |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 201 | { |
Alexandre Julliard | bcf393a | 2000-10-01 01:44:50 +0000 | [diff] [blame] | 202 | OBJECT_ATTRIBUTES attr; |
Alexandre Julliard | ab5e975 | 2001-03-23 19:12:01 +0000 | [diff] [blame] | 203 | UNICODE_STRING classW; |
Alexandre Julliard | bcf393a | 2000-10-01 01:44:50 +0000 | [diff] [blame] | 204 | ANSI_STRING nameA, classA; |
| 205 | NTSTATUS status; |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 206 | |
| 207 | if (reserved) return ERROR_INVALID_PARAMETER; |
Michael Cardenas | 7dbce65 | 2002-03-21 01:24:52 +0000 | [diff] [blame] | 208 | if (!is_version_nt()) access = KEY_ALL_ACCESS; /* Win95 ignores the access mask */ |
Juergen Schmied | a44e0b0 | 2002-05-09 19:39:10 +0000 | [diff] [blame] | 209 | 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] | 210 | if (!(hkey = get_special_root_hkey( hkey ))) return ERROR_INVALID_HANDLE; |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 211 | |
Alexandre Julliard | bcf393a | 2000-10-01 01:44:50 +0000 | [diff] [blame] | 212 | attr.Length = sizeof(attr); |
| 213 | attr.RootDirectory = hkey; |
Alexandre Julliard | ab5e975 | 2001-03-23 19:12:01 +0000 | [diff] [blame] | 214 | attr.ObjectName = &NtCurrentTeb()->StaticUnicodeString; |
Alexandre Julliard | bcf393a | 2000-10-01 01:44:50 +0000 | [diff] [blame] | 215 | attr.Attributes = 0; |
| 216 | attr.SecurityDescriptor = NULL; |
| 217 | attr.SecurityQualityOfService = NULL; |
| 218 | RtlInitAnsiString( &nameA, name ); |
| 219 | RtlInitAnsiString( &classA, class ); |
| 220 | |
Alexandre Julliard | ab5e975 | 2001-03-23 19:12:01 +0000 | [diff] [blame] | 221 | if (!(status = RtlAnsiStringToUnicodeString( &NtCurrentTeb()->StaticUnicodeString, |
| 222 | &nameA, FALSE ))) |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 223 | { |
Alexandre Julliard | bcf393a | 2000-10-01 01:44:50 +0000 | [diff] [blame] | 224 | if (!(status = RtlAnsiStringToUnicodeString( &classW, &classA, TRUE ))) |
| 225 | { |
| 226 | status = NtCreateKey( retkey, access, &attr, 0, &classW, options, dispos ); |
| 227 | RtlFreeUnicodeString( &classW ); |
| 228 | } |
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 | return RtlNtStatusToDosError( status ); |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 231 | } |
| 232 | |
| 233 | |
| 234 | /****************************************************************************** |
James Hawkins | 6a358c4 | 2004-07-13 23:33:14 +0000 | [diff] [blame^] | 235 | * RegCreateKeyW [ADVAPI32.@] |
| 236 | * |
| 237 | * Creates the specified reg key. |
| 238 | * |
| 239 | * PARAMS |
| 240 | * hKey [I] Handle to an open key. |
| 241 | * lpSubKey [I] Name of a key that will be opened or created. |
| 242 | * phkResult [O] Receives a handle to the opened or created key. |
| 243 | * |
| 244 | * RETURNS |
| 245 | * Success: ERROR_SUCCESS |
| 246 | * Failure: nonzero error code defined in Winerror.h |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 247 | */ |
James Hawkins | 6a358c4 | 2004-07-13 23:33:14 +0000 | [diff] [blame^] | 248 | DWORD WINAPI RegCreateKeyW( HKEY hkey, LPCWSTR lpSubKey, PHKEY phkResult ) |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 249 | { |
| 250 | /* FIXME: previous implementation converted ERROR_INVALID_HANDLE to ERROR_BADKEY, */ |
| 251 | /* 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^] | 252 | return RegCreateKeyExW( hkey, lpSubKey, 0, NULL, REG_OPTION_NON_VOLATILE, |
| 253 | KEY_ALL_ACCESS, NULL, phkResult, NULL ); |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 254 | } |
| 255 | |
| 256 | |
| 257 | /****************************************************************************** |
James Hawkins | 6a358c4 | 2004-07-13 23:33:14 +0000 | [diff] [blame^] | 258 | * RegCreateKeyA [ADVAPI32.@] |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 259 | * |
James Hawkins | 6a358c4 | 2004-07-13 23:33:14 +0000 | [diff] [blame^] | 260 | * see RegCreateKeyW |
| 261 | */ |
| 262 | DWORD WINAPI RegCreateKeyA( HKEY hkey, LPCSTR lpSubKey, PHKEY phkResult ) |
| 263 | { |
| 264 | return RegCreateKeyExA( hkey, lpSubKey, 0, NULL, REG_OPTION_NON_VOLATILE, |
| 265 | KEY_ALL_ACCESS, NULL, phkResult, NULL ); |
| 266 | } |
| 267 | |
| 268 | |
| 269 | |
| 270 | /****************************************************************************** |
| 271 | * RegOpenKeyExW [ADVAPI32.@] |
| 272 | * |
Jon Griffiths | 50ce084 | 2004-04-23 21:32:34 +0000 | [diff] [blame] | 273 | * See RegOpenKeyExA. |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 274 | */ |
Alexandre Julliard | 5cf56a3 | 2002-10-03 19:46:27 +0000 | [diff] [blame] | 275 | 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] | 276 | { |
Alexandre Julliard | bcf393a | 2000-10-01 01:44:50 +0000 | [diff] [blame] | 277 | OBJECT_ATTRIBUTES attr; |
| 278 | UNICODE_STRING nameW; |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 279 | |
Alexandre Julliard | f2ef2c2 | 2002-09-13 21:42:28 +0000 | [diff] [blame] | 280 | if (!(hkey = get_special_root_hkey( hkey ))) return ERROR_INVALID_HANDLE; |
| 281 | |
Alexandre Julliard | bcf393a | 2000-10-01 01:44:50 +0000 | [diff] [blame] | 282 | attr.Length = sizeof(attr); |
| 283 | attr.RootDirectory = hkey; |
| 284 | attr.ObjectName = &nameW; |
| 285 | attr.Attributes = 0; |
| 286 | attr.SecurityDescriptor = NULL; |
| 287 | attr.SecurityQualityOfService = NULL; |
| 288 | RtlInitUnicodeString( &nameW, name ); |
| 289 | return RtlNtStatusToDosError( NtOpenKey( retkey, access, &attr ) ); |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 290 | } |
| 291 | |
| 292 | |
| 293 | /****************************************************************************** |
James Hawkins | 6a358c4 | 2004-07-13 23:33:14 +0000 | [diff] [blame^] | 294 | * RegOpenKeyExA [ADVAPI32.@] |
Jon Griffiths | 50ce084 | 2004-04-23 21:32:34 +0000 | [diff] [blame] | 295 | * |
| 296 | * Open a registry key. |
| 297 | * |
| 298 | * PARAMS |
James Hawkins | 6a358c4 | 2004-07-13 23:33:14 +0000 | [diff] [blame^] | 299 | * hkey [I] Handle of open key |
| 300 | * name [I] Name of subkey to open |
| 301 | * reserved [I] Reserved - must be zero |
| 302 | * access [I] Security access mask |
| 303 | * retkey [O] Handle to open key |
Jon Griffiths | 50ce084 | 2004-04-23 21:32:34 +0000 | [diff] [blame] | 304 | * |
| 305 | * RETURNS |
James Hawkins | 6a358c4 | 2004-07-13 23:33:14 +0000 | [diff] [blame^] | 306 | * Success: ERROR_SUCCESS |
| 307 | * Failure: A standard Win32 error code. retkey is set to 0. |
Jon Griffiths | 50ce084 | 2004-04-23 21:32:34 +0000 | [diff] [blame] | 308 | * |
| 309 | * NOTES |
James Hawkins | 6a358c4 | 2004-07-13 23:33:14 +0000 | [diff] [blame^] | 310 | * Unlike RegCreateKeyExA(), this function will not create the key if it |
| 311 | * does not exist. |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 312 | */ |
Alexandre Julliard | 5cf56a3 | 2002-10-03 19:46:27 +0000 | [diff] [blame] | 313 | 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] | 314 | { |
Alexandre Julliard | bcf393a | 2000-10-01 01:44:50 +0000 | [diff] [blame] | 315 | OBJECT_ATTRIBUTES attr; |
Alexandre Julliard | bcf393a | 2000-10-01 01:44:50 +0000 | [diff] [blame] | 316 | STRING nameA; |
| 317 | NTSTATUS status; |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 318 | |
Michael Cardenas | 7dbce65 | 2002-03-21 01:24:52 +0000 | [diff] [blame] | 319 | if (!is_version_nt()) access = KEY_ALL_ACCESS; /* Win95 ignores the access mask */ |
| 320 | |
Alexandre Julliard | f2ef2c2 | 2002-09-13 21:42:28 +0000 | [diff] [blame] | 321 | if (!(hkey = get_special_root_hkey( hkey ))) return ERROR_INVALID_HANDLE; |
| 322 | |
Alexandre Julliard | bcf393a | 2000-10-01 01:44:50 +0000 | [diff] [blame] | 323 | attr.Length = sizeof(attr); |
| 324 | attr.RootDirectory = hkey; |
Alexandre Julliard | ab5e975 | 2001-03-23 19:12:01 +0000 | [diff] [blame] | 325 | attr.ObjectName = &NtCurrentTeb()->StaticUnicodeString; |
Alexandre Julliard | bcf393a | 2000-10-01 01:44:50 +0000 | [diff] [blame] | 326 | attr.Attributes = 0; |
| 327 | attr.SecurityDescriptor = NULL; |
| 328 | attr.SecurityQualityOfService = NULL; |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 329 | |
Alexandre Julliard | bcf393a | 2000-10-01 01:44:50 +0000 | [diff] [blame] | 330 | RtlInitAnsiString( &nameA, name ); |
Alexandre Julliard | ab5e975 | 2001-03-23 19:12:01 +0000 | [diff] [blame] | 331 | if (!(status = RtlAnsiStringToUnicodeString( &NtCurrentTeb()->StaticUnicodeString, |
| 332 | &nameA, FALSE ))) |
Alexandre Julliard | bcf393a | 2000-10-01 01:44:50 +0000 | [diff] [blame] | 333 | { |
| 334 | status = NtOpenKey( retkey, access, &attr ); |
Alexandre Julliard | bcf393a | 2000-10-01 01:44:50 +0000 | [diff] [blame] | 335 | } |
| 336 | return RtlNtStatusToDosError( status ); |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 337 | } |
| 338 | |
| 339 | |
| 340 | /****************************************************************************** |
James Hawkins | 6a358c4 | 2004-07-13 23:33:14 +0000 | [diff] [blame^] | 341 | * RegOpenKeyW [ADVAPI32.@] |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 342 | * |
Jon Griffiths | 50ce084 | 2004-04-23 21:32:34 +0000 | [diff] [blame] | 343 | * See RegOpenKeyA. |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 344 | */ |
Alexandre Julliard | 5cf56a3 | 2002-10-03 19:46:27 +0000 | [diff] [blame] | 345 | DWORD WINAPI RegOpenKeyW( HKEY hkey, LPCWSTR name, PHKEY retkey ) |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 346 | { |
| 347 | return RegOpenKeyExW( hkey, name, 0, KEY_ALL_ACCESS, retkey ); |
| 348 | } |
| 349 | |
| 350 | |
| 351 | /****************************************************************************** |
James Hawkins | 6a358c4 | 2004-07-13 23:33:14 +0000 | [diff] [blame^] | 352 | * RegOpenKeyA [ADVAPI32.@] |
Jon Griffiths | 50ce084 | 2004-04-23 21:32:34 +0000 | [diff] [blame] | 353 | * |
| 354 | * Open a registry key. |
| 355 | * |
| 356 | * PARAMS |
James Hawkins | 6a358c4 | 2004-07-13 23:33:14 +0000 | [diff] [blame^] | 357 | * hkey [I] Handle of parent key to open the new key under |
| 358 | * name [I] Name of the key under hkey to open |
| 359 | * retkey [O] Destination for the resulting Handle |
Jon Griffiths | 50ce084 | 2004-04-23 21:32:34 +0000 | [diff] [blame] | 360 | * |
| 361 | * RETURNS |
James Hawkins | 6a358c4 | 2004-07-13 23:33:14 +0000 | [diff] [blame^] | 362 | * Success: ERROR_SUCCESS |
| 363 | * Failure: A standard Win32 error code. retkey is set to 0. |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 364 | */ |
Alexandre Julliard | 5cf56a3 | 2002-10-03 19:46:27 +0000 | [diff] [blame] | 365 | DWORD WINAPI RegOpenKeyA( HKEY hkey, LPCSTR name, PHKEY retkey ) |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 366 | { |
| 367 | return RegOpenKeyExA( hkey, name, 0, KEY_ALL_ACCESS, retkey ); |
| 368 | } |
| 369 | |
| 370 | |
David Elliott | 44f84b5 | 2000-10-29 01:24:54 +0000 | [diff] [blame] | 371 | /****************************************************************************** |
James Hawkins | 6a358c4 | 2004-07-13 23:33:14 +0000 | [diff] [blame^] | 372 | * RegOpenCurrentUser [ADVAPI32.@] |
| 373 | * |
David Elliott | 44f84b5 | 2000-10-29 01:24:54 +0000 | [diff] [blame] | 374 | * FIXME: This function is supposed to retrieve a handle to the |
| 375 | * HKEY_CURRENT_USER for the user the current thread is impersonating. |
| 376 | * Since Wine does not currently allow threads to impersonate other users, |
| 377 | * this stub should work fine. |
| 378 | */ |
| 379 | DWORD WINAPI RegOpenCurrentUser( REGSAM access, PHKEY retkey ) |
| 380 | { |
| 381 | return RegOpenKeyExA( HKEY_CURRENT_USER, "", 0, access, retkey ); |
| 382 | } |
| 383 | |
| 384 | |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 385 | |
| 386 | /****************************************************************************** |
James Hawkins | 6a358c4 | 2004-07-13 23:33:14 +0000 | [diff] [blame^] | 387 | * RegEnumKeyExW [ADVAPI32.@] |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 388 | * |
| 389 | * PARAMS |
James Hawkins | 6a358c4 | 2004-07-13 23:33:14 +0000 | [diff] [blame^] | 390 | * hkey [I] Handle to key to enumerate |
| 391 | * index [I] Index of subkey to enumerate |
| 392 | * name [O] Buffer for subkey name |
| 393 | * name_len [O] Size of subkey buffer |
| 394 | * reserved [I] Reserved |
| 395 | * class [O] Buffer for class string |
| 396 | * class_len [O] Size of class buffer |
| 397 | * ft [O] Time key last written to |
| 398 | * |
| 399 | * RETURNS |
| 400 | * Success: ERROR_SUCCESS |
| 401 | * Failure: System error code. If there are no more subkeys available, the |
| 402 | * function returns ERROR_NO_MORE_ITEMS. |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 403 | */ |
| 404 | DWORD WINAPI RegEnumKeyExW( HKEY hkey, DWORD index, LPWSTR name, LPDWORD name_len, |
| 405 | LPDWORD reserved, LPWSTR class, LPDWORD class_len, FILETIME *ft ) |
| 406 | { |
Alexandre Julliard | 454355e | 2000-10-02 03:46:58 +0000 | [diff] [blame] | 407 | NTSTATUS status; |
| 408 | char buffer[256], *buf_ptr = buffer; |
| 409 | KEY_NODE_INFORMATION *info = (KEY_NODE_INFORMATION *)buffer; |
| 410 | DWORD total_size; |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 411 | |
Michael Stefaniuc | cbacde5 | 2002-10-25 19:17:33 +0000 | [diff] [blame] | 412 | 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] | 413 | name_len ? *name_len : -1, reserved, class, class_len, ft ); |
| 414 | |
| 415 | if (reserved) return ERROR_INVALID_PARAMETER; |
Alexandre Julliard | f2ef2c2 | 2002-09-13 21:42:28 +0000 | [diff] [blame] | 416 | if (!(hkey = get_special_root_hkey( hkey ))) return ERROR_INVALID_HANDLE; |
Rein Klazes | 0bb6fdd | 2002-07-05 01:21:13 +0000 | [diff] [blame] | 417 | |
Alexandre Julliard | 454355e | 2000-10-02 03:46:58 +0000 | [diff] [blame] | 418 | status = NtEnumerateKey( hkey, index, KeyNodeInformation, |
| 419 | buffer, sizeof(buffer), &total_size ); |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 420 | |
Alexandre Julliard | 454355e | 2000-10-02 03:46:58 +0000 | [diff] [blame] | 421 | while (status == STATUS_BUFFER_OVERFLOW) |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 422 | { |
Alexandre Julliard | 454355e | 2000-10-02 03:46:58 +0000 | [diff] [blame] | 423 | /* retry with a dynamically allocated buffer */ |
| 424 | if (buf_ptr != buffer) HeapFree( GetProcessHeap(), 0, buf_ptr ); |
| 425 | if (!(buf_ptr = HeapAlloc( GetProcessHeap(), 0, total_size ))) |
| 426 | return ERROR_NOT_ENOUGH_MEMORY; |
| 427 | info = (KEY_NODE_INFORMATION *)buf_ptr; |
| 428 | status = NtEnumerateKey( hkey, index, KeyNodeInformation, |
| 429 | buf_ptr, total_size, &total_size ); |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 430 | } |
Alexandre Julliard | 454355e | 2000-10-02 03:46:58 +0000 | [diff] [blame] | 431 | |
| 432 | if (!status) |
| 433 | { |
| 434 | DWORD len = info->NameLength / sizeof(WCHAR); |
| 435 | DWORD cls_len = info->ClassLength / sizeof(WCHAR); |
| 436 | |
Dmitry Timoshkov | 6b6596a | 2001-11-23 18:44:43 +0000 | [diff] [blame] | 437 | if (ft) *ft = *(FILETIME *)&info->LastWriteTime; |
Alexandre Julliard | 454355e | 2000-10-02 03:46:58 +0000 | [diff] [blame] | 438 | |
Aric Stewart | 20a4cc3 | 2002-02-05 19:45:55 +0000 | [diff] [blame] | 439 | if (len >= *name_len || (class && class_len && (cls_len >= *class_len))) |
Alexandre Julliard | 454355e | 2000-10-02 03:46:58 +0000 | [diff] [blame] | 440 | status = STATUS_BUFFER_OVERFLOW; |
| 441 | else |
| 442 | { |
| 443 | *name_len = len; |
| 444 | memcpy( name, info->Name, info->NameLength ); |
| 445 | name[len] = 0; |
| 446 | if (class_len) |
| 447 | { |
| 448 | *class_len = cls_len; |
| 449 | if (class) |
| 450 | { |
| 451 | memcpy( class, buf_ptr + info->ClassOffset, info->ClassLength ); |
| 452 | class[cls_len] = 0; |
| 453 | } |
| 454 | } |
| 455 | } |
| 456 | } |
| 457 | |
| 458 | if (buf_ptr != buffer) HeapFree( GetProcessHeap(), 0, buf_ptr ); |
| 459 | return RtlNtStatusToDosError( status ); |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 460 | } |
| 461 | |
| 462 | |
| 463 | /****************************************************************************** |
James Hawkins | 6a358c4 | 2004-07-13 23:33:14 +0000 | [diff] [blame^] | 464 | * RegEnumKeyExA [ADVAPI32.@] |
| 465 | * |
| 466 | * see RegEnumKeyExW |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 467 | */ |
| 468 | DWORD WINAPI RegEnumKeyExA( HKEY hkey, DWORD index, LPSTR name, LPDWORD name_len, |
| 469 | LPDWORD reserved, LPSTR class, LPDWORD class_len, FILETIME *ft ) |
| 470 | { |
Alexandre Julliard | 454355e | 2000-10-02 03:46:58 +0000 | [diff] [blame] | 471 | NTSTATUS status; |
| 472 | char buffer[256], *buf_ptr = buffer; |
| 473 | KEY_NODE_INFORMATION *info = (KEY_NODE_INFORMATION *)buffer; |
| 474 | DWORD total_size; |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 475 | |
Michael Stefaniuc | cbacde5 | 2002-10-25 19:17:33 +0000 | [diff] [blame] | 476 | 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] | 477 | name_len ? *name_len : -1, reserved, class, class_len, ft ); |
| 478 | |
| 479 | if (reserved) return ERROR_INVALID_PARAMETER; |
Alexandre Julliard | f2ef2c2 | 2002-09-13 21:42:28 +0000 | [diff] [blame] | 480 | if (!(hkey = get_special_root_hkey( hkey ))) return ERROR_INVALID_HANDLE; |
Rein Klazes | 0bb6fdd | 2002-07-05 01:21:13 +0000 | [diff] [blame] | 481 | |
Alexandre Julliard | 454355e | 2000-10-02 03:46:58 +0000 | [diff] [blame] | 482 | status = NtEnumerateKey( hkey, index, KeyNodeInformation, |
| 483 | buffer, sizeof(buffer), &total_size ); |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 484 | |
Alexandre Julliard | 454355e | 2000-10-02 03:46:58 +0000 | [diff] [blame] | 485 | while (status == STATUS_BUFFER_OVERFLOW) |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 486 | { |
Alexandre Julliard | 454355e | 2000-10-02 03:46:58 +0000 | [diff] [blame] | 487 | /* retry with a dynamically allocated buffer */ |
| 488 | if (buf_ptr != buffer) HeapFree( GetProcessHeap(), 0, buf_ptr ); |
| 489 | if (!(buf_ptr = HeapAlloc( GetProcessHeap(), 0, total_size ))) |
| 490 | return ERROR_NOT_ENOUGH_MEMORY; |
| 491 | info = (KEY_NODE_INFORMATION *)buf_ptr; |
| 492 | status = NtEnumerateKey( hkey, index, KeyNodeInformation, |
| 493 | buf_ptr, total_size, &total_size ); |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 494 | } |
Alexandre Julliard | 454355e | 2000-10-02 03:46:58 +0000 | [diff] [blame] | 495 | |
| 496 | if (!status) |
| 497 | { |
Alexandre Julliard | 60fd03d | 2001-12-05 22:18:48 +0000 | [diff] [blame] | 498 | DWORD len, cls_len; |
Alexandre Julliard | 454355e | 2000-10-02 03:46:58 +0000 | [diff] [blame] | 499 | |
Alexandre Julliard | 60fd03d | 2001-12-05 22:18:48 +0000 | [diff] [blame] | 500 | RtlUnicodeToMultiByteSize( &len, info->Name, info->NameLength ); |
| 501 | RtlUnicodeToMultiByteSize( &cls_len, (WCHAR *)(buf_ptr + info->ClassOffset), |
| 502 | info->ClassLength ); |
Dmitry Timoshkov | 6b6596a | 2001-11-23 18:44:43 +0000 | [diff] [blame] | 503 | if (ft) *ft = *(FILETIME *)&info->LastWriteTime; |
Alexandre Julliard | 454355e | 2000-10-02 03:46:58 +0000 | [diff] [blame] | 504 | |
Aric Stewart | 20a4cc3 | 2002-02-05 19:45:55 +0000 | [diff] [blame] | 505 | if (len >= *name_len || (class && class_len && (cls_len >= *class_len))) |
Alexandre Julliard | 454355e | 2000-10-02 03:46:58 +0000 | [diff] [blame] | 506 | status = STATUS_BUFFER_OVERFLOW; |
| 507 | else |
| 508 | { |
| 509 | *name_len = len; |
Alexandre Julliard | 60fd03d | 2001-12-05 22:18:48 +0000 | [diff] [blame] | 510 | RtlUnicodeToMultiByteN( name, len, NULL, info->Name, info->NameLength ); |
Alexandre Julliard | 454355e | 2000-10-02 03:46:58 +0000 | [diff] [blame] | 511 | name[len] = 0; |
| 512 | if (class_len) |
| 513 | { |
| 514 | *class_len = cls_len; |
| 515 | if (class) |
| 516 | { |
Alexandre Julliard | 60fd03d | 2001-12-05 22:18:48 +0000 | [diff] [blame] | 517 | RtlUnicodeToMultiByteN( class, cls_len, NULL, |
| 518 | (WCHAR *)(buf_ptr + info->ClassOffset), |
| 519 | info->ClassLength ); |
Alexandre Julliard | 454355e | 2000-10-02 03:46:58 +0000 | [diff] [blame] | 520 | class[cls_len] = 0; |
| 521 | } |
| 522 | } |
| 523 | } |
| 524 | } |
| 525 | |
| 526 | if (buf_ptr != buffer) HeapFree( GetProcessHeap(), 0, buf_ptr ); |
| 527 | return RtlNtStatusToDosError( status ); |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 528 | } |
| 529 | |
| 530 | |
| 531 | /****************************************************************************** |
James Hawkins | 6a358c4 | 2004-07-13 23:33:14 +0000 | [diff] [blame^] | 532 | * RegEnumKeyW [ADVAPI32.@] |
| 533 | * |
| 534 | * Enumerates subkyes of the specified open reg key. |
| 535 | * |
| 536 | * PARAMS |
| 537 | * hKey [I] Handle to an open key. |
| 538 | * dwIndex [I] Index of the subkey of hKey to retrieve. |
| 539 | * lpName [O] Name of the subkey. |
| 540 | * cchName [I] Size of lpName in TCHARS. |
| 541 | * |
| 542 | * RETURNS |
| 543 | * Success: ERROR_SUCCESS |
| 544 | * Failure: system error code. If there are no more subkeys available, the |
| 545 | * function returns ERROR_NO_MORE_ITEMS. |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 546 | */ |
| 547 | DWORD WINAPI RegEnumKeyW( HKEY hkey, DWORD index, LPWSTR name, DWORD name_len ) |
| 548 | { |
| 549 | return RegEnumKeyExW( hkey, index, name, &name_len, NULL, NULL, NULL, NULL ); |
| 550 | } |
| 551 | |
| 552 | |
| 553 | /****************************************************************************** |
James Hawkins | 6a358c4 | 2004-07-13 23:33:14 +0000 | [diff] [blame^] | 554 | * RegEnumKeyA [ADVAPI32.@] |
| 555 | * |
| 556 | * see RegEnumKeyW |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 557 | */ |
| 558 | DWORD WINAPI RegEnumKeyA( HKEY hkey, DWORD index, LPSTR name, DWORD name_len ) |
| 559 | { |
| 560 | return RegEnumKeyExA( hkey, index, name, &name_len, NULL, NULL, NULL, NULL ); |
| 561 | } |
| 562 | |
| 563 | |
| 564 | /****************************************************************************** |
James Hawkins | 6a358c4 | 2004-07-13 23:33:14 +0000 | [diff] [blame^] | 565 | * RegQueryInfoKeyW [ADVAPI32.@] |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 566 | * |
| 567 | * PARAMS |
| 568 | * hkey [I] Handle to key to query |
| 569 | * class [O] Buffer for class string |
| 570 | * class_len [O] Size of class string buffer |
| 571 | * reserved [I] Reserved |
| 572 | * subkeys [O] Buffer for number of subkeys |
| 573 | * max_subkey [O] Buffer for longest subkey name length |
| 574 | * max_class [O] Buffer for longest class string length |
| 575 | * values [O] Buffer for number of value entries |
| 576 | * max_value [O] Buffer for longest value name length |
| 577 | * max_data [O] Buffer for longest value data length |
| 578 | * security [O] Buffer for security descriptor length |
| 579 | * modif [O] Modification time |
| 580 | * |
Vincent Béron | 9a62491 | 2002-05-31 23:06:46 +0000 | [diff] [blame] | 581 | * - win95 allows class to be valid and class_len to be NULL |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 582 | * - winnt returns ERROR_INVALID_PARAMETER if class is valid and class_len is NULL |
Vincent Béron | 9a62491 | 2002-05-31 23:06:46 +0000 | [diff] [blame] | 583 | * - both allow class to be NULL and class_len to be NULL |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 584 | * (it's hard to test validity, so test !NULL instead) |
| 585 | */ |
| 586 | DWORD WINAPI RegQueryInfoKeyW( HKEY hkey, LPWSTR class, LPDWORD class_len, LPDWORD reserved, |
| 587 | LPDWORD subkeys, LPDWORD max_subkey, LPDWORD max_class, |
| 588 | LPDWORD values, LPDWORD max_value, LPDWORD max_data, |
| 589 | LPDWORD security, FILETIME *modif ) |
| 590 | { |
Alexandre Julliard | 454355e | 2000-10-02 03:46:58 +0000 | [diff] [blame] | 591 | NTSTATUS status; |
| 592 | char buffer[256], *buf_ptr = buffer; |
| 593 | KEY_FULL_INFORMATION *info = (KEY_FULL_INFORMATION *)buffer; |
| 594 | DWORD total_size; |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 595 | |
Michael Stefaniuc | cbacde5 | 2002-10-25 19:17:33 +0000 | [diff] [blame] | 596 | 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] | 597 | reserved, subkeys, max_subkey, values, max_value, max_data, security, modif ); |
| 598 | |
Michael Cardenas | 7dbce65 | 2002-03-21 01:24:52 +0000 | [diff] [blame] | 599 | if (class && !class_len && is_version_nt()) return ERROR_INVALID_PARAMETER; |
Alexandre Julliard | f2ef2c2 | 2002-09-13 21:42:28 +0000 | [diff] [blame] | 600 | if (!(hkey = get_special_root_hkey( hkey ))) return ERROR_INVALID_HANDLE; |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 601 | |
Alexandre Julliard | 454355e | 2000-10-02 03:46:58 +0000 | [diff] [blame] | 602 | status = NtQueryKey( hkey, KeyFullInformation, buffer, sizeof(buffer), &total_size ); |
Alexandre Julliard | c661583 | 2001-02-14 21:45:52 +0000 | [diff] [blame] | 603 | if (status && status != STATUS_BUFFER_OVERFLOW) goto done; |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 604 | |
| 605 | if (class) |
| 606 | { |
Alexandre Julliard | 454355e | 2000-10-02 03:46:58 +0000 | [diff] [blame] | 607 | /* retry with a dynamically allocated buffer */ |
| 608 | while (status == STATUS_BUFFER_OVERFLOW) |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 609 | { |
Alexandre Julliard | 454355e | 2000-10-02 03:46:58 +0000 | [diff] [blame] | 610 | if (buf_ptr != buffer) HeapFree( GetProcessHeap(), 0, buf_ptr ); |
| 611 | if (!(buf_ptr = HeapAlloc( GetProcessHeap(), 0, total_size ))) |
| 612 | return ERROR_NOT_ENOUGH_MEMORY; |
| 613 | info = (KEY_FULL_INFORMATION *)buf_ptr; |
| 614 | status = NtQueryKey( hkey, KeyFullInformation, buf_ptr, total_size, &total_size ); |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 615 | } |
Alexandre Julliard | 454355e | 2000-10-02 03:46:58 +0000 | [diff] [blame] | 616 | |
Alexandre Julliard | c661583 | 2001-02-14 21:45:52 +0000 | [diff] [blame] | 617 | if (status) goto done; |
| 618 | |
| 619 | if (class_len && (info->ClassLength/sizeof(WCHAR) + 1 > *class_len)) |
Alexandre Julliard | 454355e | 2000-10-02 03:46:58 +0000 | [diff] [blame] | 620 | { |
Alexandre Julliard | c661583 | 2001-02-14 21:45:52 +0000 | [diff] [blame] | 621 | status = STATUS_BUFFER_OVERFLOW; |
| 622 | } |
| 623 | else |
| 624 | { |
| 625 | memcpy( class, buf_ptr + info->ClassOffset, info->ClassLength ); |
| 626 | class[info->ClassLength/sizeof(WCHAR)] = 0; |
Alexandre Julliard | 454355e | 2000-10-02 03:46:58 +0000 | [diff] [blame] | 627 | } |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 628 | } |
Alexandre Julliard | c661583 | 2001-02-14 21:45:52 +0000 | [diff] [blame] | 629 | else status = STATUS_SUCCESS; |
Alexandre Julliard | 454355e | 2000-10-02 03:46:58 +0000 | [diff] [blame] | 630 | |
Alexandre Julliard | c661583 | 2001-02-14 21:45:52 +0000 | [diff] [blame] | 631 | if (class_len) *class_len = info->ClassLength / sizeof(WCHAR); |
| 632 | if (subkeys) *subkeys = info->SubKeys; |
| 633 | if (max_subkey) *max_subkey = info->MaxNameLen; |
| 634 | if (max_class) *max_class = info->MaxClassLen; |
| 635 | if (values) *values = info->Values; |
| 636 | if (max_value) *max_value = info->MaxValueNameLen; |
| 637 | if (max_data) *max_data = info->MaxValueDataLen; |
Dmitry Timoshkov | 6b6596a | 2001-11-23 18:44:43 +0000 | [diff] [blame] | 638 | if (modif) *modif = *(FILETIME *)&info->LastWriteTime; |
Alexandre Julliard | 454355e | 2000-10-02 03:46:58 +0000 | [diff] [blame] | 639 | |
Alexandre Julliard | c661583 | 2001-02-14 21:45:52 +0000 | [diff] [blame] | 640 | done: |
Alexandre Julliard | 454355e | 2000-10-02 03:46:58 +0000 | [diff] [blame] | 641 | if (buf_ptr != buffer) HeapFree( GetProcessHeap(), 0, buf_ptr ); |
| 642 | return RtlNtStatusToDosError( status ); |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 643 | } |
| 644 | |
| 645 | |
| 646 | /****************************************************************************** |
James Hawkins | 6a358c4 | 2004-07-13 23:33:14 +0000 | [diff] [blame^] | 647 | * RegQueryMultipleValuesA [ADVAPI32.@] |
| 648 | * |
| 649 | * Retrieves the type and data for a list of value names associated with a key. |
| 650 | * |
| 651 | * PARAMS |
| 652 | * hKey [I] Handle to an open key. |
| 653 | * val_list [O] Array of VALENT structures that describes the entries. |
| 654 | * num_vals [I] Number of elements in val_list. |
| 655 | * lpValueBuf [O] Pointer to a buffer that receives the data for each value. |
| 656 | * ldwTotsize [I/O] Size of lpValueBuf. |
| 657 | * |
| 658 | * RETURNS |
| 659 | * Success: ERROR_SUCCESS. ldwTotsize contains num bytes copied. |
| 660 | * Failure: nonzero error code from Winerror.h ldwTotsize contains num needed |
| 661 | * bytes. |
Dominik Strasser | 751c454 | 2002-07-20 20:02:55 +0000 | [diff] [blame] | 662 | */ |
| 663 | DWORD WINAPI RegQueryMultipleValuesA(HKEY hkey, PVALENTA val_list, DWORD num_vals, |
| 664 | LPSTR lpValueBuf, LPDWORD ldwTotsize) |
| 665 | { |
| 666 | int i; |
| 667 | DWORD maxBytes = *ldwTotsize; |
| 668 | HRESULT status; |
| 669 | LPSTR bufptr = lpValueBuf; |
| 670 | *ldwTotsize = 0; |
| 671 | |
Michael Stefaniuc | cbacde5 | 2002-10-25 19:17:33 +0000 | [diff] [blame] | 672 | 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] | 673 | |
| 674 | for(i=0; i < num_vals; ++i) |
| 675 | { |
| 676 | |
| 677 | val_list[i].ve_valuelen=0; |
| 678 | status = RegQueryValueExA(hkey, val_list[i].ve_valuename, NULL, NULL, NULL, &val_list[i].ve_valuelen); |
| 679 | if(status != ERROR_SUCCESS) |
| 680 | { |
| 681 | return status; |
| 682 | } |
| 683 | |
| 684 | if(lpValueBuf != NULL && *ldwTotsize + val_list[i].ve_valuelen <= maxBytes) |
| 685 | { |
| 686 | status = RegQueryValueExA(hkey, val_list[i].ve_valuename, NULL, &val_list[i].ve_type, |
| 687 | bufptr, &val_list[i].ve_valuelen); |
| 688 | if(status != ERROR_SUCCESS) |
| 689 | { |
| 690 | return status; |
| 691 | } |
| 692 | |
| 693 | val_list[i].ve_valueptr = (DWORD_PTR)bufptr; |
| 694 | |
| 695 | bufptr += val_list[i].ve_valuelen; |
| 696 | } |
| 697 | |
| 698 | *ldwTotsize += val_list[i].ve_valuelen; |
| 699 | } |
| 700 | return lpValueBuf != NULL && *ldwTotsize <= maxBytes ? ERROR_SUCCESS : ERROR_MORE_DATA; |
| 701 | } |
| 702 | |
| 703 | |
| 704 | /****************************************************************************** |
James Hawkins | 6a358c4 | 2004-07-13 23:33:14 +0000 | [diff] [blame^] | 705 | * RegQueryMultipleValuesW [ADVAPI32.@] |
| 706 | * |
| 707 | * see RegQueryMultipleValuesA |
Dominik Strasser | 751c454 | 2002-07-20 20:02:55 +0000 | [diff] [blame] | 708 | */ |
| 709 | DWORD WINAPI RegQueryMultipleValuesW(HKEY hkey, PVALENTW val_list, DWORD num_vals, |
| 710 | LPWSTR lpValueBuf, LPDWORD ldwTotsize) |
| 711 | { |
| 712 | int i; |
| 713 | DWORD maxBytes = *ldwTotsize; |
| 714 | HRESULT status; |
| 715 | LPSTR bufptr = (LPSTR)lpValueBuf; |
| 716 | *ldwTotsize = 0; |
| 717 | |
Michael Stefaniuc | cbacde5 | 2002-10-25 19:17:33 +0000 | [diff] [blame] | 718 | 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] | 719 | |
| 720 | for(i=0; i < num_vals; ++i) |
| 721 | { |
| 722 | val_list[i].ve_valuelen=0; |
| 723 | status = RegQueryValueExW(hkey, val_list[i].ve_valuename, NULL, NULL, NULL, &val_list[i].ve_valuelen); |
| 724 | if(status != ERROR_SUCCESS) |
| 725 | { |
| 726 | return status; |
| 727 | } |
| 728 | |
| 729 | if(lpValueBuf != NULL && *ldwTotsize + val_list[i].ve_valuelen <= maxBytes) |
| 730 | { |
| 731 | status = RegQueryValueExW(hkey, val_list[i].ve_valuename, NULL, &val_list[i].ve_type, |
| 732 | bufptr, &val_list[i].ve_valuelen); |
| 733 | if(status != ERROR_SUCCESS) |
| 734 | { |
| 735 | return status; |
| 736 | } |
| 737 | |
| 738 | val_list[i].ve_valueptr = (DWORD_PTR)bufptr; |
| 739 | |
| 740 | bufptr += val_list[i].ve_valuelen; |
| 741 | } |
| 742 | |
| 743 | *ldwTotsize += val_list[i].ve_valuelen; |
| 744 | } |
| 745 | return lpValueBuf != NULL && *ldwTotsize <= maxBytes ? ERROR_SUCCESS : ERROR_MORE_DATA; |
| 746 | } |
| 747 | |
| 748 | /****************************************************************************** |
James Hawkins | 6a358c4 | 2004-07-13 23:33:14 +0000 | [diff] [blame^] | 749 | * RegQueryInfoKeyA [ADVAPI32.@] |
| 750 | * |
| 751 | * Retrieves information about a registry key. |
| 752 | * |
| 753 | * PARAMS |
| 754 | * hKey [I] Handle to an open key. |
| 755 | * lpClass [O] Class string of the key. |
| 756 | * lpcClass [I/O] size of lpClass. |
| 757 | * lpReserved [I] Reserved; must be NULL. |
| 758 | * lpcSubKeys [O] Number of subkeys contained by the key. |
| 759 | * lpcMaxSubKeyLen [O] Size of the key's subkey with the longest name. |
| 760 | * lpcMaxClassLen [O] Size of the longest string specifying a subkey |
| 761 | * class in TCHARS. |
| 762 | * lpcValues [O] Number of values associated with the key. |
| 763 | * lpcMaxValueNameLen [O] Size of the key's longest value name in TCHARS. |
| 764 | * lpcMaxValueLen [O] Longest data component among the key's values |
| 765 | * lpcbSecurityDescriptor [O] Size of the key's security descriptor. |
| 766 | * lpftLastWriteTime [O] FILETIME strucutre that is the last write time. |
| 767 | * |
| 768 | * RETURNS |
| 769 | * Success: ERROR_SUCCESS |
| 770 | * Failure: nonzero error code from Winerror.h |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 771 | */ |
| 772 | DWORD WINAPI RegQueryInfoKeyA( HKEY hkey, LPSTR class, LPDWORD class_len, LPDWORD reserved, |
| 773 | LPDWORD subkeys, LPDWORD max_subkey, LPDWORD max_class, |
| 774 | LPDWORD values, LPDWORD max_value, LPDWORD max_data, |
| 775 | LPDWORD security, FILETIME *modif ) |
| 776 | { |
Alexandre Julliard | 454355e | 2000-10-02 03:46:58 +0000 | [diff] [blame] | 777 | NTSTATUS status; |
| 778 | char buffer[256], *buf_ptr = buffer; |
| 779 | KEY_FULL_INFORMATION *info = (KEY_FULL_INFORMATION *)buffer; |
Alexandre Julliard | c661583 | 2001-02-14 21:45:52 +0000 | [diff] [blame] | 780 | DWORD total_size, len; |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 781 | |
Michael Stefaniuc | cbacde5 | 2002-10-25 19:17:33 +0000 | [diff] [blame] | 782 | 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] | 783 | reserved, subkeys, max_subkey, values, max_value, max_data, security, modif ); |
| 784 | |
Michael Cardenas | 7dbce65 | 2002-03-21 01:24:52 +0000 | [diff] [blame] | 785 | if (class && !class_len && is_version_nt()) return ERROR_INVALID_PARAMETER; |
Alexandre Julliard | f2ef2c2 | 2002-09-13 21:42:28 +0000 | [diff] [blame] | 786 | if (!(hkey = get_special_root_hkey( hkey ))) return ERROR_INVALID_HANDLE; |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 787 | |
Alexandre Julliard | 454355e | 2000-10-02 03:46:58 +0000 | [diff] [blame] | 788 | status = NtQueryKey( hkey, KeyFullInformation, buffer, sizeof(buffer), &total_size ); |
Alexandre Julliard | c661583 | 2001-02-14 21:45:52 +0000 | [diff] [blame] | 789 | if (status && status != STATUS_BUFFER_OVERFLOW) goto done; |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 790 | |
Alexandre Julliard | 454355e | 2000-10-02 03:46:58 +0000 | [diff] [blame] | 791 | if (class || class_len) |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 792 | { |
Alexandre Julliard | 454355e | 2000-10-02 03:46:58 +0000 | [diff] [blame] | 793 | /* retry with a dynamically allocated buffer */ |
| 794 | while (status == STATUS_BUFFER_OVERFLOW) |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 795 | { |
Alexandre Julliard | 454355e | 2000-10-02 03:46:58 +0000 | [diff] [blame] | 796 | if (buf_ptr != buffer) HeapFree( GetProcessHeap(), 0, buf_ptr ); |
| 797 | if (!(buf_ptr = HeapAlloc( GetProcessHeap(), 0, total_size ))) |
| 798 | return ERROR_NOT_ENOUGH_MEMORY; |
| 799 | info = (KEY_FULL_INFORMATION *)buf_ptr; |
| 800 | status = NtQueryKey( hkey, KeyFullInformation, buf_ptr, total_size, &total_size ); |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 801 | } |
Alexandre Julliard | 454355e | 2000-10-02 03:46:58 +0000 | [diff] [blame] | 802 | |
Alexandre Julliard | c661583 | 2001-02-14 21:45:52 +0000 | [diff] [blame] | 803 | if (status) goto done; |
| 804 | |
Alexandre Julliard | 60fd03d | 2001-12-05 22:18:48 +0000 | [diff] [blame] | 805 | RtlUnicodeToMultiByteSize( &len, (WCHAR *)(buf_ptr + info->ClassOffset), info->ClassLength); |
Alexandre Julliard | c661583 | 2001-02-14 21:45:52 +0000 | [diff] [blame] | 806 | if (class_len) |
Alexandre Julliard | 454355e | 2000-10-02 03:46:58 +0000 | [diff] [blame] | 807 | { |
Alexandre Julliard | c661583 | 2001-02-14 21:45:52 +0000 | [diff] [blame] | 808 | if (len + 1 > *class_len) status = STATUS_BUFFER_OVERFLOW; |
| 809 | *class_len = len; |
| 810 | } |
| 811 | if (class && !status) |
| 812 | { |
Alexandre Julliard | 60fd03d | 2001-12-05 22:18:48 +0000 | [diff] [blame] | 813 | RtlUnicodeToMultiByteN( class, len, NULL, (WCHAR *)(buf_ptr + info->ClassOffset), |
| 814 | info->ClassLength ); |
Alexandre Julliard | c661583 | 2001-02-14 21:45:52 +0000 | [diff] [blame] | 815 | class[len] = 0; |
Alexandre Julliard | 454355e | 2000-10-02 03:46:58 +0000 | [diff] [blame] | 816 | } |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 817 | } |
Alexandre Julliard | c661583 | 2001-02-14 21:45:52 +0000 | [diff] [blame] | 818 | else status = STATUS_SUCCESS; |
Alexandre Julliard | 454355e | 2000-10-02 03:46:58 +0000 | [diff] [blame] | 819 | |
Alexandre Julliard | c661583 | 2001-02-14 21:45:52 +0000 | [diff] [blame] | 820 | if (subkeys) *subkeys = info->SubKeys; |
| 821 | if (max_subkey) *max_subkey = info->MaxNameLen; |
| 822 | if (max_class) *max_class = info->MaxClassLen; |
| 823 | if (values) *values = info->Values; |
| 824 | if (max_value) *max_value = info->MaxValueNameLen; |
| 825 | if (max_data) *max_data = info->MaxValueDataLen; |
Dmitry Timoshkov | 6b6596a | 2001-11-23 18:44:43 +0000 | [diff] [blame] | 826 | if (modif) *modif = *(FILETIME *)&info->LastWriteTime; |
Alexandre Julliard | 454355e | 2000-10-02 03:46:58 +0000 | [diff] [blame] | 827 | |
Alexandre Julliard | c661583 | 2001-02-14 21:45:52 +0000 | [diff] [blame] | 828 | done: |
Alexandre Julliard | 454355e | 2000-10-02 03:46:58 +0000 | [diff] [blame] | 829 | if (buf_ptr != buffer) HeapFree( GetProcessHeap(), 0, buf_ptr ); |
| 830 | return RtlNtStatusToDosError( status ); |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 831 | } |
| 832 | |
| 833 | |
| 834 | /****************************************************************************** |
James Hawkins | 6a358c4 | 2004-07-13 23:33:14 +0000 | [diff] [blame^] | 835 | * RegCloseKey [ADVAPI32.@] |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 836 | * |
Jon Griffiths | 50ce084 | 2004-04-23 21:32:34 +0000 | [diff] [blame] | 837 | * Close an open registry key. |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 838 | * |
| 839 | * PARAMS |
James Hawkins | 6a358c4 | 2004-07-13 23:33:14 +0000 | [diff] [blame^] | 840 | * hkey [I] Handle of key to close |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 841 | * |
| 842 | * RETURNS |
James Hawkins | 6a358c4 | 2004-07-13 23:33:14 +0000 | [diff] [blame^] | 843 | * Success: ERROR_SUCCESS |
| 844 | * Failure: Error code |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 845 | */ |
| 846 | DWORD WINAPI RegCloseKey( HKEY hkey ) |
| 847 | { |
Alexandre Julliard | 7375597 | 2002-07-31 19:26:03 +0000 | [diff] [blame] | 848 | if (!hkey || hkey >= (HKEY)0x80000000) return ERROR_SUCCESS; |
Alexandre Julliard | bcf393a | 2000-10-01 01:44:50 +0000 | [diff] [blame] | 849 | return RtlNtStatusToDosError( NtClose( hkey ) ); |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 850 | } |
| 851 | |
| 852 | |
| 853 | /****************************************************************************** |
James Hawkins | 6a358c4 | 2004-07-13 23:33:14 +0000 | [diff] [blame^] | 854 | * RegDeleteKeyW [ADVAPI32.@] |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 855 | * |
Jon Griffiths | 50ce084 | 2004-04-23 21:32:34 +0000 | [diff] [blame] | 856 | * See RegDeleteKeyA. |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 857 | */ |
| 858 | DWORD WINAPI RegDeleteKeyW( HKEY hkey, LPCWSTR name ) |
| 859 | { |
| 860 | DWORD ret; |
Alexandre Julliard | bcf393a | 2000-10-01 01:44:50 +0000 | [diff] [blame] | 861 | HKEY tmp; |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 862 | |
Alexandre Julliard | f2ef2c2 | 2002-09-13 21:42:28 +0000 | [diff] [blame] | 863 | if (!(hkey = get_special_root_hkey( hkey ))) return ERROR_INVALID_HANDLE; |
| 864 | |
Mike McCormack | da00742 | 2002-06-14 23:35:37 +0000 | [diff] [blame] | 865 | if (!name || !*name) |
Alexandre Julliard | bcf393a | 2000-10-01 01:44:50 +0000 | [diff] [blame] | 866 | { |
Mike McCormack | da00742 | 2002-06-14 23:35:37 +0000 | [diff] [blame] | 867 | ret = RtlNtStatusToDosError( NtDeleteKey( hkey ) ); |
| 868 | } |
Alexandre Julliard | a929873 | 2002-09-12 20:47:14 +0000 | [diff] [blame] | 869 | else if (!(ret = RegOpenKeyExW( hkey, name, 0, KEY_ENUMERATE_SUB_KEYS, &tmp ))) |
Mike McCormack | da00742 | 2002-06-14 23:35:37 +0000 | [diff] [blame] | 870 | { |
| 871 | if (!is_version_nt()) /* win95 does recursive key deletes */ |
| 872 | { |
| 873 | WCHAR name[MAX_PATH]; |
| 874 | |
Francois Gouget | 9591836 | 2003-06-18 19:45:22 +0000 | [diff] [blame] | 875 | while(!RegEnumKeyW(tmp, 0, name, sizeof(name))) |
Mike McCormack | da00742 | 2002-06-14 23:35:37 +0000 | [diff] [blame] | 876 | { |
| 877 | if(RegDeleteKeyW(tmp, name)) /* recurse */ |
| 878 | break; |
| 879 | } |
| 880 | } |
Alexandre Julliard | bcf393a | 2000-10-01 01:44:50 +0000 | [diff] [blame] | 881 | ret = RtlNtStatusToDosError( NtDeleteKey( tmp ) ); |
| 882 | RegCloseKey( tmp ); |
| 883 | } |
Mike McCormack | da00742 | 2002-06-14 23:35:37 +0000 | [diff] [blame] | 884 | TRACE("%s ret=%08lx\n", debugstr_w(name), ret); |
Alexandre Julliard | bcf393a | 2000-10-01 01:44:50 +0000 | [diff] [blame] | 885 | return ret; |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 886 | } |
| 887 | |
| 888 | |
| 889 | /****************************************************************************** |
James Hawkins | 6a358c4 | 2004-07-13 23:33:14 +0000 | [diff] [blame^] | 890 | * RegDeleteKeyA [ADVAPI32.@] |
Jon Griffiths | 50ce084 | 2004-04-23 21:32:34 +0000 | [diff] [blame] | 891 | * |
| 892 | * Delete a registry key. |
| 893 | * |
| 894 | * PARAMS |
James Hawkins | 6a358c4 | 2004-07-13 23:33:14 +0000 | [diff] [blame^] | 895 | * hkey [I] Handle to parent key containing the key to delete |
| 896 | * name [I] Name of the key user hkey to delete |
Jon Griffiths | 50ce084 | 2004-04-23 21:32:34 +0000 | [diff] [blame] | 897 | * |
| 898 | * RETURNS |
James Hawkins | 6a358c4 | 2004-07-13 23:33:14 +0000 | [diff] [blame^] | 899 | * Success: ERROR_SUCCESS |
| 900 | * Failure: Error code |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 901 | */ |
| 902 | DWORD WINAPI RegDeleteKeyA( HKEY hkey, LPCSTR name ) |
| 903 | { |
| 904 | DWORD ret; |
Alexandre Julliard | bcf393a | 2000-10-01 01:44:50 +0000 | [diff] [blame] | 905 | HKEY tmp; |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 906 | |
Alexandre Julliard | f2ef2c2 | 2002-09-13 21:42:28 +0000 | [diff] [blame] | 907 | if (!(hkey = get_special_root_hkey( hkey ))) return ERROR_INVALID_HANDLE; |
| 908 | |
Mike McCormack | da00742 | 2002-06-14 23:35:37 +0000 | [diff] [blame] | 909 | if (!name || !*name) |
Alexandre Julliard | bcf393a | 2000-10-01 01:44:50 +0000 | [diff] [blame] | 910 | { |
Mike McCormack | da00742 | 2002-06-14 23:35:37 +0000 | [diff] [blame] | 911 | ret = RtlNtStatusToDosError( NtDeleteKey( hkey ) ); |
| 912 | } |
Alexandre Julliard | a929873 | 2002-09-12 20:47:14 +0000 | [diff] [blame] | 913 | else if (!(ret = RegOpenKeyExA( hkey, name, 0, KEY_ENUMERATE_SUB_KEYS, &tmp ))) |
Mike McCormack | da00742 | 2002-06-14 23:35:37 +0000 | [diff] [blame] | 914 | { |
| 915 | if (!is_version_nt()) /* win95 does recursive key deletes */ |
| 916 | { |
| 917 | CHAR name[MAX_PATH]; |
| 918 | |
Francois Gouget | 9591836 | 2003-06-18 19:45:22 +0000 | [diff] [blame] | 919 | while(!RegEnumKeyA(tmp, 0, name, sizeof(name))) |
Mike McCormack | da00742 | 2002-06-14 23:35:37 +0000 | [diff] [blame] | 920 | { |
| 921 | if(RegDeleteKeyA(tmp, name)) /* recurse */ |
| 922 | break; |
| 923 | } |
| 924 | } |
Alexandre Julliard | bcf393a | 2000-10-01 01:44:50 +0000 | [diff] [blame] | 925 | ret = RtlNtStatusToDosError( NtDeleteKey( tmp ) ); |
| 926 | RegCloseKey( tmp ); |
| 927 | } |
Mike McCormack | da00742 | 2002-06-14 23:35:37 +0000 | [diff] [blame] | 928 | TRACE("%s ret=%08lx\n", debugstr_a(name), ret); |
Alexandre Julliard | bcf393a | 2000-10-01 01:44:50 +0000 | [diff] [blame] | 929 | return ret; |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 930 | } |
| 931 | |
| 932 | |
| 933 | |
| 934 | /****************************************************************************** |
James Hawkins | 6a358c4 | 2004-07-13 23:33:14 +0000 | [diff] [blame^] | 935 | * RegSetValueExW [ADVAPI32.@] |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 936 | * |
Jon Griffiths | 50ce084 | 2004-04-23 21:32:34 +0000 | [diff] [blame] | 937 | * Set the data and contents of a registry value. |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 938 | * |
| 939 | * PARAMS |
James Hawkins | 6a358c4 | 2004-07-13 23:33:14 +0000 | [diff] [blame^] | 940 | * hkey [I] Handle of key to set value for |
| 941 | * name [I] Name of value to set |
| 942 | * reserved [I] Reserved, must be zero |
| 943 | * type [I] Type of the value being set |
| 944 | * data [I] The new contents of the value to set |
| 945 | * count [I] Size of data |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 946 | * |
| 947 | * RETURNS |
James Hawkins | 6a358c4 | 2004-07-13 23:33:14 +0000 | [diff] [blame^] | 948 | * Success: ERROR_SUCCESS |
| 949 | * Failure: Error code |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 950 | * |
| 951 | * NOTES |
James Hawkins | 6a358c4 | 2004-07-13 23:33:14 +0000 | [diff] [blame^] | 952 | * win95 does not care about count for REG_SZ and finds out the len by itself (js) |
| 953 | * NT does definitely care (aj) |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 954 | */ |
| 955 | DWORD WINAPI RegSetValueExW( HKEY hkey, LPCWSTR name, DWORD reserved, |
| 956 | DWORD type, CONST BYTE *data, DWORD count ) |
| 957 | { |
Alexandre Julliard | bcf393a | 2000-10-01 01:44:50 +0000 | [diff] [blame] | 958 | UNICODE_STRING nameW; |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 959 | |
Michael Cardenas | 7dbce65 | 2002-03-21 01:24:52 +0000 | [diff] [blame] | 960 | if (!is_version_nt()) /* win95 */ |
Alexandre Julliard | 918da64 | 2001-04-10 21:30:24 +0000 | [diff] [blame] | 961 | { |
| 962 | if (type == REG_SZ) count = (strlenW( (WCHAR *)data ) + 1) * sizeof(WCHAR); |
| 963 | } |
| 964 | else if (count && is_string(type)) |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 965 | { |
| 966 | LPCWSTR str = (LPCWSTR)data; |
| 967 | /* if user forgot to count terminating null, add it (yes NT does this) */ |
| 968 | if (str[count / sizeof(WCHAR) - 1] && !str[count / sizeof(WCHAR)]) |
| 969 | count += sizeof(WCHAR); |
| 970 | } |
Alexandre Julliard | f2ef2c2 | 2002-09-13 21:42:28 +0000 | [diff] [blame] | 971 | if (!(hkey = get_special_root_hkey( hkey ))) return ERROR_INVALID_HANDLE; |
Alexandre Julliard | a01004d | 2000-05-14 22:57:57 +0000 | [diff] [blame] | 972 | |
Alexandre Julliard | bcf393a | 2000-10-01 01:44:50 +0000 | [diff] [blame] | 973 | RtlInitUnicodeString( &nameW, name ); |
| 974 | return RtlNtStatusToDosError( NtSetValueKey( hkey, &nameW, 0, type, data, count ) ); |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 975 | } |
| 976 | |
| 977 | |
| 978 | /****************************************************************************** |
James Hawkins | 6a358c4 | 2004-07-13 23:33:14 +0000 | [diff] [blame^] | 979 | * RegSetValueExA [ADVAPI32.@] |
| 980 | * |
| 981 | * see RegSetValueExW |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 982 | */ |
| 983 | DWORD WINAPI RegSetValueExA( HKEY hkey, LPCSTR name, DWORD reserved, DWORD type, |
Alexandre Julliard | bcf393a | 2000-10-01 01:44:50 +0000 | [diff] [blame] | 984 | CONST BYTE *data, DWORD count ) |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 985 | { |
Alexandre Julliard | bcf393a | 2000-10-01 01:44:50 +0000 | [diff] [blame] | 986 | ANSI_STRING nameA; |
| 987 | WCHAR *dataW = NULL; |
| 988 | NTSTATUS status; |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 989 | |
Michael Cardenas | 7dbce65 | 2002-03-21 01:24:52 +0000 | [diff] [blame] | 990 | if (!is_version_nt()) /* win95 */ |
Alexandre Julliard | 918da64 | 2001-04-10 21:30:24 +0000 | [diff] [blame] | 991 | { |
| 992 | if (type == REG_SZ) count = strlen(data) + 1; |
| 993 | } |
| 994 | else if (count && is_string(type)) |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 995 | { |
| 996 | /* if user forgot to count terminating null, add it (yes NT does this) */ |
| 997 | if (data[count-1] && !data[count]) count++; |
| 998 | } |
Alexandre Julliard | bcf393a | 2000-10-01 01:44:50 +0000 | [diff] [blame] | 999 | |
Alexandre Julliard | f2ef2c2 | 2002-09-13 21:42:28 +0000 | [diff] [blame] | 1000 | if (!(hkey = get_special_root_hkey( hkey ))) return ERROR_INVALID_HANDLE; |
| 1001 | |
Alexandre Julliard | a01004d | 2000-05-14 22:57:57 +0000 | [diff] [blame] | 1002 | if (is_string( type )) /* need to convert to Unicode */ |
Alexandre Julliard | a01004d | 2000-05-14 22:57:57 +0000 | [diff] [blame] | 1003 | { |
Alexandre Julliard | 60fd03d | 2001-12-05 22:18:48 +0000 | [diff] [blame] | 1004 | DWORD lenW; |
| 1005 | RtlMultiByteToUnicodeSize( &lenW, data, count ); |
| 1006 | if (!(dataW = HeapAlloc( GetProcessHeap(), 0, lenW ))) return ERROR_OUTOFMEMORY; |
| 1007 | RtlMultiByteToUnicodeN( dataW, lenW, NULL, data, count ); |
| 1008 | count = lenW; |
Alexandre Julliard | bcf393a | 2000-10-01 01:44:50 +0000 | [diff] [blame] | 1009 | data = (BYTE *)dataW; |
Alexandre Julliard | a01004d | 2000-05-14 22:57:57 +0000 | [diff] [blame] | 1010 | } |
Alexandre Julliard | bcf393a | 2000-10-01 01:44:50 +0000 | [diff] [blame] | 1011 | |
| 1012 | RtlInitAnsiString( &nameA, name ); |
Alexandre Julliard | ab5e975 | 2001-03-23 19:12:01 +0000 | [diff] [blame] | 1013 | if (!(status = RtlAnsiStringToUnicodeString( &NtCurrentTeb()->StaticUnicodeString, |
| 1014 | &nameA, FALSE ))) |
Alexandre Julliard | bcf393a | 2000-10-01 01:44:50 +0000 | [diff] [blame] | 1015 | { |
Alexandre Julliard | ab5e975 | 2001-03-23 19:12:01 +0000 | [diff] [blame] | 1016 | status = NtSetValueKey( hkey, &NtCurrentTeb()->StaticUnicodeString, 0, type, data, count ); |
Alexandre Julliard | bcf393a | 2000-10-01 01:44:50 +0000 | [diff] [blame] | 1017 | } |
| 1018 | if (dataW) HeapFree( GetProcessHeap(), 0, dataW ); |
| 1019 | return RtlNtStatusToDosError( status ); |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 1020 | } |
| 1021 | |
| 1022 | |
| 1023 | /****************************************************************************** |
James Hawkins | 6a358c4 | 2004-07-13 23:33:14 +0000 | [diff] [blame^] | 1024 | * RegSetValueW [ADVAPI32.@] |
| 1025 | * |
| 1026 | * Sets the data for the default or unnamed value of a reg key. |
| 1027 | * |
| 1028 | * PARAMS |
| 1029 | * hKey [I] Handle to an open key. |
| 1030 | * lpSubKey [I] Name of a subkey of hKey. |
| 1031 | * dwType [I] Type of information to store. |
| 1032 | * lpData [I] String that contains the data to set for the default value. |
| 1033 | * cbData [I] Size of lpData. |
| 1034 | * |
| 1035 | * RETURNS |
| 1036 | * Success: ERROR_SUCCESS |
| 1037 | * Failure: nonzero error code from Winerror.h |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 1038 | */ |
| 1039 | DWORD WINAPI RegSetValueW( HKEY hkey, LPCWSTR name, DWORD type, LPCWSTR data, DWORD count ) |
| 1040 | { |
| 1041 | HKEY subkey = hkey; |
| 1042 | DWORD ret; |
| 1043 | |
Michael Stefaniuc | cbacde5 | 2002-10-25 19:17:33 +0000 | [diff] [blame] | 1044 | 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] | 1045 | |
| 1046 | if (type != REG_SZ) return ERROR_INVALID_PARAMETER; |
| 1047 | |
| 1048 | if (name && name[0]) /* need to create the subkey */ |
| 1049 | { |
| 1050 | if ((ret = RegCreateKeyW( hkey, name, &subkey )) != ERROR_SUCCESS) return ret; |
| 1051 | } |
| 1052 | |
| 1053 | ret = RegSetValueExW( subkey, NULL, 0, REG_SZ, (LPBYTE)data, |
Alexandre Julliard | c7e7df8 | 2000-08-14 14:41:19 +0000 | [diff] [blame] | 1054 | (strlenW( data ) + 1) * sizeof(WCHAR) ); |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 1055 | if (subkey != hkey) RegCloseKey( subkey ); |
| 1056 | return ret; |
| 1057 | } |
| 1058 | |
| 1059 | |
| 1060 | /****************************************************************************** |
James Hawkins | 6a358c4 | 2004-07-13 23:33:14 +0000 | [diff] [blame^] | 1061 | * RegSetValueA [ADVAPI32.@] |
| 1062 | * |
| 1063 | * see RegSetValueW |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 1064 | */ |
| 1065 | DWORD WINAPI RegSetValueA( HKEY hkey, LPCSTR name, DWORD type, LPCSTR data, DWORD count ) |
| 1066 | { |
| 1067 | HKEY subkey = hkey; |
| 1068 | DWORD ret; |
| 1069 | |
Michael Stefaniuc | cbacde5 | 2002-10-25 19:17:33 +0000 | [diff] [blame] | 1070 | 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] | 1071 | |
| 1072 | if (type != REG_SZ) return ERROR_INVALID_PARAMETER; |
| 1073 | |
| 1074 | if (name && name[0]) /* need to create the subkey */ |
| 1075 | { |
| 1076 | if ((ret = RegCreateKeyA( hkey, name, &subkey )) != ERROR_SUCCESS) return ret; |
| 1077 | } |
| 1078 | ret = RegSetValueExA( subkey, NULL, 0, REG_SZ, (LPBYTE)data, strlen(data)+1 ); |
| 1079 | if (subkey != hkey) RegCloseKey( subkey ); |
| 1080 | return ret; |
| 1081 | } |
| 1082 | |
| 1083 | |
| 1084 | |
| 1085 | /****************************************************************************** |
James Hawkins | 6a358c4 | 2004-07-13 23:33:14 +0000 | [diff] [blame^] | 1086 | * RegQueryValueExW [ADVAPI32.@] |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 1087 | * |
Jon Griffiths | 50ce084 | 2004-04-23 21:32:34 +0000 | [diff] [blame] | 1088 | * See RegQueryValueExA. |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 1089 | */ |
| 1090 | DWORD WINAPI RegQueryValueExW( HKEY hkey, LPCWSTR name, LPDWORD reserved, LPDWORD type, |
Alexandre Julliard | bcf393a | 2000-10-01 01:44:50 +0000 | [diff] [blame] | 1091 | LPBYTE data, LPDWORD count ) |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 1092 | { |
Alexandre Julliard | bcf393a | 2000-10-01 01:44:50 +0000 | [diff] [blame] | 1093 | NTSTATUS status; |
| 1094 | UNICODE_STRING name_str; |
| 1095 | DWORD total_size; |
Alexandre Julliard | 454355e | 2000-10-02 03:46:58 +0000 | [diff] [blame] | 1096 | char buffer[256], *buf_ptr = buffer; |
Alexandre Julliard | bcf393a | 2000-10-01 01:44:50 +0000 | [diff] [blame] | 1097 | KEY_VALUE_PARTIAL_INFORMATION *info = (KEY_VALUE_PARTIAL_INFORMATION *)buffer; |
Alexandre Julliard | a010932 | 2002-07-05 21:30:38 +0000 | [diff] [blame] | 1098 | static const int info_size = offsetof( KEY_VALUE_PARTIAL_INFORMATION, Data ); |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 1099 | |
Michael Stefaniuc | cbacde5 | 2002-10-25 19:17:33 +0000 | [diff] [blame] | 1100 | TRACE("(%p,%s,%p,%p,%p,%p=%ld)\n", |
Francois Gouget | 8f63a71 | 2003-12-13 01:34:40 +0000 | [diff] [blame] | 1101 | hkey, debugstr_w(name), reserved, type, data, count, |
| 1102 | (count && data) ? *count : 0 ); |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 1103 | |
Eric Pouech | 2c655f5 | 1999-11-25 22:05:46 +0000 | [diff] [blame] | 1104 | if ((data && !count) || reserved) return ERROR_INVALID_PARAMETER; |
Alexandre Julliard | f2ef2c2 | 2002-09-13 21:42:28 +0000 | [diff] [blame] | 1105 | if (!(hkey = get_special_root_hkey( hkey ))) return ERROR_INVALID_HANDLE; |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 1106 | |
Alexandre Julliard | bcf393a | 2000-10-01 01:44:50 +0000 | [diff] [blame] | 1107 | RtlInitUnicodeString( &name_str, name ); |
| 1108 | |
| 1109 | if (data) total_size = min( sizeof(buffer), *count + info_size ); |
| 1110 | else total_size = info_size; |
| 1111 | |
| 1112 | status = NtQueryValueKey( hkey, &name_str, KeyValuePartialInformation, |
| 1113 | buffer, total_size, &total_size ); |
| 1114 | if (status && status != STATUS_BUFFER_OVERFLOW) goto done; |
Alexandre Julliard | a01004d | 2000-05-14 22:57:57 +0000 | [diff] [blame] | 1115 | |
| 1116 | if (data) |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 1117 | { |
Alexandre Julliard | bcf393a | 2000-10-01 01:44:50 +0000 | [diff] [blame] | 1118 | /* retry with a dynamically allocated buffer */ |
| 1119 | while (status == STATUS_BUFFER_OVERFLOW && total_size - info_size <= *count) |
Alexandre Julliard | a01004d | 2000-05-14 22:57:57 +0000 | [diff] [blame] | 1120 | { |
Alexandre Julliard | bcf393a | 2000-10-01 01:44:50 +0000 | [diff] [blame] | 1121 | if (buf_ptr != buffer) HeapFree( GetProcessHeap(), 0, buf_ptr ); |
| 1122 | if (!(buf_ptr = HeapAlloc( GetProcessHeap(), 0, total_size ))) |
Alexandre Julliard | 454355e | 2000-10-02 03:46:58 +0000 | [diff] [blame] | 1123 | return ERROR_NOT_ENOUGH_MEMORY; |
| 1124 | info = (KEY_VALUE_PARTIAL_INFORMATION *)buf_ptr; |
| 1125 | status = NtQueryValueKey( hkey, &name_str, KeyValuePartialInformation, |
| 1126 | buf_ptr, total_size, &total_size ); |
Alexandre Julliard | bcf393a | 2000-10-01 01:44:50 +0000 | [diff] [blame] | 1127 | } |
| 1128 | |
| 1129 | if (!status) |
| 1130 | { |
| 1131 | memcpy( data, buf_ptr + info_size, total_size - info_size ); |
| 1132 | /* if the type is REG_SZ and data is not 0-terminated |
| 1133 | * and there is enough space in the buffer NT appends a \0 */ |
| 1134 | if (total_size - info_size <= *count-sizeof(WCHAR) && is_string(info->Type)) |
Alexandre Julliard | a01004d | 2000-05-14 22:57:57 +0000 | [diff] [blame] | 1135 | { |
Alexandre Julliard | bcf393a | 2000-10-01 01:44:50 +0000 | [diff] [blame] | 1136 | WCHAR *ptr = (WCHAR *)(data + total_size - info_size); |
| 1137 | if (ptr > (WCHAR *)data && ptr[-1]) *ptr = 0; |
Alexandre Julliard | a01004d | 2000-05-14 22:57:57 +0000 | [diff] [blame] | 1138 | } |
| 1139 | } |
Alexandre Julliard | 454355e | 2000-10-02 03:46:58 +0000 | [diff] [blame] | 1140 | else if (status != STATUS_BUFFER_OVERFLOW) goto done; |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 1141 | } |
Alexandre Julliard | c661583 | 2001-02-14 21:45:52 +0000 | [diff] [blame] | 1142 | else status = STATUS_SUCCESS; |
Alexandre Julliard | bcf393a | 2000-10-01 01:44:50 +0000 | [diff] [blame] | 1143 | |
| 1144 | if (type) *type = info->Type; |
| 1145 | if (count) *count = total_size - info_size; |
| 1146 | |
| 1147 | done: |
Alexandre Julliard | 454355e | 2000-10-02 03:46:58 +0000 | [diff] [blame] | 1148 | if (buf_ptr != buffer) HeapFree( GetProcessHeap(), 0, buf_ptr ); |
Alexandre Julliard | bcf393a | 2000-10-01 01:44:50 +0000 | [diff] [blame] | 1149 | return RtlNtStatusToDosError(status); |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 1150 | } |
| 1151 | |
| 1152 | |
| 1153 | /****************************************************************************** |
James Hawkins | 6a358c4 | 2004-07-13 23:33:14 +0000 | [diff] [blame^] | 1154 | * RegQueryValueExA [ADVAPI32.@] |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 1155 | * |
Jon Griffiths | 50ce084 | 2004-04-23 21:32:34 +0000 | [diff] [blame] | 1156 | * Get the type and contents of a specified value under with a key. |
| 1157 | * |
| 1158 | * PARAMS |
James Hawkins | 6a358c4 | 2004-07-13 23:33:14 +0000 | [diff] [blame^] | 1159 | * hkey [I] Handle of the key to query |
| 1160 | * name [I] Name of value under hkey to query |
| 1161 | * reserved [I] Reserved - must be NULL |
| 1162 | * type [O] Destination for the value type, or NULL if not required |
| 1163 | * data [O] Destination for the values contents, or NULL if not required |
| 1164 | * 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] | 1165 | * |
| 1166 | * RETURNS |
| 1167 | * Success: ERROR_SUCCESS. *count is updated with the number of bytes copied to data. |
| 1168 | * Failure: ERROR_INVALID_HANDLE, if hkey is invalid. |
| 1169 | * ERROR_INVALID_PARAMETER, if any other parameter is invalid. |
| 1170 | * ERROR_MORE_DATA, if on input *count is too small to hold the contents. |
| 1171 | * |
| 1172 | * NOTES |
| 1173 | * MSDN states that if data is too small it is partially filled. In reality |
| 1174 | * it remains untouched. |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 1175 | */ |
| 1176 | DWORD WINAPI RegQueryValueExA( HKEY hkey, LPCSTR name, LPDWORD reserved, LPDWORD type, |
Alexandre Julliard | bcf393a | 2000-10-01 01:44:50 +0000 | [diff] [blame] | 1177 | LPBYTE data, LPDWORD count ) |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 1178 | { |
Alexandre Julliard | bcf393a | 2000-10-01 01:44:50 +0000 | [diff] [blame] | 1179 | NTSTATUS status; |
| 1180 | ANSI_STRING nameA; |
Alexandre Julliard | bcf393a | 2000-10-01 01:44:50 +0000 | [diff] [blame] | 1181 | DWORD total_size; |
Alexandre Julliard | 454355e | 2000-10-02 03:46:58 +0000 | [diff] [blame] | 1182 | char buffer[256], *buf_ptr = buffer; |
Alexandre Julliard | bcf393a | 2000-10-01 01:44:50 +0000 | [diff] [blame] | 1183 | KEY_VALUE_PARTIAL_INFORMATION *info = (KEY_VALUE_PARTIAL_INFORMATION *)buffer; |
Alexandre Julliard | a010932 | 2002-07-05 21:30:38 +0000 | [diff] [blame] | 1184 | static const int info_size = offsetof( KEY_VALUE_PARTIAL_INFORMATION, Data ); |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 1185 | |
Michael Stefaniuc | cbacde5 | 2002-10-25 19:17:33 +0000 | [diff] [blame] | 1186 | TRACE("(%p,%s,%p,%p,%p,%p=%ld)\n", |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 1187 | hkey, debugstr_a(name), reserved, type, data, count, count ? *count : 0 ); |
| 1188 | |
Eric Pouech | 2c655f5 | 1999-11-25 22:05:46 +0000 | [diff] [blame] | 1189 | if ((data && !count) || reserved) return ERROR_INVALID_PARAMETER; |
Alexandre Julliard | f2ef2c2 | 2002-09-13 21:42:28 +0000 | [diff] [blame] | 1190 | if (!(hkey = get_special_root_hkey( hkey ))) return ERROR_INVALID_HANDLE; |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 1191 | |
Alexandre Julliard | bcf393a | 2000-10-01 01:44:50 +0000 | [diff] [blame] | 1192 | RtlInitAnsiString( &nameA, name ); |
Alexandre Julliard | ab5e975 | 2001-03-23 19:12:01 +0000 | [diff] [blame] | 1193 | if ((status = RtlAnsiStringToUnicodeString( &NtCurrentTeb()->StaticUnicodeString, |
| 1194 | &nameA, FALSE ))) |
Alexandre Julliard | 454355e | 2000-10-02 03:46:58 +0000 | [diff] [blame] | 1195 | return RtlNtStatusToDosError(status); |
Alexandre Julliard | a01004d | 2000-05-14 22:57:57 +0000 | [diff] [blame] | 1196 | |
Alexandre Julliard | ab5e975 | 2001-03-23 19:12:01 +0000 | [diff] [blame] | 1197 | status = NtQueryValueKey( hkey, &NtCurrentTeb()->StaticUnicodeString, |
| 1198 | KeyValuePartialInformation, buffer, sizeof(buffer), &total_size ); |
Alexandre Julliard | bcf393a | 2000-10-01 01:44:50 +0000 | [diff] [blame] | 1199 | if (status && status != STATUS_BUFFER_OVERFLOW) goto done; |
Alexandre Julliard | a01004d | 2000-05-14 22:57:57 +0000 | [diff] [blame] | 1200 | |
Alexandre Julliard | bcf393a | 2000-10-01 01:44:50 +0000 | [diff] [blame] | 1201 | /* we need to fetch the contents for a string type even if not requested, |
| 1202 | * because we need to compute the length of the ASCII string. */ |
| 1203 | if (data || is_string(info->Type)) |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 1204 | { |
Alexandre Julliard | bcf393a | 2000-10-01 01:44:50 +0000 | [diff] [blame] | 1205 | /* retry with a dynamically allocated buffer */ |
| 1206 | while (status == STATUS_BUFFER_OVERFLOW) |
Alexandre Julliard | a01004d | 2000-05-14 22:57:57 +0000 | [diff] [blame] | 1207 | { |
Alexandre Julliard | bcf393a | 2000-10-01 01:44:50 +0000 | [diff] [blame] | 1208 | if (buf_ptr != buffer) HeapFree( GetProcessHeap(), 0, buf_ptr ); |
| 1209 | if (!(buf_ptr = HeapAlloc( GetProcessHeap(), 0, total_size ))) |
Alexandre Julliard | 454355e | 2000-10-02 03:46:58 +0000 | [diff] [blame] | 1210 | { |
Alexandre Julliard | bcf393a | 2000-10-01 01:44:50 +0000 | [diff] [blame] | 1211 | status = STATUS_NO_MEMORY; |
Alexandre Julliard | 454355e | 2000-10-02 03:46:58 +0000 | [diff] [blame] | 1212 | goto done; |
| 1213 | } |
| 1214 | info = (KEY_VALUE_PARTIAL_INFORMATION *)buf_ptr; |
Alexandre Julliard | ab5e975 | 2001-03-23 19:12:01 +0000 | [diff] [blame] | 1215 | status = NtQueryValueKey( hkey, &NtCurrentTeb()->StaticUnicodeString, |
| 1216 | KeyValuePartialInformation, buf_ptr, total_size, &total_size ); |
Alexandre Julliard | bcf393a | 2000-10-01 01:44:50 +0000 | [diff] [blame] | 1217 | } |
| 1218 | |
Alexandre Julliard | c661583 | 2001-02-14 21:45:52 +0000 | [diff] [blame] | 1219 | if (status) goto done; |
| 1220 | |
| 1221 | if (is_string(info->Type)) |
Alexandre Julliard | bcf393a | 2000-10-01 01:44:50 +0000 | [diff] [blame] | 1222 | { |
Alexandre Julliard | 60fd03d | 2001-12-05 22:18:48 +0000 | [diff] [blame] | 1223 | DWORD len; |
| 1224 | |
| 1225 | RtlUnicodeToMultiByteSize( &len, (WCHAR *)(buf_ptr + info_size), |
| 1226 | total_size - info_size ); |
Alexandre Julliard | c661583 | 2001-02-14 21:45:52 +0000 | [diff] [blame] | 1227 | if (data && len) |
Alexandre Julliard | 57f05e1 | 2000-10-15 00:40:25 +0000 | [diff] [blame] | 1228 | { |
Alexandre Julliard | c661583 | 2001-02-14 21:45:52 +0000 | [diff] [blame] | 1229 | if (len > *count) status = STATUS_BUFFER_OVERFLOW; |
| 1230 | else |
| 1231 | { |
Alexandre Julliard | 60fd03d | 2001-12-05 22:18:48 +0000 | [diff] [blame] | 1232 | RtlUnicodeToMultiByteN( data, len, NULL, (WCHAR *)(buf_ptr + info_size), |
| 1233 | total_size - info_size ); |
Alexandre Julliard | c661583 | 2001-02-14 21:45:52 +0000 | [diff] [blame] | 1234 | /* if the type is REG_SZ and data is not 0-terminated |
| 1235 | * and there is enough space in the buffer NT appends a \0 */ |
| 1236 | if (len < *count && data[len-1]) data[len] = 0; |
| 1237 | } |
Alexandre Julliard | 57f05e1 | 2000-10-15 00:40:25 +0000 | [diff] [blame] | 1238 | } |
Alexandre Julliard | c661583 | 2001-02-14 21:45:52 +0000 | [diff] [blame] | 1239 | total_size = len + info_size; |
Alexandre Julliard | a01004d | 2000-05-14 22:57:57 +0000 | [diff] [blame] | 1240 | } |
Alexandre Julliard | c661583 | 2001-02-14 21:45:52 +0000 | [diff] [blame] | 1241 | else if (data) |
| 1242 | { |
| 1243 | if (total_size - info_size > *count) status = STATUS_BUFFER_OVERFLOW; |
| 1244 | else memcpy( data, buf_ptr + info_size, total_size - info_size ); |
| 1245 | } |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 1246 | } |
Alexandre Julliard | c661583 | 2001-02-14 21:45:52 +0000 | [diff] [blame] | 1247 | else status = STATUS_SUCCESS; |
Alexandre Julliard | a01004d | 2000-05-14 22:57:57 +0000 | [diff] [blame] | 1248 | |
Alexandre Julliard | bcf393a | 2000-10-01 01:44:50 +0000 | [diff] [blame] | 1249 | if (type) *type = info->Type; |
| 1250 | if (count) *count = total_size - info_size; |
Alexandre Julliard | bcf393a | 2000-10-01 01:44:50 +0000 | [diff] [blame] | 1251 | |
| 1252 | done: |
Alexandre Julliard | 454355e | 2000-10-02 03:46:58 +0000 | [diff] [blame] | 1253 | if (buf_ptr != buffer) HeapFree( GetProcessHeap(), 0, buf_ptr ); |
Alexandre Julliard | bcf393a | 2000-10-01 01:44:50 +0000 | [diff] [blame] | 1254 | return RtlNtStatusToDosError(status); |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 1255 | } |
| 1256 | |
| 1257 | |
| 1258 | /****************************************************************************** |
James Hawkins | 6a358c4 | 2004-07-13 23:33:14 +0000 | [diff] [blame^] | 1259 | * RegQueryValueW [ADVAPI32.@] |
| 1260 | * |
| 1261 | * Retrieves the data associated with the default or unnamed value of a key. |
| 1262 | * |
| 1263 | * PARAMS |
| 1264 | * hKey [I] Handle to an open key. |
| 1265 | * lpSubKey [I] Name of the subkey of hKey. |
| 1266 | * lpValue [O] Receives the string associated with the default value |
| 1267 | * of the key. |
| 1268 | * lpcbValue [I/O] Size of lpValue. |
| 1269 | * |
| 1270 | * RETURNS |
| 1271 | * Success: ERROR_SUCCESS |
| 1272 | * Failure: nonzero error code from Winerror.h |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 1273 | */ |
| 1274 | DWORD WINAPI RegQueryValueW( HKEY hkey, LPCWSTR name, LPWSTR data, LPLONG count ) |
| 1275 | { |
| 1276 | DWORD ret; |
| 1277 | HKEY subkey = hkey; |
| 1278 | |
Michael Stefaniuc | cbacde5 | 2002-10-25 19:17:33 +0000 | [diff] [blame] | 1279 | 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] | 1280 | |
| 1281 | if (name && name[0]) |
| 1282 | { |
| 1283 | if ((ret = RegOpenKeyW( hkey, name, &subkey )) != ERROR_SUCCESS) return ret; |
| 1284 | } |
| 1285 | ret = RegQueryValueExW( subkey, NULL, NULL, NULL, (LPBYTE)data, count ); |
| 1286 | if (subkey != hkey) RegCloseKey( subkey ); |
| 1287 | if (ret == ERROR_FILE_NOT_FOUND) |
| 1288 | { |
| 1289 | /* return empty string if default value not found */ |
| 1290 | if (data) *data = 0; |
| 1291 | if (count) *count = 1; |
| 1292 | ret = ERROR_SUCCESS; |
| 1293 | } |
| 1294 | return ret; |
| 1295 | } |
| 1296 | |
| 1297 | |
| 1298 | /****************************************************************************** |
James Hawkins | 6a358c4 | 2004-07-13 23:33:14 +0000 | [diff] [blame^] | 1299 | * RegQueryValueA [ADVAPI32.@] |
| 1300 | * |
| 1301 | * see RegQueryValueW |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 1302 | */ |
| 1303 | DWORD WINAPI RegQueryValueA( HKEY hkey, LPCSTR name, LPSTR data, LPLONG count ) |
| 1304 | { |
| 1305 | DWORD ret; |
| 1306 | HKEY subkey = hkey; |
| 1307 | |
Michael Stefaniuc | cbacde5 | 2002-10-25 19:17:33 +0000 | [diff] [blame] | 1308 | 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] | 1309 | |
| 1310 | if (name && name[0]) |
| 1311 | { |
| 1312 | if ((ret = RegOpenKeyA( hkey, name, &subkey )) != ERROR_SUCCESS) return ret; |
| 1313 | } |
| 1314 | ret = RegQueryValueExA( subkey, NULL, NULL, NULL, (LPBYTE)data, count ); |
| 1315 | if (subkey != hkey) RegCloseKey( subkey ); |
| 1316 | if (ret == ERROR_FILE_NOT_FOUND) |
| 1317 | { |
| 1318 | /* return empty string if default value not found */ |
| 1319 | if (data) *data = 0; |
| 1320 | if (count) *count = 1; |
| 1321 | ret = ERROR_SUCCESS; |
| 1322 | } |
| 1323 | return ret; |
| 1324 | } |
| 1325 | |
| 1326 | |
| 1327 | /****************************************************************************** |
James Hawkins | 6a358c4 | 2004-07-13 23:33:14 +0000 | [diff] [blame^] | 1328 | * RegEnumValueW [ADVAPI32.@] |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 1329 | * |
| 1330 | * PARAMS |
James Hawkins | 6a358c4 | 2004-07-13 23:33:14 +0000 | [diff] [blame^] | 1331 | * hkey [I] Handle to key to query |
| 1332 | * index [I] Index of value to query |
| 1333 | * value [O] Value string |
| 1334 | * val_count [I/O] Size of value buffer (in wchars) |
| 1335 | * reserved [I] Reserved |
| 1336 | * type [O] Type code |
| 1337 | * data [O] Value data |
| 1338 | * count [I/O] Size of data buffer (in bytes) |
| 1339 | * |
| 1340 | * RETURNS |
| 1341 | * Success: ERROR_SUCCESS |
| 1342 | * Failure: nonzero error code from Winerror.h |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 1343 | */ |
| 1344 | |
| 1345 | DWORD WINAPI RegEnumValueW( HKEY hkey, DWORD index, LPWSTR value, LPDWORD val_count, |
| 1346 | LPDWORD reserved, LPDWORD type, LPBYTE data, LPDWORD count ) |
| 1347 | { |
Alexandre Julliard | 0b6a79c | 2000-12-15 20:57:00 +0000 | [diff] [blame] | 1348 | NTSTATUS status; |
| 1349 | DWORD total_size; |
| 1350 | char buffer[256], *buf_ptr = buffer; |
| 1351 | KEY_VALUE_FULL_INFORMATION *info = (KEY_VALUE_FULL_INFORMATION *)buffer; |
Alexandre Julliard | a010932 | 2002-07-05 21:30:38 +0000 | [diff] [blame] | 1352 | static const int info_size = offsetof( KEY_VALUE_FULL_INFORMATION, Name ); |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 1353 | |
Michael Stefaniuc | cbacde5 | 2002-10-25 19:17:33 +0000 | [diff] [blame] | 1354 | TRACE("(%p,%ld,%p,%p,%p,%p,%p,%p)\n", |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 1355 | hkey, index, value, val_count, reserved, type, data, count ); |
| 1356 | |
| 1357 | /* NT only checks count, not val_count */ |
Eric Pouech | 2c655f5 | 1999-11-25 22:05:46 +0000 | [diff] [blame] | 1358 | if ((data && !count) || reserved) return ERROR_INVALID_PARAMETER; |
Alexandre Julliard | f2ef2c2 | 2002-09-13 21:42:28 +0000 | [diff] [blame] | 1359 | if (!(hkey = get_special_root_hkey( hkey ))) return ERROR_INVALID_HANDLE; |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 1360 | |
Alexandre Julliard | 0b6a79c | 2000-12-15 20:57:00 +0000 | [diff] [blame] | 1361 | total_size = info_size + (MAX_PATH + 1) * sizeof(WCHAR); |
| 1362 | if (data) total_size += *count; |
| 1363 | total_size = min( sizeof(buffer), total_size ); |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 1364 | |
Alexandre Julliard | 0b6a79c | 2000-12-15 20:57:00 +0000 | [diff] [blame] | 1365 | status = NtEnumerateValueKey( hkey, index, KeyValueFullInformation, |
| 1366 | buffer, total_size, &total_size ); |
| 1367 | if (status && status != STATUS_BUFFER_OVERFLOW) goto done; |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 1368 | |
Alexandre Julliard | 0b6a79c | 2000-12-15 20:57:00 +0000 | [diff] [blame] | 1369 | if (value || data) |
Alexandre Julliard | a01004d | 2000-05-14 22:57:57 +0000 | [diff] [blame] | 1370 | { |
Alexandre Julliard | 0b6a79c | 2000-12-15 20:57:00 +0000 | [diff] [blame] | 1371 | /* retry with a dynamically allocated buffer */ |
| 1372 | while (status == STATUS_BUFFER_OVERFLOW) |
Alexandre Julliard | a01004d | 2000-05-14 22:57:57 +0000 | [diff] [blame] | 1373 | { |
Alexandre Julliard | 0b6a79c | 2000-12-15 20:57:00 +0000 | [diff] [blame] | 1374 | if (buf_ptr != buffer) HeapFree( GetProcessHeap(), 0, buf_ptr ); |
| 1375 | if (!(buf_ptr = HeapAlloc( GetProcessHeap(), 0, total_size ))) |
| 1376 | return ERROR_NOT_ENOUGH_MEMORY; |
| 1377 | info = (KEY_VALUE_FULL_INFORMATION *)buf_ptr; |
| 1378 | status = NtEnumerateValueKey( hkey, index, KeyValueFullInformation, |
| 1379 | buf_ptr, total_size, &total_size ); |
| 1380 | } |
| 1381 | |
| 1382 | if (status) goto done; |
| 1383 | |
| 1384 | if (value) |
| 1385 | { |
| 1386 | if (info->NameLength/sizeof(WCHAR) >= *val_count) |
Alexandre Julliard | a01004d | 2000-05-14 22:57:57 +0000 | [diff] [blame] | 1387 | { |
Alexandre Julliard | 0b6a79c | 2000-12-15 20:57:00 +0000 | [diff] [blame] | 1388 | status = STATUS_BUFFER_OVERFLOW; |
Alexandre Julliard | c1dddbe | 2002-07-10 03:27:35 +0000 | [diff] [blame] | 1389 | goto overflow; |
Alexandre Julliard | 0b6a79c | 2000-12-15 20:57:00 +0000 | [diff] [blame] | 1390 | } |
| 1391 | memcpy( value, info->Name, info->NameLength ); |
| 1392 | *val_count = info->NameLength / sizeof(WCHAR); |
| 1393 | value[*val_count] = 0; |
| 1394 | } |
| 1395 | |
| 1396 | if (data) |
| 1397 | { |
| 1398 | if (total_size - info->DataOffset > *count) |
| 1399 | { |
| 1400 | status = STATUS_BUFFER_OVERFLOW; |
Alexandre Julliard | c1dddbe | 2002-07-10 03:27:35 +0000 | [diff] [blame] | 1401 | goto overflow; |
Alexandre Julliard | 0b6a79c | 2000-12-15 20:57:00 +0000 | [diff] [blame] | 1402 | } |
| 1403 | memcpy( data, buf_ptr + info->DataOffset, total_size - info->DataOffset ); |
| 1404 | if (total_size - info->DataOffset <= *count-sizeof(WCHAR) && is_string(info->Type)) |
| 1405 | { |
| 1406 | /* if the type is REG_SZ and data is not 0-terminated |
| 1407 | * and there is enough space in the buffer NT appends a \0 */ |
| 1408 | WCHAR *ptr = (WCHAR *)(data + total_size - info->DataOffset); |
| 1409 | if (ptr > (WCHAR *)data && ptr[-1]) *ptr = 0; |
Alexandre Julliard | a01004d | 2000-05-14 22:57:57 +0000 | [diff] [blame] | 1410 | } |
| 1411 | } |
Alexandre Julliard | a01004d | 2000-05-14 22:57:57 +0000 | [diff] [blame] | 1412 | } |
Alexandre Julliard | c661583 | 2001-02-14 21:45:52 +0000 | [diff] [blame] | 1413 | else status = STATUS_SUCCESS; |
Alexandre Julliard | 0b6a79c | 2000-12-15 20:57:00 +0000 | [diff] [blame] | 1414 | |
Alexandre Julliard | c1dddbe | 2002-07-10 03:27:35 +0000 | [diff] [blame] | 1415 | overflow: |
Alexandre Julliard | 0b6a79c | 2000-12-15 20:57:00 +0000 | [diff] [blame] | 1416 | if (type) *type = info->Type; |
| 1417 | if (count) *count = info->DataLength; |
| 1418 | |
| 1419 | done: |
| 1420 | if (buf_ptr != buffer) HeapFree( GetProcessHeap(), 0, buf_ptr ); |
| 1421 | return RtlNtStatusToDosError(status); |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 1422 | } |
| 1423 | |
| 1424 | |
| 1425 | /****************************************************************************** |
James Hawkins | 6a358c4 | 2004-07-13 23:33:14 +0000 | [diff] [blame^] | 1426 | * RegEnumValueA [ADVAPI32.@] |
| 1427 | * |
| 1428 | * see RegEnumValueW |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 1429 | */ |
| 1430 | DWORD WINAPI RegEnumValueA( HKEY hkey, DWORD index, LPSTR value, LPDWORD val_count, |
| 1431 | LPDWORD reserved, LPDWORD type, LPBYTE data, LPDWORD count ) |
| 1432 | { |
Alexandre Julliard | 0b6a79c | 2000-12-15 20:57:00 +0000 | [diff] [blame] | 1433 | NTSTATUS status; |
| 1434 | DWORD total_size; |
| 1435 | char buffer[256], *buf_ptr = buffer; |
| 1436 | KEY_VALUE_FULL_INFORMATION *info = (KEY_VALUE_FULL_INFORMATION *)buffer; |
Alexandre Julliard | a010932 | 2002-07-05 21:30:38 +0000 | [diff] [blame] | 1437 | static const int info_size = offsetof( KEY_VALUE_FULL_INFORMATION, Name ); |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 1438 | |
Michael Stefaniuc | cbacde5 | 2002-10-25 19:17:33 +0000 | [diff] [blame] | 1439 | TRACE("(%p,%ld,%p,%p,%p,%p,%p,%p)\n", |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 1440 | hkey, index, value, val_count, reserved, type, data, count ); |
| 1441 | |
| 1442 | /* NT only checks count, not val_count */ |
Eric Pouech | 2c655f5 | 1999-11-25 22:05:46 +0000 | [diff] [blame] | 1443 | if ((data && !count) || reserved) return ERROR_INVALID_PARAMETER; |
Alexandre Julliard | f2ef2c2 | 2002-09-13 21:42:28 +0000 | [diff] [blame] | 1444 | if (!(hkey = get_special_root_hkey( hkey ))) return ERROR_INVALID_HANDLE; |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 1445 | |
Alexandre Julliard | 0b6a79c | 2000-12-15 20:57:00 +0000 | [diff] [blame] | 1446 | total_size = info_size + (MAX_PATH + 1) * sizeof(WCHAR); |
| 1447 | if (data) total_size += *count; |
| 1448 | total_size = min( sizeof(buffer), total_size ); |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 1449 | |
Alexandre Julliard | 0b6a79c | 2000-12-15 20:57:00 +0000 | [diff] [blame] | 1450 | status = NtEnumerateValueKey( hkey, index, KeyValueFullInformation, |
| 1451 | buffer, total_size, &total_size ); |
| 1452 | if (status && status != STATUS_BUFFER_OVERFLOW) goto done; |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 1453 | |
Alexandre Julliard | 0b6a79c | 2000-12-15 20:57:00 +0000 | [diff] [blame] | 1454 | /* we need to fetch the contents for a string type even if not requested, |
| 1455 | * because we need to compute the length of the ASCII string. */ |
| 1456 | if (value || data || is_string(info->Type)) |
Alexandre Julliard | a01004d | 2000-05-14 22:57:57 +0000 | [diff] [blame] | 1457 | { |
Alexandre Julliard | 0b6a79c | 2000-12-15 20:57:00 +0000 | [diff] [blame] | 1458 | /* retry with a dynamically allocated buffer */ |
| 1459 | while (status == STATUS_BUFFER_OVERFLOW) |
Alexandre Julliard | a01004d | 2000-05-14 22:57:57 +0000 | [diff] [blame] | 1460 | { |
Alexandre Julliard | 0b6a79c | 2000-12-15 20:57:00 +0000 | [diff] [blame] | 1461 | if (buf_ptr != buffer) HeapFree( GetProcessHeap(), 0, buf_ptr ); |
| 1462 | if (!(buf_ptr = HeapAlloc( GetProcessHeap(), 0, total_size ))) |
| 1463 | return ERROR_NOT_ENOUGH_MEMORY; |
| 1464 | info = (KEY_VALUE_FULL_INFORMATION *)buf_ptr; |
| 1465 | status = NtEnumerateValueKey( hkey, index, KeyValueFullInformation, |
| 1466 | buf_ptr, total_size, &total_size ); |
Alexandre Julliard | a01004d | 2000-05-14 22:57:57 +0000 | [diff] [blame] | 1467 | } |
Alexandre Julliard | 0b6a79c | 2000-12-15 20:57:00 +0000 | [diff] [blame] | 1468 | |
| 1469 | if (status) goto done; |
| 1470 | |
Alexandre Julliard | 0b6a79c | 2000-12-15 20:57:00 +0000 | [diff] [blame] | 1471 | if (is_string(info->Type)) |
| 1472 | { |
Alexandre Julliard | 60fd03d | 2001-12-05 22:18:48 +0000 | [diff] [blame] | 1473 | DWORD len; |
| 1474 | RtlUnicodeToMultiByteSize( &len, (WCHAR *)(buf_ptr + info->DataOffset), |
| 1475 | total_size - info->DataOffset ); |
Alexandre Julliard | 0b6a79c | 2000-12-15 20:57:00 +0000 | [diff] [blame] | 1476 | if (data && len) |
| 1477 | { |
Alexandre Julliard | c1dddbe | 2002-07-10 03:27:35 +0000 | [diff] [blame] | 1478 | if (len > *count) status = STATUS_BUFFER_OVERFLOW; |
| 1479 | else |
Alexandre Julliard | 0b6a79c | 2000-12-15 20:57:00 +0000 | [diff] [blame] | 1480 | { |
Alexandre Julliard | c1dddbe | 2002-07-10 03:27:35 +0000 | [diff] [blame] | 1481 | RtlUnicodeToMultiByteN( data, len, NULL, (WCHAR *)(buf_ptr + info->DataOffset), |
| 1482 | total_size - info->DataOffset ); |
| 1483 | /* if the type is REG_SZ and data is not 0-terminated |
| 1484 | * and there is enough space in the buffer NT appends a \0 */ |
| 1485 | if (len < *count && data[len-1]) data[len] = 0; |
Alexandre Julliard | 0b6a79c | 2000-12-15 20:57:00 +0000 | [diff] [blame] | 1486 | } |
Alexandre Julliard | 0b6a79c | 2000-12-15 20:57:00 +0000 | [diff] [blame] | 1487 | } |
| 1488 | info->DataLength = len; |
| 1489 | } |
| 1490 | else if (data) |
| 1491 | { |
| 1492 | if (total_size - info->DataOffset > *count) status = STATUS_BUFFER_OVERFLOW; |
| 1493 | else memcpy( data, buf_ptr + info->DataOffset, total_size - info->DataOffset ); |
| 1494 | } |
Alexandre Julliard | c1dddbe | 2002-07-10 03:27:35 +0000 | [diff] [blame] | 1495 | |
| 1496 | if (value && !status) |
| 1497 | { |
| 1498 | DWORD len; |
| 1499 | |
| 1500 | RtlUnicodeToMultiByteSize( &len, info->Name, info->NameLength ); |
| 1501 | if (len >= *val_count) |
| 1502 | { |
| 1503 | status = STATUS_BUFFER_OVERFLOW; |
| 1504 | if (*val_count) |
| 1505 | { |
| 1506 | len = *val_count - 1; |
| 1507 | RtlUnicodeToMultiByteN( value, len, NULL, info->Name, info->NameLength ); |
| 1508 | value[len] = 0; |
| 1509 | } |
| 1510 | } |
| 1511 | else |
| 1512 | { |
| 1513 | RtlUnicodeToMultiByteN( value, len, NULL, info->Name, info->NameLength ); |
| 1514 | value[len] = 0; |
| 1515 | *val_count = len; |
| 1516 | } |
| 1517 | } |
Alexandre Julliard | a01004d | 2000-05-14 22:57:57 +0000 | [diff] [blame] | 1518 | } |
Alexandre Julliard | c661583 | 2001-02-14 21:45:52 +0000 | [diff] [blame] | 1519 | else status = STATUS_SUCCESS; |
Alexandre Julliard | a01004d | 2000-05-14 22:57:57 +0000 | [diff] [blame] | 1520 | |
Alexandre Julliard | 0b6a79c | 2000-12-15 20:57:00 +0000 | [diff] [blame] | 1521 | if (type) *type = info->Type; |
| 1522 | if (count) *count = info->DataLength; |
| 1523 | |
| 1524 | done: |
| 1525 | if (buf_ptr != buffer) HeapFree( GetProcessHeap(), 0, buf_ptr ); |
| 1526 | return RtlNtStatusToDosError(status); |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 1527 | } |
| 1528 | |
| 1529 | |
| 1530 | |
| 1531 | /****************************************************************************** |
James Hawkins | 6a358c4 | 2004-07-13 23:33:14 +0000 | [diff] [blame^] | 1532 | * RegDeleteValueW [ADVAPI32.@] |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 1533 | * |
Jon Griffiths | cd4234a | 2003-03-18 18:35:48 +0000 | [diff] [blame] | 1534 | * See RegDeleteValueA. |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 1535 | */ |
| 1536 | DWORD WINAPI RegDeleteValueW( HKEY hkey, LPCWSTR name ) |
| 1537 | { |
Alexandre Julliard | bcf393a | 2000-10-01 01:44:50 +0000 | [diff] [blame] | 1538 | UNICODE_STRING nameW; |
Alexandre Julliard | f2ef2c2 | 2002-09-13 21:42:28 +0000 | [diff] [blame] | 1539 | |
| 1540 | if (!(hkey = get_special_root_hkey( hkey ))) return ERROR_INVALID_HANDLE; |
| 1541 | |
Alexandre Julliard | bcf393a | 2000-10-01 01:44:50 +0000 | [diff] [blame] | 1542 | RtlInitUnicodeString( &nameW, name ); |
| 1543 | return RtlNtStatusToDosError( NtDeleteValueKey( hkey, &nameW ) ); |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 1544 | } |
| 1545 | |
| 1546 | |
| 1547 | /****************************************************************************** |
James Hawkins | 6a358c4 | 2004-07-13 23:33:14 +0000 | [diff] [blame^] | 1548 | * RegDeleteValueA [ADVAPI32.@] |
Jon Griffiths | cd4234a | 2003-03-18 18:35:48 +0000 | [diff] [blame] | 1549 | * |
| 1550 | * Delete a value from the registry. |
| 1551 | * |
| 1552 | * PARAMS |
| 1553 | * hkey [I] Registry handle of the key holding the value |
| 1554 | * name [I] Name of the value under hkey to delete |
| 1555 | * |
| 1556 | * RETURNS |
James Hawkins | 6a358c4 | 2004-07-13 23:33:14 +0000 | [diff] [blame^] | 1557 | * Success: ERROR_SUCCESS |
| 1558 | * Failure: nonzero error code from Winerror.h |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 1559 | */ |
| 1560 | DWORD WINAPI RegDeleteValueA( HKEY hkey, LPCSTR name ) |
| 1561 | { |
Alexandre Julliard | bcf393a | 2000-10-01 01:44:50 +0000 | [diff] [blame] | 1562 | STRING nameA; |
| 1563 | NTSTATUS status; |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 1564 | |
Alexandre Julliard | f2ef2c2 | 2002-09-13 21:42:28 +0000 | [diff] [blame] | 1565 | if (!(hkey = get_special_root_hkey( hkey ))) return ERROR_INVALID_HANDLE; |
| 1566 | |
Alexandre Julliard | bcf393a | 2000-10-01 01:44:50 +0000 | [diff] [blame] | 1567 | RtlInitAnsiString( &nameA, name ); |
Alexandre Julliard | ab5e975 | 2001-03-23 19:12:01 +0000 | [diff] [blame] | 1568 | if (!(status = RtlAnsiStringToUnicodeString( &NtCurrentTeb()->StaticUnicodeString, |
| 1569 | &nameA, FALSE ))) |
Alexandre Julliard | ab5e975 | 2001-03-23 19:12:01 +0000 | [diff] [blame] | 1570 | status = NtDeleteValueKey( hkey, &NtCurrentTeb()->StaticUnicodeString ); |
Alexandre Julliard | bcf393a | 2000-10-01 01:44:50 +0000 | [diff] [blame] | 1571 | return RtlNtStatusToDosError( status ); |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 1572 | } |
| 1573 | |
| 1574 | |
| 1575 | /****************************************************************************** |
James Hawkins | 6a358c4 | 2004-07-13 23:33:14 +0000 | [diff] [blame^] | 1576 | * RegLoadKeyW [ADVAPI32.@] |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 1577 | * |
| 1578 | * PARAMS |
James Hawkins | 6a358c4 | 2004-07-13 23:33:14 +0000 | [diff] [blame^] | 1579 | * hkey [I] Handle of open key |
| 1580 | * subkey [I] Address of name of subkey |
| 1581 | * filename [I] Address of filename for registry information |
| 1582 | * |
| 1583 | * RETURNS |
| 1584 | * Success: ERROR_SUCCES |
| 1585 | * Failure: nonzero error code from Winerror.h |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 1586 | */ |
| 1587 | LONG WINAPI RegLoadKeyW( HKEY hkey, LPCWSTR subkey, LPCWSTR filename ) |
| 1588 | { |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 1589 | HANDLE file; |
Alexandre Julliard | 57f05e1 | 2000-10-15 00:40:25 +0000 | [diff] [blame] | 1590 | DWORD ret, len, err = GetLastError(); |
Aric Stewart | cdb9be7 | 2002-11-13 19:45:27 +0000 | [diff] [blame] | 1591 | HKEY shkey; |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 1592 | |
Michael Stefaniuc | cbacde5 | 2002-10-25 19:17:33 +0000 | [diff] [blame] | 1593 | TRACE( "(%p,%s,%s)\n", hkey, debugstr_w(subkey), debugstr_w(filename) ); |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 1594 | |
| 1595 | if (!filename || !*filename) return ERROR_INVALID_PARAMETER; |
| 1596 | if (!subkey || !*subkey) return ERROR_INVALID_PARAMETER; |
Alexandre Julliard | f2ef2c2 | 2002-09-13 21:42:28 +0000 | [diff] [blame] | 1597 | if (!(hkey = get_special_root_hkey( hkey ))) return ERROR_INVALID_HANDLE; |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 1598 | |
Alexandre Julliard | 57f05e1 | 2000-10-15 00:40:25 +0000 | [diff] [blame] | 1599 | len = strlenW( subkey ) * sizeof(WCHAR); |
| 1600 | if (len > MAX_PATH*sizeof(WCHAR)) return ERROR_INVALID_PARAMETER; |
| 1601 | |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 1602 | if ((file = CreateFileW( filename, GENERIC_READ, 0, NULL, OPEN_EXISTING, |
François Gouget | da2b6a9 | 2001-01-06 01:29:18 +0000 | [diff] [blame] | 1603 | FILE_ATTRIBUTE_NORMAL, 0 )) == INVALID_HANDLE_VALUE) |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 1604 | { |
| 1605 | ret = GetLastError(); |
| 1606 | goto done; |
| 1607 | } |
Alexandre Julliard | 57f05e1 | 2000-10-15 00:40:25 +0000 | [diff] [blame] | 1608 | |
Aric Stewart | cdb9be7 | 2002-11-13 19:45:27 +0000 | [diff] [blame] | 1609 | RegCreateKeyW(hkey,subkey,&shkey); |
| 1610 | |
Alexandre Julliard | 9caa71e | 2001-11-30 18:46:42 +0000 | [diff] [blame] | 1611 | SERVER_START_REQ( load_registry ) |
Alexandre Julliard | 57f05e1 | 2000-10-15 00:40:25 +0000 | [diff] [blame] | 1612 | { |
Aric Stewart | cdb9be7 | 2002-11-13 19:45:27 +0000 | [diff] [blame] | 1613 | req->hkey = shkey; |
Alexandre Julliard | 57f05e1 | 2000-10-15 00:40:25 +0000 | [diff] [blame] | 1614 | req->file = file; |
Alexandre Julliard | 9caa71e | 2001-11-30 18:46:42 +0000 | [diff] [blame] | 1615 | wine_server_add_data( req, subkey, len ); |
| 1616 | ret = RtlNtStatusToDosError( wine_server_call(req) ); |
Alexandre Julliard | 57f05e1 | 2000-10-15 00:40:25 +0000 | [diff] [blame] | 1617 | } |
Alexandre Julliard | 9caa71e | 2001-11-30 18:46:42 +0000 | [diff] [blame] | 1618 | SERVER_END_REQ; |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 1619 | CloseHandle( file ); |
Aric Stewart | cdb9be7 | 2002-11-13 19:45:27 +0000 | [diff] [blame] | 1620 | RegCloseKey(shkey); |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 1621 | |
| 1622 | done: |
| 1623 | SetLastError( err ); /* restore the last error code */ |
| 1624 | return ret; |
| 1625 | } |
| 1626 | |
| 1627 | |
| 1628 | /****************************************************************************** |
James Hawkins | 6a358c4 | 2004-07-13 23:33:14 +0000 | [diff] [blame^] | 1629 | * RegLoadKeyA [ADVAPI32.@] |
| 1630 | * |
| 1631 | * see RegLoadKeyW |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 1632 | */ |
| 1633 | LONG WINAPI RegLoadKeyA( HKEY hkey, LPCSTR subkey, LPCSTR filename ) |
| 1634 | { |
Alexandre Julliard | 9caa71e | 2001-11-30 18:46:42 +0000 | [diff] [blame] | 1635 | WCHAR buffer[MAX_PATH]; |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 1636 | HANDLE file; |
Alexandre Julliard | 57f05e1 | 2000-10-15 00:40:25 +0000 | [diff] [blame] | 1637 | DWORD ret, len, err = GetLastError(); |
Aric Stewart | cdb9be7 | 2002-11-13 19:45:27 +0000 | [diff] [blame] | 1638 | HKEY shkey; |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 1639 | |
Michael Stefaniuc | cbacde5 | 2002-10-25 19:17:33 +0000 | [diff] [blame] | 1640 | TRACE( "(%p,%s,%s)\n", hkey, debugstr_a(subkey), debugstr_a(filename) ); |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 1641 | |
| 1642 | if (!filename || !*filename) return ERROR_INVALID_PARAMETER; |
| 1643 | if (!subkey || !*subkey) return ERROR_INVALID_PARAMETER; |
Alexandre Julliard | f2ef2c2 | 2002-09-13 21:42:28 +0000 | [diff] [blame] | 1644 | if (!(hkey = get_special_root_hkey( hkey ))) return ERROR_INVALID_HANDLE; |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 1645 | |
Alexandre Julliard | 9caa71e | 2001-11-30 18:46:42 +0000 | [diff] [blame] | 1646 | if (!(len = MultiByteToWideChar( CP_ACP, 0, subkey, strlen(subkey), buffer, MAX_PATH ))) |
| 1647 | return ERROR_INVALID_PARAMETER; |
Alexandre Julliard | 57f05e1 | 2000-10-15 00:40:25 +0000 | [diff] [blame] | 1648 | |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 1649 | if ((file = CreateFileA( filename, GENERIC_READ, 0, NULL, OPEN_EXISTING, |
François Gouget | da2b6a9 | 2001-01-06 01:29:18 +0000 | [diff] [blame] | 1650 | FILE_ATTRIBUTE_NORMAL, 0 )) == INVALID_HANDLE_VALUE) |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 1651 | { |
| 1652 | ret = GetLastError(); |
| 1653 | goto done; |
| 1654 | } |
Alexandre Julliard | 57f05e1 | 2000-10-15 00:40:25 +0000 | [diff] [blame] | 1655 | |
Aric Stewart | cdb9be7 | 2002-11-13 19:45:27 +0000 | [diff] [blame] | 1656 | RegCreateKeyA(hkey,subkey,&shkey); |
| 1657 | |
Alexandre Julliard | 9caa71e | 2001-11-30 18:46:42 +0000 | [diff] [blame] | 1658 | SERVER_START_REQ( load_registry ) |
Alexandre Julliard | 57f05e1 | 2000-10-15 00:40:25 +0000 | [diff] [blame] | 1659 | { |
Aric Stewart | cdb9be7 | 2002-11-13 19:45:27 +0000 | [diff] [blame] | 1660 | req->hkey = shkey; |
Alexandre Julliard | 57f05e1 | 2000-10-15 00:40:25 +0000 | [diff] [blame] | 1661 | req->file = file; |
Alexandre Julliard | 9caa71e | 2001-11-30 18:46:42 +0000 | [diff] [blame] | 1662 | wine_server_add_data( req, buffer, len * sizeof(WCHAR) ); |
| 1663 | ret = RtlNtStatusToDosError( wine_server_call(req) ); |
Alexandre Julliard | 57f05e1 | 2000-10-15 00:40:25 +0000 | [diff] [blame] | 1664 | } |
Alexandre Julliard | 9caa71e | 2001-11-30 18:46:42 +0000 | [diff] [blame] | 1665 | SERVER_END_REQ; |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 1666 | CloseHandle( file ); |
Aric Stewart | cdb9be7 | 2002-11-13 19:45:27 +0000 | [diff] [blame] | 1667 | RegCloseKey(shkey); |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 1668 | |
| 1669 | done: |
| 1670 | SetLastError( err ); /* restore the last error code */ |
| 1671 | return ret; |
| 1672 | } |
| 1673 | |
| 1674 | |
| 1675 | /****************************************************************************** |
James Hawkins | 6a358c4 | 2004-07-13 23:33:14 +0000 | [diff] [blame^] | 1676 | * RegSaveKeyW [ADVAPI32.@] |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 1677 | * |
| 1678 | * PARAMS |
James Hawkins | 6a358c4 | 2004-07-13 23:33:14 +0000 | [diff] [blame^] | 1679 | * hkey [I] Handle of key where save begins |
| 1680 | * lpFile [I] Address of filename to save to |
| 1681 | * sa [I] Address of security structure |
| 1682 | * |
| 1683 | * RETURNS |
| 1684 | * Success: ERROR_SUCCESS |
| 1685 | * Failure: nonzero error code from Winerror.h |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 1686 | */ |
Tony Lambregts | 4550b8b | 2003-03-14 04:50:34 +0000 | [diff] [blame] | 1687 | LONG WINAPI RegSaveKeyW( HKEY hkey, LPCWSTR file, LPSECURITY_ATTRIBUTES sa ) |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 1688 | { |
Tony Lambregts | 4550b8b | 2003-03-14 04:50:34 +0000 | [diff] [blame] | 1689 | static const WCHAR format[] = |
| 1690 | {'r','e','g','%','0','4','x','.','t','m','p',0}; |
| 1691 | WCHAR buffer[MAX_PATH]; |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 1692 | int count = 0; |
Tony Lambregts | 4550b8b | 2003-03-14 04:50:34 +0000 | [diff] [blame] | 1693 | LPWSTR nameW; |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 1694 | DWORD ret, err; |
Alexandre Julliard | 7375597 | 2002-07-31 19:26:03 +0000 | [diff] [blame] | 1695 | HANDLE handle; |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 1696 | |
Tony Lambregts | 4550b8b | 2003-03-14 04:50:34 +0000 | [diff] [blame] | 1697 | TRACE( "(%p,%s,%p)\n", hkey, debugstr_w(file), sa ); |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 1698 | |
| 1699 | if (!file || !*file) return ERROR_INVALID_PARAMETER; |
Alexandre Julliard | f2ef2c2 | 2002-09-13 21:42:28 +0000 | [diff] [blame] | 1700 | if (!(hkey = get_special_root_hkey( hkey ))) return ERROR_INVALID_HANDLE; |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 1701 | |
| 1702 | err = GetLastError(); |
Tony Lambregts | 4550b8b | 2003-03-14 04:50:34 +0000 | [diff] [blame] | 1703 | GetFullPathNameW( file, sizeof(buffer)/sizeof(WCHAR), buffer, &nameW ); |
| 1704 | |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 1705 | for (;;) |
| 1706 | { |
Tony Lambregts | 4550b8b | 2003-03-14 04:50:34 +0000 | [diff] [blame] | 1707 | snprintfW( nameW, 16, format, count++ ); |
| 1708 | handle = CreateFileW( buffer, GENERIC_WRITE, 0, NULL, |
François Gouget | da2b6a9 | 2001-01-06 01:29:18 +0000 | [diff] [blame] | 1709 | CREATE_NEW, FILE_ATTRIBUTE_NORMAL, 0 ); |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 1710 | if (handle != INVALID_HANDLE_VALUE) break; |
Alexandre Julliard | 5354417 | 2000-03-26 18:18:03 +0000 | [diff] [blame] | 1711 | if ((ret = GetLastError()) != ERROR_ALREADY_EXISTS) goto done; |
Andreas Mohr | 6297451 | 2000-05-09 22:31:43 +0000 | [diff] [blame] | 1712 | |
| 1713 | /* Something gone haywire ? Please report if this happens abnormally */ |
| 1714 | if (count >= 100) |
Tony Lambregts | 4550b8b | 2003-03-14 04:50:34 +0000 | [diff] [blame] | 1715 | 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] | 1716 | } |
| 1717 | |
Alexandre Julliard | 67a7499 | 2001-02-27 02:09:16 +0000 | [diff] [blame] | 1718 | SERVER_START_REQ( save_registry ) |
Alexandre Julliard | 57f05e1 | 2000-10-15 00:40:25 +0000 | [diff] [blame] | 1719 | { |
Alexandre Julliard | 57f05e1 | 2000-10-15 00:40:25 +0000 | [diff] [blame] | 1720 | req->hkey = hkey; |
| 1721 | req->file = handle; |
Alexandre Julliard | 9caa71e | 2001-11-30 18:46:42 +0000 | [diff] [blame] | 1722 | ret = RtlNtStatusToDosError( wine_server_call( req ) ); |
Alexandre Julliard | 57f05e1 | 2000-10-15 00:40:25 +0000 | [diff] [blame] | 1723 | } |
| 1724 | SERVER_END_REQ; |
| 1725 | |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 1726 | CloseHandle( handle ); |
| 1727 | if (!ret) |
| 1728 | { |
Tony Lambregts | 4550b8b | 2003-03-14 04:50:34 +0000 | [diff] [blame] | 1729 | if (!MoveFileExW( buffer, file, MOVEFILE_REPLACE_EXISTING )) |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 1730 | { |
Tony Lambregts | 4550b8b | 2003-03-14 04:50:34 +0000 | [diff] [blame] | 1731 | ERR( "Failed to move %s to %s\n", debugstr_w(buffer), |
| 1732 | debugstr_w(file) ); |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 1733 | ret = GetLastError(); |
| 1734 | } |
| 1735 | } |
Tony Lambregts | 4550b8b | 2003-03-14 04:50:34 +0000 | [diff] [blame] | 1736 | if (ret) DeleteFileW( buffer ); |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 1737 | |
| 1738 | done: |
| 1739 | SetLastError( err ); /* restore last error code */ |
| 1740 | return ret; |
| 1741 | } |
| 1742 | |
| 1743 | |
| 1744 | /****************************************************************************** |
James Hawkins | 6a358c4 | 2004-07-13 23:33:14 +0000 | [diff] [blame^] | 1745 | * RegSaveKeyA [ADVAPI32.@] |
| 1746 | * |
| 1747 | * see RegSaveKeyW |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 1748 | */ |
Tony Lambregts | 4550b8b | 2003-03-14 04:50:34 +0000 | [diff] [blame] | 1749 | LONG WINAPI RegSaveKeyA( HKEY hkey, LPCSTR file, LPSECURITY_ATTRIBUTES sa ) |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 1750 | { |
Tony Lambregts | 4550b8b | 2003-03-14 04:50:34 +0000 | [diff] [blame] | 1751 | UNICODE_STRING *fileW = &NtCurrentTeb()->StaticUnicodeString; |
| 1752 | NTSTATUS status; |
| 1753 | STRING fileA; |
| 1754 | |
| 1755 | RtlInitAnsiString(&fileA, file); |
| 1756 | if ((status = RtlAnsiStringToUnicodeString(fileW, &fileA, FALSE))) |
| 1757 | return RtlNtStatusToDosError( status ); |
| 1758 | return RegSaveKeyW(hkey, fileW->Buffer, sa); |
Alexandre Julliard | 2fab2ef | 1999-11-23 19:41:34 +0000 | [diff] [blame] | 1759 | } |
Alexandre Julliard | 5ce2329 | 2000-11-30 20:31:41 +0000 | [diff] [blame] | 1760 | |
| 1761 | |
| 1762 | /****************************************************************************** |
Patrik Stridvall | d0a4177 | 2001-02-14 23:11:17 +0000 | [diff] [blame] | 1763 | * RegRestoreKeyW [ADVAPI32.@] |
Alexandre Julliard | 5ce2329 | 2000-11-30 20:31:41 +0000 | [diff] [blame] | 1764 | * |
| 1765 | * PARAMS |
James Hawkins | 6a358c4 | 2004-07-13 23:33:14 +0000 | [diff] [blame^] | 1766 | * hkey [I] Handle of key where restore begins |
| 1767 | * lpFile [I] Address of filename containing saved tree |
| 1768 | * dwFlags [I] Optional flags |
| 1769 | * |
| 1770 | * RETURNS |
| 1771 | * Success: ERROR_SUCCESS |
| 1772 | * Failure: nonzero error code from Winerror.h |
Alexandre Julliard | 5ce2329 | 2000-11-30 20:31:41 +0000 | [diff] [blame] | 1773 | */ |
| 1774 | LONG WINAPI RegRestoreKeyW( HKEY hkey, LPCWSTR lpFile, DWORD dwFlags ) |
| 1775 | { |
Michael Stefaniuc | cbacde5 | 2002-10-25 19:17:33 +0000 | [diff] [blame] | 1776 | TRACE("(%p,%s,%ld)\n",hkey,debugstr_w(lpFile),dwFlags); |
Alexandre Julliard | 5ce2329 | 2000-11-30 20:31:41 +0000 | [diff] [blame] | 1777 | |
| 1778 | /* It seems to do this check before the hkey check */ |
| 1779 | if (!lpFile || !*lpFile) |
| 1780 | return ERROR_INVALID_PARAMETER; |
| 1781 | |
Michael Stefaniuc | cbacde5 | 2002-10-25 19:17:33 +0000 | [diff] [blame] | 1782 | FIXME("(%p,%s,%ld): stub\n",hkey,debugstr_w(lpFile),dwFlags); |
Alexandre Julliard | 5ce2329 | 2000-11-30 20:31:41 +0000 | [diff] [blame] | 1783 | |
| 1784 | /* Check for file existence */ |
| 1785 | |
| 1786 | return ERROR_SUCCESS; |
| 1787 | } |
| 1788 | |
| 1789 | |
| 1790 | /****************************************************************************** |
Patrik Stridvall | d0a4177 | 2001-02-14 23:11:17 +0000 | [diff] [blame] | 1791 | * RegRestoreKeyA [ADVAPI32.@] |
James Hawkins | 6a358c4 | 2004-07-13 23:33:14 +0000 | [diff] [blame^] | 1792 | * |
| 1793 | * see RegRestoreKeyW |
Alexandre Julliard | 5ce2329 | 2000-11-30 20:31:41 +0000 | [diff] [blame] | 1794 | */ |
| 1795 | LONG WINAPI RegRestoreKeyA( HKEY hkey, LPCSTR lpFile, DWORD dwFlags ) |
| 1796 | { |
Matthew Davison | 6f2a071 | 2003-01-20 23:23:12 +0000 | [diff] [blame] | 1797 | UNICODE_STRING lpFileW; |
| 1798 | LONG ret; |
| 1799 | |
| 1800 | RtlCreateUnicodeStringFromAsciiz( &lpFileW, lpFile ); |
| 1801 | ret = RegRestoreKeyW( hkey, lpFileW.Buffer, dwFlags ); |
| 1802 | RtlFreeUnicodeString( &lpFileW ); |
Alexandre Julliard | 5ce2329 | 2000-11-30 20:31:41 +0000 | [diff] [blame] | 1803 | return ret; |
| 1804 | } |
| 1805 | |
| 1806 | |
| 1807 | /****************************************************************************** |
Patrik Stridvall | d0a4177 | 2001-02-14 23:11:17 +0000 | [diff] [blame] | 1808 | * RegUnLoadKeyW [ADVAPI32.@] |
Alexandre Julliard | 5ce2329 | 2000-11-30 20:31:41 +0000 | [diff] [blame] | 1809 | * |
| 1810 | * PARAMS |
James Hawkins | 6a358c4 | 2004-07-13 23:33:14 +0000 | [diff] [blame^] | 1811 | * hkey [I] Handle of open key |
| 1812 | * lpSubKey [I] Address of name of subkey to unload |
| 1813 | * |
| 1814 | * RETURNS |
| 1815 | * Success: ERROR_SUCCESS |
| 1816 | * Failure: nonzero error code from Winerror.h |
Alexandre Julliard | 5ce2329 | 2000-11-30 20:31:41 +0000 | [diff] [blame] | 1817 | */ |
| 1818 | LONG WINAPI RegUnLoadKeyW( HKEY hkey, LPCWSTR lpSubKey ) |
| 1819 | { |
Mike McCormack | 5ac945c | 2003-08-19 03:08:17 +0000 | [diff] [blame] | 1820 | DWORD ret; |
| 1821 | HKEY shkey; |
| 1822 | |
| 1823 | TRACE("(%p,%s)\n",hkey, debugstr_w(lpSubKey)); |
| 1824 | |
| 1825 | ret = RegOpenKeyW(hkey,lpSubKey,&shkey); |
| 1826 | if( ret ) |
| 1827 | return ERROR_INVALID_PARAMETER; |
| 1828 | |
| 1829 | SERVER_START_REQ( unload_registry ) |
| 1830 | { |
| 1831 | req->hkey = shkey; |
| 1832 | ret = RtlNtStatusToDosError( wine_server_call(req) ); |
| 1833 | } |
| 1834 | SERVER_END_REQ; |
| 1835 | RegCloseKey(shkey); |
| 1836 | |
| 1837 | return ret; |
Alexandre Julliard | 5ce2329 | 2000-11-30 20:31:41 +0000 | [diff] [blame] | 1838 | } |
| 1839 | |
| 1840 | |
| 1841 | /****************************************************************************** |
Patrik Stridvall | d0a4177 | 2001-02-14 23:11:17 +0000 | [diff] [blame] | 1842 | * RegUnLoadKeyA [ADVAPI32.@] |
James Hawkins | 6a358c4 | 2004-07-13 23:33:14 +0000 | [diff] [blame^] | 1843 | * |
| 1844 | * see RegUnLoadKeyW |
Alexandre Julliard | 5ce2329 | 2000-11-30 20:31:41 +0000 | [diff] [blame] | 1845 | */ |
| 1846 | LONG WINAPI RegUnLoadKeyA( HKEY hkey, LPCSTR lpSubKey ) |
| 1847 | { |
Matthew Davison | 6f2a071 | 2003-01-20 23:23:12 +0000 | [diff] [blame] | 1848 | UNICODE_STRING lpSubKeyW; |
| 1849 | LONG ret; |
| 1850 | |
| 1851 | RtlCreateUnicodeStringFromAsciiz( &lpSubKeyW, lpSubKey ); |
| 1852 | ret = RegUnLoadKeyW( hkey, lpSubKeyW.Buffer ); |
| 1853 | RtlFreeUnicodeString( &lpSubKeyW ); |
Alexandre Julliard | 5ce2329 | 2000-11-30 20:31:41 +0000 | [diff] [blame] | 1854 | return ret; |
| 1855 | } |
| 1856 | |
| 1857 | |
| 1858 | /****************************************************************************** |
Patrik Stridvall | d0a4177 | 2001-02-14 23:11:17 +0000 | [diff] [blame] | 1859 | * RegReplaceKeyW [ADVAPI32.@] |
Alexandre Julliard | 5ce2329 | 2000-11-30 20:31:41 +0000 | [diff] [blame] | 1860 | * |
| 1861 | * PARAMS |
James Hawkins | 6a358c4 | 2004-07-13 23:33:14 +0000 | [diff] [blame^] | 1862 | * hkey [I] Handle of open key |
| 1863 | * lpSubKey [I] Address of name of subkey |
| 1864 | * lpNewFile [I] Address of filename for file with new data |
| 1865 | * lpOldFile [I] Address of filename for backup file |
| 1866 | * |
| 1867 | * RETURNS |
| 1868 | * Success: ERROR_SUCCESS |
| 1869 | * Failure: nonzero error code from Winerror.h |
Alexandre Julliard | 5ce2329 | 2000-11-30 20:31:41 +0000 | [diff] [blame] | 1870 | */ |
| 1871 | LONG WINAPI RegReplaceKeyW( HKEY hkey, LPCWSTR lpSubKey, LPCWSTR lpNewFile, |
| 1872 | LPCWSTR lpOldFile ) |
| 1873 | { |
Michael Stefaniuc | cbacde5 | 2002-10-25 19:17:33 +0000 | [diff] [blame] | 1874 | FIXME("(%p,%s,%s,%s): stub\n", hkey, debugstr_w(lpSubKey), |
Alexandre Julliard | 5ce2329 | 2000-11-30 20:31:41 +0000 | [diff] [blame] | 1875 | debugstr_w(lpNewFile),debugstr_w(lpOldFile)); |
| 1876 | return ERROR_SUCCESS; |
| 1877 | } |
| 1878 | |
| 1879 | |
| 1880 | /****************************************************************************** |
Patrik Stridvall | d0a4177 | 2001-02-14 23:11:17 +0000 | [diff] [blame] | 1881 | * RegReplaceKeyA [ADVAPI32.@] |
James Hawkins | 6a358c4 | 2004-07-13 23:33:14 +0000 | [diff] [blame^] | 1882 | * |
| 1883 | * see RegReplaceKeyW |
Alexandre Julliard | 5ce2329 | 2000-11-30 20:31:41 +0000 | [diff] [blame] | 1884 | */ |
| 1885 | LONG WINAPI RegReplaceKeyA( HKEY hkey, LPCSTR lpSubKey, LPCSTR lpNewFile, |
| 1886 | LPCSTR lpOldFile ) |
| 1887 | { |
Matthew Davison | 6f2a071 | 2003-01-20 23:23:12 +0000 | [diff] [blame] | 1888 | UNICODE_STRING lpSubKeyW; |
| 1889 | UNICODE_STRING lpNewFileW; |
| 1890 | UNICODE_STRING lpOldFileW; |
| 1891 | LONG ret; |
| 1892 | |
| 1893 | RtlCreateUnicodeStringFromAsciiz( &lpSubKeyW, lpSubKey ); |
| 1894 | RtlCreateUnicodeStringFromAsciiz( &lpOldFileW, lpOldFile ); |
| 1895 | RtlCreateUnicodeStringFromAsciiz( &lpNewFileW, lpNewFile ); |
| 1896 | ret = RegReplaceKeyW( hkey, lpSubKeyW.Buffer, lpNewFileW.Buffer, lpOldFileW.Buffer ); |
| 1897 | RtlFreeUnicodeString( &lpOldFileW ); |
| 1898 | RtlFreeUnicodeString( &lpNewFileW ); |
| 1899 | RtlFreeUnicodeString( &lpSubKeyW ); |
Alexandre Julliard | 5ce2329 | 2000-11-30 20:31:41 +0000 | [diff] [blame] | 1900 | return ret; |
| 1901 | } |
| 1902 | |
| 1903 | |
| 1904 | /****************************************************************************** |
Patrik Stridvall | d0a4177 | 2001-02-14 23:11:17 +0000 | [diff] [blame] | 1905 | * RegSetKeySecurity [ADVAPI32.@] |
Alexandre Julliard | 5ce2329 | 2000-11-30 20:31:41 +0000 | [diff] [blame] | 1906 | * |
| 1907 | * PARAMS |
James Hawkins | 6a358c4 | 2004-07-13 23:33:14 +0000 | [diff] [blame^] | 1908 | * hkey [I] Open handle of key to set |
| 1909 | * SecurityInfo [I] Descriptor contents |
| 1910 | * pSecurityDesc [I] Address of descriptor for key |
| 1911 | * |
| 1912 | * RETURNS |
| 1913 | * Success: ERROR_SUCCESS |
| 1914 | * Failure: nonzero error code from Winerror.h |
Alexandre Julliard | 5ce2329 | 2000-11-30 20:31:41 +0000 | [diff] [blame] | 1915 | */ |
| 1916 | LONG WINAPI RegSetKeySecurity( HKEY hkey, SECURITY_INFORMATION SecurityInfo, |
| 1917 | PSECURITY_DESCRIPTOR pSecurityDesc ) |
| 1918 | { |
Michael Stefaniuc | cbacde5 | 2002-10-25 19:17:33 +0000 | [diff] [blame] | 1919 | TRACE("(%p,%ld,%p)\n",hkey,SecurityInfo,pSecurityDesc); |
Alexandre Julliard | 5ce2329 | 2000-11-30 20:31:41 +0000 | [diff] [blame] | 1920 | |
| 1921 | /* It seems to perform this check before the hkey check */ |
| 1922 | if ((SecurityInfo & OWNER_SECURITY_INFORMATION) || |
| 1923 | (SecurityInfo & GROUP_SECURITY_INFORMATION) || |
| 1924 | (SecurityInfo & DACL_SECURITY_INFORMATION) || |
| 1925 | (SecurityInfo & SACL_SECURITY_INFORMATION)) { |
| 1926 | /* Param OK */ |
| 1927 | } else |
| 1928 | return ERROR_INVALID_PARAMETER; |
| 1929 | |
| 1930 | if (!pSecurityDesc) |
| 1931 | return ERROR_INVALID_PARAMETER; |
| 1932 | |
Michael Stefaniuc | cbacde5 | 2002-10-25 19:17:33 +0000 | [diff] [blame] | 1933 | FIXME(":(%p,%ld,%p): stub\n",hkey,SecurityInfo,pSecurityDesc); |
Alexandre Julliard | 5ce2329 | 2000-11-30 20:31:41 +0000 | [diff] [blame] | 1934 | |
| 1935 | return ERROR_SUCCESS; |
| 1936 | } |
| 1937 | |
| 1938 | |
| 1939 | /****************************************************************************** |
Patrik Stridvall | d0a4177 | 2001-02-14 23:11:17 +0000 | [diff] [blame] | 1940 | * RegGetKeySecurity [ADVAPI32.@] |
Jon Griffiths | 50ce084 | 2004-04-23 21:32:34 +0000 | [diff] [blame] | 1941 | * |
| 1942 | * Get a copy of the security descriptor for a given registry key. |
Alexandre Julliard | 5ce2329 | 2000-11-30 20:31:41 +0000 | [diff] [blame] | 1943 | * |
| 1944 | * PARAMS |
James Hawkins | 6a358c4 | 2004-07-13 23:33:14 +0000 | [diff] [blame^] | 1945 | * hkey [I] Open handle of key to set |
| 1946 | * SecurityInformation [I] Descriptor contents |
| 1947 | * pSecurityDescriptor [O] Address of descriptor for key |
| 1948 | * lpcbSecurityDescriptor [I/O] Address of size of buffer and description |
Alexandre Julliard | 5ce2329 | 2000-11-30 20:31:41 +0000 | [diff] [blame] | 1949 | * |
| 1950 | * RETURNS |
James Hawkins | 6a358c4 | 2004-07-13 23:33:14 +0000 | [diff] [blame^] | 1951 | * Success: ERROR_SUCCESS |
| 1952 | * Failure: Error code |
Alexandre Julliard | 5ce2329 | 2000-11-30 20:31:41 +0000 | [diff] [blame] | 1953 | */ |
| 1954 | LONG WINAPI RegGetKeySecurity( HKEY hkey, SECURITY_INFORMATION SecurityInformation, |
| 1955 | PSECURITY_DESCRIPTOR pSecurityDescriptor, |
| 1956 | LPDWORD lpcbSecurityDescriptor ) |
| 1957 | { |
Michael Stefaniuc | cbacde5 | 2002-10-25 19:17:33 +0000 | [diff] [blame] | 1958 | TRACE("(%p,%ld,%p,%ld)\n",hkey,SecurityInformation,pSecurityDescriptor, |
Alexandre Julliard | 5ce2329 | 2000-11-30 20:31:41 +0000 | [diff] [blame] | 1959 | lpcbSecurityDescriptor?*lpcbSecurityDescriptor:0); |
| 1960 | |
| 1961 | /* FIXME: Check for valid SecurityInformation values */ |
| 1962 | |
| 1963 | if (*lpcbSecurityDescriptor < sizeof(SECURITY_DESCRIPTOR)) |
| 1964 | return ERROR_INSUFFICIENT_BUFFER; |
| 1965 | |
Michael Stefaniuc | cbacde5 | 2002-10-25 19:17:33 +0000 | [diff] [blame] | 1966 | FIXME("(%p,%ld,%p,%ld): stub\n",hkey,SecurityInformation, |
Alexandre Julliard | 5ce2329 | 2000-11-30 20:31:41 +0000 | [diff] [blame] | 1967 | pSecurityDescriptor,lpcbSecurityDescriptor?*lpcbSecurityDescriptor:0); |
| 1968 | |
Dmitry Timoshkov | 79313d3 | 2002-04-02 02:41:27 +0000 | [diff] [blame] | 1969 | /* Do not leave security descriptor filled with garbage */ |
| 1970 | RtlCreateSecurityDescriptor(pSecurityDescriptor, SECURITY_DESCRIPTOR_REVISION); |
| 1971 | |
Alexandre Julliard | 5ce2329 | 2000-11-30 20:31:41 +0000 | [diff] [blame] | 1972 | return ERROR_SUCCESS; |
| 1973 | } |
| 1974 | |
| 1975 | |
| 1976 | /****************************************************************************** |
Patrik Stridvall | d0a4177 | 2001-02-14 23:11:17 +0000 | [diff] [blame] | 1977 | * RegFlushKey [ADVAPI32.@] |
Jon Griffiths | 50ce084 | 2004-04-23 21:32:34 +0000 | [diff] [blame] | 1978 | * |
| 1979 | * Immediately write a registry key to registry. |
Alexandre Julliard | 5ce2329 | 2000-11-30 20:31:41 +0000 | [diff] [blame] | 1980 | * |
| 1981 | * PARAMS |
James Hawkins | 6a358c4 | 2004-07-13 23:33:14 +0000 | [diff] [blame^] | 1982 | * hkey [I] Handle of key to write |
Alexandre Julliard | 5ce2329 | 2000-11-30 20:31:41 +0000 | [diff] [blame] | 1983 | * |
| 1984 | * RETURNS |
James Hawkins | 6a358c4 | 2004-07-13 23:33:14 +0000 | [diff] [blame^] | 1985 | * Success: ERROR_SUCCESS |
| 1986 | * Failure: Error code |
Alexandre Julliard | 5ce2329 | 2000-11-30 20:31:41 +0000 | [diff] [blame] | 1987 | */ |
| 1988 | DWORD WINAPI RegFlushKey( HKEY hkey ) |
| 1989 | { |
Mike Hearn | 43cb03b | 2004-01-03 00:38:30 +0000 | [diff] [blame] | 1990 | hkey = get_special_root_hkey( hkey ); |
| 1991 | if (!hkey) return ERROR_INVALID_HANDLE; |
| 1992 | |
| 1993 | return RtlNtStatusToDosError( NtFlushKey( hkey ) ); |
Alexandre Julliard | 5ce2329 | 2000-11-30 20:31:41 +0000 | [diff] [blame] | 1994 | } |
| 1995 | |
| 1996 | |
| 1997 | /****************************************************************************** |
Patrik Stridvall | d0a4177 | 2001-02-14 23:11:17 +0000 | [diff] [blame] | 1998 | * RegConnectRegistryW [ADVAPI32.@] |
Alexandre Julliard | 5ce2329 | 2000-11-30 20:31:41 +0000 | [diff] [blame] | 1999 | * |
| 2000 | * PARAMS |
James Hawkins | 6a358c4 | 2004-07-13 23:33:14 +0000 | [diff] [blame^] | 2001 | * lpMachineName [I] Address of name of remote computer |
| 2002 | * hHey [I] Predefined registry handle |
| 2003 | * phkResult [I] Address of buffer for remote registry handle |
| 2004 | * |
| 2005 | * RETURNS |
| 2006 | * Success: ERROR_SUCCESS |
| 2007 | * Failure: nonzero error code from Winerror.h |
Alexandre Julliard | 5ce2329 | 2000-11-30 20:31:41 +0000 | [diff] [blame] | 2008 | */ |
Vincent Béron | 9a62491 | 2002-05-31 23:06:46 +0000 | [diff] [blame] | 2009 | LONG WINAPI RegConnectRegistryW( LPCWSTR lpMachineName, HKEY hKey, |
Alexandre Julliard | 5cf56a3 | 2002-10-03 19:46:27 +0000 | [diff] [blame] | 2010 | PHKEY phkResult ) |
Alexandre Julliard | 5ce2329 | 2000-11-30 20:31:41 +0000 | [diff] [blame] | 2011 | { |
Juan Lang | ae176d1 | 2004-03-18 01:34:23 +0000 | [diff] [blame] | 2012 | LONG ret; |
| 2013 | |
Michael Stefaniuc | cbacde5 | 2002-10-25 19:17:33 +0000 | [diff] [blame] | 2014 | TRACE("(%s,%p,%p): stub\n",debugstr_w(lpMachineName),hKey,phkResult); |
Alexandre Julliard | 5ce2329 | 2000-11-30 20:31:41 +0000 | [diff] [blame] | 2015 | |
| 2016 | if (!lpMachineName || !*lpMachineName) { |
| 2017 | /* Use the local machine name */ |
Juan Lang | ae176d1 | 2004-03-18 01:34:23 +0000 | [diff] [blame] | 2018 | ret = RegOpenKeyW( hKey, NULL, phkResult ); |
Alexandre Julliard | 5ce2329 | 2000-11-30 20:31:41 +0000 | [diff] [blame] | 2019 | } |
Juan Lang | ae176d1 | 2004-03-18 01:34:23 +0000 | [diff] [blame] | 2020 | else if (lpMachineName[0] != '\\' || lpMachineName[1] != '\\') |
| 2021 | ret = ERROR_BAD_NETPATH; |
| 2022 | else |
| 2023 | { |
| 2024 | WCHAR compName[MAX_COMPUTERNAME_LENGTH + 1]; |
| 2025 | DWORD len = sizeof(compName) / sizeof(WCHAR); |
Alexandre Julliard | 5ce2329 | 2000-11-30 20:31:41 +0000 | [diff] [blame] | 2026 | |
Juan Lang | ae176d1 | 2004-03-18 01:34:23 +0000 | [diff] [blame] | 2027 | if (GetComputerNameW(compName, &len)) |
| 2028 | { |
| 2029 | if (!strcmpiW(lpMachineName + 2, compName)) |
| 2030 | ret = RegOpenKeyW(hKey, NULL, phkResult); |
| 2031 | else |
| 2032 | { |
| 2033 | FIXME("Cannot connect to %s\n",debugstr_w(lpMachineName)); |
| 2034 | ret = ERROR_BAD_NETPATH; |
| 2035 | } |
| 2036 | } |
| 2037 | else |
| 2038 | ret = GetLastError(); |
| 2039 | } |
| 2040 | return ret; |
Alexandre Julliard | 5ce2329 | 2000-11-30 20:31:41 +0000 | [diff] [blame] | 2041 | } |
| 2042 | |
| 2043 | |
| 2044 | /****************************************************************************** |
Patrik Stridvall | d0a4177 | 2001-02-14 23:11:17 +0000 | [diff] [blame] | 2045 | * RegConnectRegistryA [ADVAPI32.@] |
James Hawkins | 6a358c4 | 2004-07-13 23:33:14 +0000 | [diff] [blame^] | 2046 | * |
| 2047 | * see RegConnectRegistryW |
Alexandre Julliard | 5ce2329 | 2000-11-30 20:31:41 +0000 | [diff] [blame] | 2048 | */ |
Alexandre Julliard | 5cf56a3 | 2002-10-03 19:46:27 +0000 | [diff] [blame] | 2049 | LONG WINAPI RegConnectRegistryA( LPCSTR machine, HKEY hkey, PHKEY reskey ) |
Alexandre Julliard | 5ce2329 | 2000-11-30 20:31:41 +0000 | [diff] [blame] | 2050 | { |
Matthew Davison | 6f2a071 | 2003-01-20 23:23:12 +0000 | [diff] [blame] | 2051 | UNICODE_STRING machineW; |
| 2052 | LONG ret; |
| 2053 | |
| 2054 | RtlCreateUnicodeStringFromAsciiz( &machineW, machine ); |
| 2055 | ret = RegConnectRegistryW( machineW.Buffer, hkey, reskey ); |
| 2056 | RtlFreeUnicodeString( &machineW ); |
Alexandre Julliard | 5ce2329 | 2000-11-30 20:31:41 +0000 | [diff] [blame] | 2057 | return ret; |
| 2058 | } |
| 2059 | |
| 2060 | |
| 2061 | /****************************************************************************** |
Patrik Stridvall | d0a4177 | 2001-02-14 23:11:17 +0000 | [diff] [blame] | 2062 | * RegNotifyChangeKeyValue [ADVAPI32.@] |
Alexandre Julliard | 5ce2329 | 2000-11-30 20:31:41 +0000 | [diff] [blame] | 2063 | * |
| 2064 | * PARAMS |
James Hawkins | 6a358c4 | 2004-07-13 23:33:14 +0000 | [diff] [blame^] | 2065 | * hkey [I] Handle of key to watch |
| 2066 | * fWatchSubTree [I] Flag for subkey notification |
| 2067 | * fdwNotifyFilter [I] Changes to be reported |
| 2068 | * hEvent [I] Handle of signaled event |
| 2069 | * fAsync [I] Flag for asynchronous reporting |
| 2070 | * |
| 2071 | * RETURNS |
| 2072 | * Success: ERROR_SUCCESS |
| 2073 | * Failure: nonzero error code from Winerror.h |
Alexandre Julliard | 5ce2329 | 2000-11-30 20:31:41 +0000 | [diff] [blame] | 2074 | */ |
Vincent Béron | 9a62491 | 2002-05-31 23:06:46 +0000 | [diff] [blame] | 2075 | LONG WINAPI RegNotifyChangeKeyValue( HKEY hkey, BOOL fWatchSubTree, |
Alexandre Julliard | 5ce2329 | 2000-11-30 20:31:41 +0000 | [diff] [blame] | 2076 | DWORD fdwNotifyFilter, HANDLE hEvent, |
| 2077 | BOOL fAsync ) |
| 2078 | { |
Mike McCormack | 11f4b44 | 2002-11-25 02:47:32 +0000 | [diff] [blame] | 2079 | LONG ret; |
| 2080 | |
| 2081 | TRACE("(%p,%i,%ld,%p,%i)\n",hkey,fWatchSubTree,fdwNotifyFilter, |
Alexandre Julliard | 5ce2329 | 2000-11-30 20:31:41 +0000 | [diff] [blame] | 2082 | hEvent,fAsync); |
Mike McCormack | 11f4b44 | 2002-11-25 02:47:32 +0000 | [diff] [blame] | 2083 | |
| 2084 | if( !fAsync ) |
| 2085 | hEvent = CreateEventA(NULL, 0, 0, NULL); |
| 2086 | |
| 2087 | SERVER_START_REQ( set_registry_notification ) |
| 2088 | { |
| 2089 | req->hkey = hkey; |
| 2090 | req->event = hEvent; |
| 2091 | req->subtree = fWatchSubTree; |
| 2092 | req->filter = fdwNotifyFilter; |
| 2093 | ret = RtlNtStatusToDosError( wine_server_call(req) ); |
| 2094 | } |
| 2095 | SERVER_END_REQ; |
| 2096 | |
| 2097 | if( !fAsync ) |
| 2098 | { |
| 2099 | if( ret == ERROR_SUCCESS ) |
| 2100 | WaitForSingleObject( hEvent, INFINITE ); |
| 2101 | CloseHandle( hEvent ); |
| 2102 | } |
| 2103 | |
| 2104 | return ret; |
Alexandre Julliard | 5ce2329 | 2000-11-30 20:31:41 +0000 | [diff] [blame] | 2105 | } |
Robert Shearman | 65e8182 | 2004-01-16 04:40:33 +0000 | [diff] [blame] | 2106 | |
| 2107 | /****************************************************************************** |
| 2108 | * RegOpenUserClassesRoot [ADVAPI32.@] |
Jon Griffiths | 50ce084 | 2004-04-23 21:32:34 +0000 | [diff] [blame] | 2109 | * |
| 2110 | * Open the HKEY_CLASSES_ROOT key for a user. |
Robert Shearman | 65e8182 | 2004-01-16 04:40:33 +0000 | [diff] [blame] | 2111 | * |
| 2112 | * PARAMS |
James Hawkins | 6a358c4 | 2004-07-13 23:33:14 +0000 | [diff] [blame^] | 2113 | * hToken [I] Handle of token representing the user |
| 2114 | * dwOptions [I] Reserved, nust be 0 |
| 2115 | * samDesired [I] Desired access rights |
| 2116 | * phkResult [O] Destination for the resulting key handle |
Robert Shearman | 65e8182 | 2004-01-16 04:40:33 +0000 | [diff] [blame] | 2117 | * |
James Hawkins | 6a358c4 | 2004-07-13 23:33:14 +0000 | [diff] [blame^] | 2118 | * RETURNS |
| 2119 | * Success: ERROR_SUCCESS |
| 2120 | * Failure: nonzero error code from Winerror.h |
| 2121 | * |
Jon Griffiths | 50ce084 | 2004-04-23 21:32:34 +0000 | [diff] [blame] | 2122 | * NOTES |
James Hawkins | 6a358c4 | 2004-07-13 23:33:14 +0000 | [diff] [blame^] | 2123 | * On Windows 2000 and upwards the HKEY_CLASSES_ROOT key is a view of the |
| 2124 | * "HKEY_LOCAL_MACHINE\Software\Classes" and the |
| 2125 | * "HKEY_CURRENT_USER\Software\Classes" keys merged together. |
Robert Shearman | 65e8182 | 2004-01-16 04:40:33 +0000 | [diff] [blame] | 2126 | */ |
| 2127 | LONG WINAPI RegOpenUserClassesRoot( |
| 2128 | HANDLE hToken, |
| 2129 | DWORD dwOptions, |
| 2130 | REGSAM samDesired, |
| 2131 | PHKEY phkResult |
| 2132 | ) |
| 2133 | { |
| 2134 | FIXME("(%p, 0x%lx, 0x%lx, %p) semi-stub\n", hToken, dwOptions, samDesired, phkResult); |
| 2135 | |
| 2136 | *phkResult = HKEY_CLASSES_ROOT; |
| 2137 | return ERROR_SUCCESS; |
| 2138 | } |