1 /* 2 * Unit tests for registry functions 3 * 4 * Copyright (c) 2002 Alexandre Julliard 5 * Copyright (c) 2010 André Hentschel 6 * 7 * This library is free software; you can redistribute it and/or 8 * modify it under the terms of the GNU Lesser General Public 9 * License as published by the Free Software Foundation; either 10 * version 2.1 of the License, or (at your option) any later version. 11 * 12 * This library is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 * Lesser General Public License for more details. 16 * 17 * You should have received a copy of the GNU Lesser General Public 18 * License along with this library; if not, write to the Free Software 19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 20 */ 21 22 #include "precomp.h" 23 24 #include <assert.h> 25 #include <winperf.h> 26 27 #define IS_HKCR(hk) ((UINT_PTR)hk > 0 && ((UINT_PTR)hk & 3) == 2) 28 29 static HKEY hkey_main; 30 static DWORD GLE; 31 32 static const char * sTestpath1 = "%LONGSYSTEMVAR%\\subdir1"; 33 static const char * sTestpath2 = "%FOO%\\subdir1"; 34 static const DWORD ptr_size = 8 * sizeof(void*); 35 36 static DWORD (WINAPI *pRegGetValueA)(HKEY,LPCSTR,LPCSTR,DWORD,LPDWORD,PVOID,LPDWORD); 37 static LONG (WINAPI *pRegCopyTreeA)(HKEY,const char *,HKEY); 38 static LONG (WINAPI *pRegDeleteTreeA)(HKEY,const char *); 39 static DWORD (WINAPI *pRegDeleteKeyExA)(HKEY,LPCSTR,REGSAM,DWORD); 40 static BOOL (WINAPI *pIsWow64Process)(HANDLE,PBOOL); 41 static NTSTATUS (WINAPI * pNtDeleteKey)(HANDLE); 42 static NTSTATUS (WINAPI * pRtlFormatCurrentUserKeyPath)(UNICODE_STRING*); 43 static NTSTATUS (WINAPI * pRtlFreeUnicodeString)(PUNICODE_STRING); 44 static LONG (WINAPI *pRegDeleteKeyValueA)(HKEY,LPCSTR,LPCSTR); 45 static LONG (WINAPI *pRegSetKeyValueW)(HKEY,LPCWSTR,LPCWSTR,DWORD,const void*,DWORD); 46 47 static BOOL limited_user; 48 49 50 /* Debugging functions from wine/libs/wine/debug.c */ 51 52 /* allocate some tmp string space */ 53 /* FIXME: this is not 100% thread-safe */ 54 static char *get_temp_buffer( int size ) 55 { 56 static char *list[32]; 57 static UINT pos; 58 char *ret; 59 UINT idx; 60 61 idx = ++pos % (sizeof(list)/sizeof(list[0])); 62 if (list[idx]) 63 ret = HeapReAlloc( GetProcessHeap(), 0, list[idx], size ); 64 else 65 ret = HeapAlloc( GetProcessHeap(), 0, size ); 66 if (ret) list[idx] = ret; 67 return ret; 68 } 69 70 static const char *wine_debugstr_an( const char *str, int n ) 71 { 72 static const char hex[16] = "0123456789abcdef"; 73 char *dst, *res; 74 size_t size; 75 76 if (!((ULONG_PTR)str >> 16)) 77 { 78 if (!str) return "(null)"; 79 res = get_temp_buffer( 6 ); 80 sprintf( res, "#%04x", LOWORD(str) ); 81 return res; 82 } 83 if (n == -1) n = strlen(str); 84 if (n < 0) n = 0; 85 size = 10 + min( 300, n * 4 ); 86 dst = res = get_temp_buffer( size ); 87 *dst++ = '"'; 88 while (n-- > 0 && dst <= res + size - 9) 89 { 90 unsigned char c = *str++; 91 switch (c) 92 { 93 case '\n': *dst++ = '\\'; *dst++ = 'n'; break; 94 case '\r': *dst++ = '\\'; *dst++ = 'r'; break; 95 case '\t': *dst++ = '\\'; *dst++ = 't'; break; 96 case '"': *dst++ = '\\'; *dst++ = '"'; break; 97 case '\\': *dst++ = '\\'; *dst++ = '\\'; break; 98 default: 99 if (c >= ' ' && c <= 126) 100 *dst++ = c; 101 else 102 { 103 *dst++ = '\\'; 104 *dst++ = 'x'; 105 *dst++ = hex[(c >> 4) & 0x0f]; 106 *dst++ = hex[c & 0x0f]; 107 } 108 } 109 } 110 *dst++ = '"'; 111 if (n > 0) 112 { 113 *dst++ = '.'; 114 *dst++ = '.'; 115 *dst++ = '.'; 116 } 117 *dst++ = 0; 118 return res; 119 } 120 121 #define ADVAPI32_GET_PROC(func) \ 122 p ## func = (void*)GetProcAddress(hadvapi32, #func) 123 124 static void InitFunctionPtrs(void) 125 { 126 HMODULE hntdll = GetModuleHandleA("ntdll.dll"); 127 HMODULE hkernel32 = GetModuleHandleA("kernel32.dll"); 128 HMODULE hadvapi32 = GetModuleHandleA("advapi32.dll"); 129 130 /* This function was introduced with Windows 2003 SP1 */ 131 ADVAPI32_GET_PROC(RegGetValueA); 132 ADVAPI32_GET_PROC(RegCopyTreeA); 133 ADVAPI32_GET_PROC(RegDeleteTreeA); 134 ADVAPI32_GET_PROC(RegDeleteKeyExA); 135 ADVAPI32_GET_PROC(RegDeleteKeyValueA); 136 ADVAPI32_GET_PROC(RegSetKeyValueW); 137 138 pIsWow64Process = (void *)GetProcAddress( hkernel32, "IsWow64Process" ); 139 pRtlFormatCurrentUserKeyPath = (void *)GetProcAddress( hntdll, "RtlFormatCurrentUserKeyPath" ); 140 pRtlFreeUnicodeString = (void *)GetProcAddress(hntdll, "RtlFreeUnicodeString"); 141 pNtDeleteKey = (void *)GetProcAddress( hntdll, "NtDeleteKey" ); 142 } 143 144 /* delete key and all its subkeys */ 145 static DWORD delete_key( HKEY hkey ) 146 { 147 char name[MAX_PATH]; 148 DWORD ret; 149 150 if ((ret = RegOpenKeyExA( hkey, "", 0, KEY_ENUMERATE_SUB_KEYS, &hkey ))) return ret; 151 while (!(ret = RegEnumKeyA(hkey, 0, name, sizeof(name)))) 152 { 153 HKEY tmp; 154 if (!(ret = RegOpenKeyExA( hkey, name, 0, KEY_ENUMERATE_SUB_KEYS, &tmp ))) 155 { 156 ret = delete_key( tmp ); 157 RegCloseKey( tmp ); 158 } 159 if (ret) break; 160 } 161 if (ret != ERROR_NO_MORE_ITEMS) return ret; 162 RegDeleteKeyA( hkey, "" ); 163 RegCloseKey(hkey); 164 return 0; 165 } 166 167 static void setup_main_key(void) 168 { 169 if (!RegOpenKeyA( HKEY_CURRENT_USER, "Software\\Wine\\Test", &hkey_main )) delete_key( hkey_main ); 170 171 assert (!RegCreateKeyA( HKEY_CURRENT_USER, "Software\\Wine\\Test", &hkey_main )); 172 } 173 174 static void check_user_privs(void) 175 { 176 DWORD ret; 177 HKEY hkey = (HKEY)0xdeadbeef; 178 179 ret = RegOpenKeyExA( HKEY_LOCAL_MACHINE, "Software", 0, KEY_READ|KEY_WRITE, &hkey); 180 ok(ret == ERROR_SUCCESS || ret == ERROR_ACCESS_DENIED, "expected success or access denied, got %i\n", ret); 181 if (ret == ERROR_SUCCESS) 182 { 183 ok(hkey != NULL, "RegOpenKeyExA succeeded but returned NULL hkey\n"); 184 RegCloseKey(hkey); 185 } 186 else 187 { 188 ok(hkey == NULL, "RegOpenKeyExA failed but returned hkey %p\n", hkey); 189 limited_user = TRUE; 190 trace("running as limited user\n"); 191 } 192 } 193 194 #define lok ok_(__FILE__, line) 195 #define test_hkey_main_Value_A(name, string, full_byte_len) _test_hkey_main_Value_A(__LINE__, name, string, full_byte_len) 196 static void _test_hkey_main_Value_A(int line, LPCSTR name, LPCSTR string, 197 DWORD full_byte_len) 198 { 199 DWORD ret, type, cbData; 200 DWORD str_byte_len; 201 BYTE* value; 202 203 type=0xdeadbeef; 204 cbData=0xdeadbeef; 205 /* When successful RegQueryValueExA() leaves GLE as is, 206 * so we must reset it to detect unimplemented functions. 207 */ 208 SetLastError(0xdeadbeef); 209 ret = RegQueryValueExA(hkey_main, name, NULL, &type, NULL, &cbData); 210 GLE = GetLastError(); 211 lok(ret == ERROR_SUCCESS, "RegQueryValueExA/1 failed: %d, GLE=%d\n", ret, GLE); 212 /* It is wrong for the Ansi version to not be implemented */ 213 ok(GLE == 0xdeadbeef, "RegQueryValueExA set GLE = %u\n", GLE); 214 if(GLE == ERROR_CALL_NOT_IMPLEMENTED) return; 215 216 str_byte_len = (string ? lstrlenA(string) : 0) + 1; 217 lok(type == REG_SZ, "RegQueryValueExA/1 returned type %d\n", type); 218 lok(cbData == full_byte_len, "cbData=%d instead of %d or %d\n", cbData, full_byte_len, str_byte_len); 219 220 value = HeapAlloc(GetProcessHeap(), 0, cbData+1); 221 memset(value, 0xbd, cbData+1); 222 type=0xdeadbeef; 223 ret = RegQueryValueExA(hkey_main, name, NULL, &type, value, &cbData); 224 GLE = GetLastError(); 225 lok(ret == ERROR_SUCCESS, "RegQueryValueExA/2 failed: %d, GLE=%d\n", ret, GLE); 226 if (!string) 227 { 228 /* When cbData == 0, RegQueryValueExA() should not modify the buffer */ 229 lok(*value == 0xbd, "RegQueryValueExA overflowed: cbData=%u *value=%02x\n", cbData, *value); 230 } 231 else 232 { 233 lok(memcmp(value, string, cbData) == 0, "RegQueryValueExA/2 failed: %s/%d != %s/%d\n", 234 wine_debugstr_an((char*)value, cbData), cbData, 235 wine_debugstr_an(string, full_byte_len), full_byte_len); 236 lok(*(value+cbData) == 0xbd, "RegQueryValueExA/2 overflowed at offset %u: %02x != bd\n", cbData, *(value+cbData)); 237 } 238 HeapFree(GetProcessHeap(), 0, value); 239 } 240 241 #define test_hkey_main_Value_W(name, string, full_byte_len) _test_hkey_main_Value_W(__LINE__, name, string, full_byte_len) 242 static void _test_hkey_main_Value_W(int line, LPCWSTR name, LPCWSTR string, 243 DWORD full_byte_len) 244 { 245 DWORD ret, type, cbData; 246 BYTE* value; 247 248 type=0xdeadbeef; 249 cbData=0xdeadbeef; 250 /* When successful RegQueryValueExW() leaves GLE as is, 251 * so we must reset it to detect unimplemented functions. 252 */ 253 SetLastError(0xdeadbeef); 254 ret = RegQueryValueExW(hkey_main, name, NULL, &type, NULL, &cbData); 255 GLE = GetLastError(); 256 lok(ret == ERROR_SUCCESS, "RegQueryValueExW/1 failed: %d, GLE=%d\n", ret, GLE); 257 if(GLE == ERROR_CALL_NOT_IMPLEMENTED) 258 { 259 win_skip("RegQueryValueExW() is not implemented\n"); 260 return; 261 } 262 263 lok(type == REG_SZ, "RegQueryValueExW/1 returned type %d\n", type); 264 lok(cbData == full_byte_len, 265 "cbData=%d instead of %d\n", cbData, full_byte_len); 266 267 /* Give enough space to overflow by one WCHAR */ 268 value = HeapAlloc(GetProcessHeap(), 0, cbData+2); 269 memset(value, 0xbd, cbData+2); 270 type=0xdeadbeef; 271 ret = RegQueryValueExW(hkey_main, name, NULL, &type, value, &cbData); 272 GLE = GetLastError(); 273 lok(ret == ERROR_SUCCESS, "RegQueryValueExW/2 failed: %d, GLE=%d\n", ret, GLE); 274 if (string) 275 { 276 lok(memcmp(value, string, cbData) == 0, "RegQueryValueExW failed: %s/%d != %s/%d\n", 277 wine_dbgstr_wn((WCHAR*)value, cbData / sizeof(WCHAR)), cbData, 278 wine_dbgstr_wn(string, full_byte_len / sizeof(WCHAR)), full_byte_len); 279 } 280 /* This implies that when cbData == 0, RegQueryValueExW() should not modify the buffer */ 281 lok(*(value+cbData) == 0xbd, "RegQueryValueExW/2 overflowed at %u: %02x != bd\n", cbData, *(value+cbData)); 282 lok(*(value+cbData+1) == 0xbd, "RegQueryValueExW/2 overflowed at %u+1: %02x != bd\n", cbData, *(value+cbData+1)); 283 HeapFree(GetProcessHeap(), 0, value); 284 } 285 286 static void test_set_value(void) 287 { 288 DWORD ret; 289 290 static const WCHAR name1W[] = {'C','l','e','a','n','S','i','n','g','l','e','S','t','r','i','n','g', 0}; 291 static const WCHAR name2W[] = {'S','o','m','e','I','n','t','r','a','Z','e','r','o','e','d','S','t','r','i','n','g', 0}; 292 static const WCHAR emptyW[] = {0}; 293 static const WCHAR string1W[] = {'T','h','i','s','N','e','v','e','r','B','r','e','a','k','s', 0}; 294 static const WCHAR string2W[] = {'T','h','i','s', 0 ,'B','r','e','a','k','s', 0 , 0 ,'A', 0 , 0 , 0 , 'L','o','t', 0 , 0 , 0 , 0, 0}; 295 static const WCHAR substring2W[] = {'T','h','i','s',0}; 296 297 static const char name1A[] = "CleanSingleString"; 298 static const char name2A[] = "SomeIntraZeroedString"; 299 static const char emptyA[] = ""; 300 static const char string1A[] = "ThisNeverBreaks"; 301 static const char string2A[] = "This\0Breaks\0\0A\0\0\0Lot\0\0\0\0"; 302 static const char substring2A[] = "This"; 303 304 if (0) 305 { 306 /* Crashes on NT4, Windows 2000 and XP SP1 */ 307 ret = RegSetValueA(hkey_main, NULL, REG_SZ, NULL, 0); 308 ok(ret == ERROR_INVALID_PARAMETER, "RegSetValueA should have failed with ERROR_INVALID_PARAMETER instead of %d\n", ret); 309 } 310 311 ret = RegSetValueA(hkey_main, NULL, REG_SZ, string1A, sizeof(string1A)); 312 ok(ret == ERROR_SUCCESS, "RegSetValueA failed: %d, GLE=%d\n", ret, GetLastError()); 313 test_hkey_main_Value_A(NULL, string1A, sizeof(string1A)); 314 test_hkey_main_Value_W(NULL, string1W, sizeof(string1W)); 315 316 /* RegSetValueA ignores the size passed in */ 317 ret = RegSetValueA(hkey_main, NULL, REG_SZ, string1A, 4); 318 ok(ret == ERROR_SUCCESS, "RegSetValueA failed: %d, GLE=%d\n", ret, GetLastError()); 319 test_hkey_main_Value_A(NULL, string1A, sizeof(string1A)); 320 test_hkey_main_Value_W(NULL, string1W, sizeof(string1W)); 321 322 /* stops at first null */ 323 ret = RegSetValueA(hkey_main, NULL, REG_SZ, string2A, sizeof(string2A)); 324 ok(ret == ERROR_SUCCESS, "RegSetValueA failed: %d, GLE=%d\n", ret, GetLastError()); 325 test_hkey_main_Value_A(NULL, substring2A, sizeof(substring2A)); 326 test_hkey_main_Value_W(NULL, substring2W, sizeof(substring2W)); 327 328 /* only REG_SZ is supported on NT*/ 329 ret = RegSetValueA(hkey_main, NULL, REG_BINARY, string2A, sizeof(string2A)); 330 ok(ret == ERROR_INVALID_PARAMETER, "got %d (expected ERROR_INVALID_PARAMETER)\n", ret); 331 332 ret = RegSetValueA(hkey_main, NULL, REG_EXPAND_SZ, string2A, sizeof(string2A)); 333 ok(ret == ERROR_INVALID_PARAMETER, "got %d (expected ERROR_INVALID_PARAMETER)\n", ret); 334 335 ret = RegSetValueA(hkey_main, NULL, REG_MULTI_SZ, string2A, sizeof(string2A)); 336 ok(ret == ERROR_INVALID_PARAMETER, "got %d (expected ERROR_INVALID_PARAMETER)\n", ret); 337 338 /* Test RegSetValueExA with a 'zero-byte' string (as Office 2003 does). 339 * Surprisingly enough we're supposed to get zero bytes out of it. 340 */ 341 ret = RegSetValueExA(hkey_main, name1A, 0, REG_SZ, (const BYTE *)emptyA, 0); 342 ok(ret == ERROR_SUCCESS, "RegSetValueExA failed: %d, GLE=%d\n", ret, GetLastError()); 343 test_hkey_main_Value_A(name1A, NULL, 0); 344 test_hkey_main_Value_W(name1W, NULL, 0); 345 346 /* test RegSetValueExA with an empty string */ 347 ret = RegSetValueExA(hkey_main, name1A, 0, REG_SZ, (const BYTE *)emptyA, sizeof(emptyA)); 348 ok(ret == ERROR_SUCCESS, "RegSetValueExA failed: %d, GLE=%d\n", ret, GetLastError()); 349 test_hkey_main_Value_A(name1A, emptyA, sizeof(emptyA)); 350 test_hkey_main_Value_W(name1W, emptyW, sizeof(emptyW)); 351 352 /* test RegSetValueExA with off-by-one size */ 353 ret = RegSetValueExA(hkey_main, name1A, 0, REG_SZ, (const BYTE *)string1A, sizeof(string1A)-sizeof(string1A[0])); 354 ok(ret == ERROR_SUCCESS, "RegSetValueExA failed: %d, GLE=%d\n", ret, GetLastError()); 355 test_hkey_main_Value_A(name1A, string1A, sizeof(string1A)); 356 test_hkey_main_Value_W(name1W, string1W, sizeof(string1W)); 357 358 /* test RegSetValueExA with normal string */ 359 ret = RegSetValueExA(hkey_main, name1A, 0, REG_SZ, (const BYTE *)string1A, sizeof(string1A)); 360 ok(ret == ERROR_SUCCESS, "RegSetValueExA failed: %d, GLE=%d\n", ret, GetLastError()); 361 test_hkey_main_Value_A(name1A, string1A, sizeof(string1A)); 362 test_hkey_main_Value_W(name1W, string1W, sizeof(string1W)); 363 364 /* test RegSetValueExA with intrazeroed string */ 365 ret = RegSetValueExA(hkey_main, name2A, 0, REG_SZ, (const BYTE *)string2A, sizeof(string2A)); 366 ok(ret == ERROR_SUCCESS, "RegSetValueExA failed: %d, GLE=%d\n", ret, GetLastError()); 367 test_hkey_main_Value_A(name2A, string2A, sizeof(string2A)); 368 test_hkey_main_Value_W(name2W, string2W, sizeof(string2W)); 369 370 if (0) 371 { 372 /* Crashes on NT4, Windows 2000 and XP SP1 */ 373 ret = RegSetValueW(hkey_main, NULL, REG_SZ, NULL, 0); 374 ok(ret == ERROR_INVALID_PARAMETER, "RegSetValueW should have failed with ERROR_INVALID_PARAMETER instead of %d\n", ret); 375 376 RegSetValueExA(hkey_main, name2A, 0, REG_SZ, (const BYTE *)1, 1); 377 RegSetValueExA(hkey_main, name2A, 0, REG_DWORD, (const BYTE *)1, 1); 378 } 379 380 ret = RegSetValueW(hkey_main, NULL, REG_SZ, string1W, sizeof(string1W)); 381 ok(ret == ERROR_SUCCESS, "RegSetValueW failed: %d, GLE=%d\n", ret, GetLastError()); 382 test_hkey_main_Value_A(NULL, string1A, sizeof(string1A)); 383 test_hkey_main_Value_W(NULL, string1W, sizeof(string1W)); 384 385 ret = RegSetValueW(hkey_main, name1W, REG_SZ, string1W, sizeof(string1W)); 386 ok(ret == ERROR_SUCCESS, "RegSetValueW failed: %d, GLE=%d\n", ret, GetLastError()); 387 test_hkey_main_Value_A(name1A, string1A, sizeof(string1A)); 388 test_hkey_main_Value_W(name1W, string1W, sizeof(string1W)); 389 390 /* RegSetValueW ignores the size passed in */ 391 ret = RegSetValueW(hkey_main, NULL, REG_SZ, string1W, 4 * sizeof(string1W[0])); 392 ok(ret == ERROR_SUCCESS, "RegSetValueW failed: %d, GLE=%d\n", ret, GetLastError()); 393 test_hkey_main_Value_A(NULL, string1A, sizeof(string1A)); 394 test_hkey_main_Value_W(NULL, string1W, sizeof(string1W)); 395 396 /* stops at first null */ 397 ret = RegSetValueW(hkey_main, NULL, REG_SZ, string2W, sizeof(string2W)); 398 ok(ret == ERROR_SUCCESS, "RegSetValueW failed: %d, GLE=%d\n", ret, GetLastError()); 399 test_hkey_main_Value_A(NULL, substring2A, sizeof(substring2A)); 400 test_hkey_main_Value_W(NULL, substring2W, sizeof(substring2W)); 401 402 /* only REG_SZ is supported */ 403 ret = RegSetValueW(hkey_main, NULL, REG_BINARY, string2W, sizeof(string2W)); 404 ok(ret == ERROR_INVALID_PARAMETER, "RegSetValueW should have returned ERROR_INVALID_PARAMETER instead of %d\n", ret); 405 ret = RegSetValueW(hkey_main, NULL, REG_EXPAND_SZ, string2W, sizeof(string2W)); 406 ok(ret == ERROR_INVALID_PARAMETER, "RegSetValueW should have returned ERROR_INVALID_PARAMETER instead of %d\n", ret); 407 ret = RegSetValueW(hkey_main, NULL, REG_MULTI_SZ, string2W, sizeof(string2W)); 408 ok(ret == ERROR_INVALID_PARAMETER, "RegSetValueW should have returned ERROR_INVALID_PARAMETER instead of %d\n", ret); 409 410 /* test RegSetValueExW with off-by-one size */ 411 ret = RegSetValueExW(hkey_main, name1W, 0, REG_SZ, (const BYTE *)string1W, sizeof(string1W)-sizeof(string1W[0])); 412 ok(ret == ERROR_SUCCESS, "RegSetValueExW failed: %d, GLE=%d\n", ret, GetLastError()); 413 test_hkey_main_Value_A(name1A, string1A, sizeof(string1A)); 414 test_hkey_main_Value_W(name1W, string1W, sizeof(string1W)); 415 416 /* test RegSetValueExW with normal string */ 417 ret = RegSetValueExW(hkey_main, name1W, 0, REG_SZ, (const BYTE *)string1W, sizeof(string1W)); 418 ok(ret == ERROR_SUCCESS, "RegSetValueExW failed: %d, GLE=%d\n", ret, GetLastError()); 419 test_hkey_main_Value_A(name1A, string1A, sizeof(string1A)); 420 test_hkey_main_Value_W(name1W, string1W, sizeof(string1W)); 421 422 /* test RegSetValueExW with intrazeroed string */ 423 ret = RegSetValueExW(hkey_main, name2W, 0, REG_SZ, (const BYTE *)string2W, sizeof(string2W)); 424 ok(ret == ERROR_SUCCESS, "RegSetValueExW failed: %d, GLE=%d\n", ret, GetLastError()); 425 test_hkey_main_Value_A(name2A, string2A, sizeof(string2A)); 426 test_hkey_main_Value_W(name2W, string2W, sizeof(string2W)); 427 428 /* test RegSetValueExW with data = 1 */ 429 ret = RegSetValueExW(hkey_main, name2W, 0, REG_SZ, (const BYTE *)1, 1); 430 ok(ret == ERROR_NOACCESS, "RegSetValueExW should have failed with ERROR_NOACCESS: %d, GLE=%d\n", ret, GetLastError()); 431 ret = RegSetValueExW(hkey_main, name2W, 0, REG_DWORD, (const BYTE *)1, 1); 432 ok(ret == ERROR_NOACCESS, "RegSetValueExW should have failed with ERROR_NOACCESS: %d, GLE=%d\n", ret, GetLastError()); 433 434 if (pRegGetValueA) /* avoid a crash on Windows 2000 */ 435 { 436 ret = RegSetValueExW(hkey_main, NULL, 0, REG_SZ, NULL, 4); 437 ok(ret == ERROR_NOACCESS, "RegSetValueExW should have failed with ERROR_NOACCESS: %d, GLE=%d\n", ret, GetLastError()); 438 439 ret = RegSetValueExW(hkey_main, NULL, 0, REG_SZ, NULL, 0); 440 ok(ret == ERROR_SUCCESS, "got %d\n", ret); 441 442 ret = RegSetValueExW(hkey_main, NULL, 0, REG_DWORD, NULL, 4); 443 ok(ret == ERROR_NOACCESS, "RegSetValueExW should have failed with ERROR_NOACCESS: %d, GLE=%d\n", ret, GetLastError()); 444 445 ret = RegSetValueExW(hkey_main, NULL, 0, REG_DWORD, NULL, 0); 446 ok(ret == ERROR_SUCCESS, "got %d\n", ret); 447 } 448 449 /* RegSetKeyValue */ 450 if (!pRegSetKeyValueW) 451 win_skip("RegSetKeyValue() is not supported.\n"); 452 else 453 { 454 static const WCHAR subkeyW[] = {'s','u','b','k','e','y',0}; 455 DWORD len, type; 456 HKEY subkey; 457 458 ret = pRegSetKeyValueW(hkey_main, NULL, name1W, REG_SZ, (const BYTE*)string2W, sizeof(string2W)); 459 ok(ret == ERROR_SUCCESS, "got %d\n", ret); 460 test_hkey_main_Value_A(name1A, string2A, sizeof(string2A)); 461 test_hkey_main_Value_W(name1W, string2W, sizeof(string2W)); 462 463 ret = pRegSetKeyValueW(hkey_main, subkeyW, name1W, REG_SZ, string1W, sizeof(string1W)); 464 ok(ret == ERROR_SUCCESS, "got %d\n", ret); 465 466 ret = RegOpenKeyExW(hkey_main, subkeyW, 0, KEY_QUERY_VALUE, &subkey); 467 ok(ret == ERROR_SUCCESS, "got %d\n", ret); 468 type = len = 0; 469 ret = RegQueryValueExW(subkey, name1W, 0, &type, NULL, &len); 470 ok(ret == ERROR_SUCCESS, "got %d\n", ret); 471 ok(len == sizeof(string1W), "got %d\n", len); 472 ok(type == REG_SZ, "got type %d\n", type); 473 474 ret = pRegSetKeyValueW(hkey_main, subkeyW, name1W, REG_SZ, NULL, 0); 475 ok(ret == ERROR_SUCCESS, "got %d\n", ret); 476 477 ret = pRegSetKeyValueW(hkey_main, subkeyW, name1W, REG_SZ, NULL, 4); 478 ok(ret == ERROR_NOACCESS, "got %d\n", ret); 479 480 ret = pRegSetKeyValueW(hkey_main, subkeyW, name1W, REG_DWORD, NULL, 4); 481 ok(ret == ERROR_NOACCESS, "got %d\n", ret); 482 483 RegCloseKey(subkey); 484 } 485 } 486 487 static void create_test_entries(void) 488 { 489 static const DWORD qw[2] = { 0x12345678, 0x87654321 }; 490 491 SetEnvironmentVariableA("LONGSYSTEMVAR", "bar"); 492 SetEnvironmentVariableA("FOO", "ImARatherLongButIndeedNeededString"); 493 494 ok(!RegSetValueExA(hkey_main,"TP1_EXP_SZ",0,REG_EXPAND_SZ, (const BYTE *)sTestpath1, strlen(sTestpath1)+1), 495 "RegSetValueExA failed\n"); 496 ok(!RegSetValueExA(hkey_main,"TP1_SZ",0,REG_SZ, (const BYTE *)sTestpath1, strlen(sTestpath1)+1), 497 "RegSetValueExA failed\n"); 498 ok(!RegSetValueExA(hkey_main,"TP1_ZB_SZ",0,REG_SZ, (const BYTE *)"", 0), 499 "RegSetValueExA failed\n"); 500 ok(!RegSetValueExA(hkey_main,"TP2_EXP_SZ",0,REG_EXPAND_SZ, (const BYTE *)sTestpath2, strlen(sTestpath2)+1), 501 "RegSetValueExA failed\n"); 502 ok(!RegSetValueExA(hkey_main,"DWORD",0,REG_DWORD, (const BYTE *)qw, 4), 503 "RegSetValueExA failed\n"); 504 ok(!RegSetValueExA(hkey_main,"BIN32",0,REG_BINARY, (const BYTE *)qw, 4), 505 "RegSetValueExA failed\n"); 506 ok(!RegSetValueExA(hkey_main,"BIN64",0,REG_BINARY, (const BYTE *)qw, 8), 507 "RegSetValueExA failed\n"); 508 } 509 510 static void test_enum_value(void) 511 { 512 DWORD res; 513 HKEY test_key; 514 char value[20], data[20]; 515 WCHAR valueW[20], dataW[20]; 516 DWORD val_count, data_count, type; 517 static const WCHAR foobarW[] = {'f','o','o','b','a','r',0}; 518 static const WCHAR testW[] = {'T','e','s','t',0}; 519 static const WCHAR xxxW[] = {'x','x','x','x','x','x','x','x',0}; 520 521 /* create the working key for new 'Test' value */ 522 res = RegCreateKeyA( hkey_main, "TestKey", &test_key ); 523 ok( res == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %d\n", res); 524 525 /* check NULL data with zero length */ 526 res = RegSetValueExA( test_key, "Test", 0, REG_SZ, NULL, 0 ); 527 if (GetVersion() & 0x80000000) 528 ok( res == ERROR_INVALID_PARAMETER, "RegSetValueExA returned %d\n", res ); 529 else 530 ok( !res, "RegSetValueExA returned %d\n", res ); 531 res = RegSetValueExA( test_key, "Test", 0, REG_EXPAND_SZ, NULL, 0 ); 532 ok( ERROR_SUCCESS == res || ERROR_INVALID_PARAMETER == res, "RegSetValueExA returned %d\n", res ); 533 res = RegSetValueExA( test_key, "Test", 0, REG_BINARY, NULL, 0 ); 534 ok( ERROR_SUCCESS == res || ERROR_INVALID_PARAMETER == res, "RegSetValueExA returned %d\n", res ); 535 536 /* test reading the value and data without setting them */ 537 val_count = 20; 538 data_count = 20; 539 type = 1234; 540 strcpy( value, "xxxxxxxxxx" ); 541 strcpy( data, "xxxxxxxxxx" ); 542 res = RegEnumValueA( test_key, 0, value, &val_count, NULL, &type, (LPBYTE)data, &data_count ); 543 ok( res == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %d\n", res ); 544 ok( val_count == 4, "val_count set to %d instead of 4\n", val_count ); 545 ok( data_count == 0, "data_count set to %d instead of 0\n", data_count ); 546 ok( type == REG_BINARY, "type %d is not REG_BINARY\n", type ); 547 ok( !strcmp( value, "Test" ), "value is '%s' instead of Test\n", value ); 548 ok( !strcmp( data, "xxxxxxxxxx" ), "data is '%s' instead of xxxxxxxxxx\n", data ); 549 550 val_count = 20; 551 data_count = 20; 552 type = 1234; 553 memcpy( valueW, xxxW, sizeof(xxxW) ); 554 memcpy( dataW, xxxW, sizeof(xxxW) ); 555 res = RegEnumValueW( test_key, 0, valueW, &val_count, NULL, &type, (BYTE*)dataW, &data_count ); 556 ok( res == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %d\n", res ); 557 ok( val_count == 4, "val_count set to %d instead of 4\n", val_count ); 558 ok( data_count == 0, "data_count set to %d instead of 0\n", data_count ); 559 ok( type == REG_BINARY, "type %d is not REG_BINARY\n", type ); 560 ok( !memcmp( valueW, testW, sizeof(testW) ), "value is not 'Test'\n" ); 561 ok( !memcmp( dataW, xxxW, sizeof(xxxW) ), "data is not 'xxxxxxxxxx'\n" ); 562 563 res = RegSetValueExA( test_key, "Test", 0, REG_SZ, (const BYTE *)"foobar", 7 ); 564 ok( res == 0, "RegSetValueExA failed error %d\n", res ); 565 566 /* overflow both name and data */ 567 val_count = 2; 568 data_count = 2; 569 type = 1234; 570 strcpy( value, "xxxxxxxxxx" ); 571 strcpy( data, "xxxxxxxxxx" ); 572 res = RegEnumValueA( test_key, 0, value, &val_count, NULL, &type, (LPBYTE)data, &data_count ); 573 ok( res == ERROR_MORE_DATA, "expected ERROR_MORE_DATA, got %d\n", res ); 574 ok( val_count == 2, "val_count set to %d\n", val_count ); 575 ok( data_count == 7 || broken( data_count == 8 ), "data_count set to %d instead of 7\n", data_count ); 576 ok( type == REG_SZ, "type %d is not REG_SZ\n", type ); 577 ok( !strcmp( value, "xxxxxxxxxx" ), "value set to '%s'\n", value ); 578 ok( !strcmp( data, "xxxxxxxxxx" ), "data set to '%s'\n", data ); 579 580 /* overflow name */ 581 val_count = 3; 582 data_count = 20; 583 type = 1234; 584 strcpy( value, "xxxxxxxxxx" ); 585 strcpy( data, "xxxxxxxxxx" ); 586 res = RegEnumValueA( test_key, 0, value, &val_count, NULL, &type, (LPBYTE)data, &data_count ); 587 ok( res == ERROR_MORE_DATA, "expected ERROR_MORE_DATA, got %d\n", res ); 588 ok( val_count == 3, "val_count set to %d\n", val_count ); 589 ok( data_count == 7 || broken( data_count == 8 ), "data_count set to %d instead of 7\n", data_count ); 590 ok( type == REG_SZ, "type %d is not REG_SZ\n", type ); 591 /* v5.1.2600.0 (XP Home and Professional) does not touch value or data in this case */ 592 ok( !strcmp( value, "Te" ) || !strcmp( value, "xxxxxxxxxx" ), 593 "value set to '%s' instead of 'Te' or 'xxxxxxxxxx'\n", value ); 594 ok( !strcmp( data, "foobar" ) || !strcmp( data, "xxxxxxx" ) || broken( !strcmp( data, "xxxxxxxx" ) && data_count == 8 ), 595 "data set to '%s' instead of 'foobar' or 'xxxxxxx'\n", data ); 596 597 /* overflow empty name */ 598 val_count = 0; 599 data_count = 20; 600 type = 1234; 601 strcpy( value, "xxxxxxxxxx" ); 602 strcpy( data, "xxxxxxxxxx" ); 603 res = RegEnumValueA( test_key, 0, value, &val_count, NULL, &type, (LPBYTE)data, &data_count ); 604 ok( res == ERROR_MORE_DATA, "expected ERROR_MORE_DATA, got %d\n", res ); 605 ok( val_count == 0, "val_count set to %d\n", val_count ); 606 ok( data_count == 7 || broken( data_count == 8 ), "data_count set to %d instead of 7\n", data_count ); 607 ok( type == REG_SZ, "type %d is not REG_SZ\n", type ); 608 ok( !strcmp( value, "xxxxxxxxxx" ), "value set to '%s'\n", value ); 609 /* v5.1.2600.0 (XP Home and Professional) does not touch data in this case */ 610 ok( !strcmp( data, "foobar" ) || !strcmp( data, "xxxxxxx" ) || broken( !strcmp( data, "xxxxxxxx" ) && data_count == 8 ), 611 "data set to '%s' instead of 'foobar' or 'xxxxxxx'\n", data ); 612 613 /* overflow data */ 614 val_count = 20; 615 data_count = 2; 616 type = 1234; 617 strcpy( value, "xxxxxxxxxx" ); 618 strcpy( data, "xxxxxxxxxx" ); 619 res = RegEnumValueA( test_key, 0, value, &val_count, NULL, &type, (LPBYTE)data, &data_count ); 620 ok( res == ERROR_MORE_DATA, "expected ERROR_MORE_DATA, got %d\n", res ); 621 ok( val_count == 20, "val_count set to %d\n", val_count ); 622 ok( data_count == 7, "data_count set to %d instead of 7\n", data_count ); 623 ok( type == REG_SZ, "type %d is not REG_SZ\n", type ); 624 ok( !strcmp( value, "xxxxxxxxxx" ), "value set to '%s'\n", value ); 625 ok( !strcmp( data, "xxxxxxxxxx" ), "data set to '%s'\n", data ); 626 627 /* no overflow */ 628 val_count = 20; 629 data_count = 20; 630 type = 1234; 631 strcpy( value, "xxxxxxxxxx" ); 632 strcpy( data, "xxxxxxxxxx" ); 633 res = RegEnumValueA( test_key, 0, value, &val_count, NULL, &type, (LPBYTE)data, &data_count ); 634 ok( res == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %d\n", res ); 635 ok( val_count == 4, "val_count set to %d instead of 4\n", val_count ); 636 ok( data_count == 7, "data_count set to %d instead of 7\n", data_count ); 637 ok( type == REG_SZ, "type %d is not REG_SZ\n", type ); 638 ok( !strcmp( value, "Test" ), "value is '%s' instead of Test\n", value ); 639 ok( !strcmp( data, "foobar" ), "data is '%s' instead of foobar\n", data ); 640 641 if (pRegGetValueA) /* avoid a crash on Windows 2000 */ 642 { 643 /* no value and no val_count parameter */ 644 data_count = 20; 645 type = 1234; 646 strcpy( data, "xxxxxxxxxx" ); 647 res = RegEnumValueA( test_key, 0, NULL, NULL, NULL, &type, (BYTE*)data, &data_count ); 648 ok( res == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %d\n", res ); 649 650 /* no value parameter */ 651 val_count = 20; 652 data_count = 20; 653 type = 1234; 654 strcpy( data, "xxxxxxxxxx" ); 655 res = RegEnumValueA( test_key, 0, NULL, &val_count, NULL, &type, (BYTE*)data, &data_count ); 656 ok( res == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %d\n", res ); 657 658 /* no val_count parameter */ 659 data_count = 20; 660 type = 1234; 661 strcpy( value, "xxxxxxxxxx" ); 662 strcpy( data, "xxxxxxxxxx" ); 663 res = RegEnumValueA( test_key, 0, value, NULL, NULL, &type, (BYTE*)data, &data_count ); 664 ok( res == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %d\n", res ); 665 } 666 667 /* Unicode tests */ 668 669 SetLastError(0xdeadbeef); 670 res = RegSetValueExW( test_key, testW, 0, REG_SZ, (const BYTE *)foobarW, 7*sizeof(WCHAR) ); 671 if (res==0 && GetLastError()==ERROR_CALL_NOT_IMPLEMENTED) 672 { 673 win_skip("RegSetValueExW is not implemented\n"); 674 goto cleanup; 675 } 676 ok( res == 0, "RegSetValueExW failed error %d\n", res ); 677 678 /* overflow both name and data */ 679 val_count = 2; 680 data_count = 2; 681 type = 1234; 682 memcpy( valueW, xxxW, sizeof(xxxW) ); 683 memcpy( dataW, xxxW, sizeof(xxxW) ); 684 res = RegEnumValueW( test_key, 0, valueW, &val_count, NULL, &type, (BYTE*)dataW, &data_count ); 685 ok( res == ERROR_MORE_DATA, "expected ERROR_MORE_DATA, got %d\n", res ); 686 ok( val_count == 2, "val_count set to %d\n", val_count ); 687 ok( data_count == 7*sizeof(WCHAR), "data_count set to %d instead of 7*sizeof(WCHAR)\n", data_count ); 688 ok( type == REG_SZ, "type %d is not REG_SZ\n", type ); 689 ok( !memcmp( valueW, xxxW, sizeof(xxxW) ), "value modified\n" ); 690 ok( !memcmp( dataW, xxxW, sizeof(xxxW) ), "data modified\n" ); 691 692 /* overflow name */ 693 val_count = 3; 694 data_count = 20; 695 type = 1234; 696 memcpy( valueW, xxxW, sizeof(xxxW) ); 697 memcpy( dataW, xxxW, sizeof(xxxW) ); 698 res = RegEnumValueW( test_key, 0, valueW, &val_count, NULL, &type, (BYTE*)dataW, &data_count ); 699 ok( res == ERROR_MORE_DATA, "expected ERROR_MORE_DATA, got %d\n", res ); 700 ok( val_count == 3, "val_count set to %d\n", val_count ); 701 ok( data_count == 7*sizeof(WCHAR), "data_count set to %d instead of 7*sizeof(WCHAR)\n", data_count ); 702 ok( type == REG_SZ, "type %d is not REG_SZ\n", type ); 703 ok( !memcmp( valueW, xxxW, sizeof(xxxW) ), "value modified\n" ); 704 ok( !memcmp( dataW, xxxW, sizeof(xxxW) ), "data modified\n" ); 705 706 /* overflow data */ 707 val_count = 20; 708 data_count = 2; 709 type = 1234; 710 memcpy( valueW, xxxW, sizeof(xxxW) ); 711 memcpy( dataW, xxxW, sizeof(xxxW) ); 712 res = RegEnumValueW( test_key, 0, valueW, &val_count, NULL, &type, (BYTE*)dataW, &data_count ); 713 ok( res == ERROR_MORE_DATA, "expected ERROR_MORE_DATA, got %d\n", res ); 714 ok( val_count == 4, "val_count set to %d instead of 4\n", val_count ); 715 ok( data_count == 7*sizeof(WCHAR), "data_count set to %d instead of 7*sizeof(WCHAR)\n", data_count ); 716 ok( type == REG_SZ, "type %d is not REG_SZ\n", type ); 717 ok( !memcmp( valueW, testW, sizeof(testW) ), "value is not 'Test'\n" ); 718 ok( !memcmp( dataW, xxxW, sizeof(xxxW) ), "data modified\n" ); 719 720 /* no overflow */ 721 val_count = 20; 722 data_count = 20; 723 type = 1234; 724 memcpy( valueW, xxxW, sizeof(xxxW) ); 725 memcpy( dataW, xxxW, sizeof(xxxW) ); 726 res = RegEnumValueW( test_key, 0, valueW, &val_count, NULL, &type, (BYTE*)dataW, &data_count ); 727 ok( res == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %d\n", res ); 728 ok( val_count == 4, "val_count set to %d instead of 4\n", val_count ); 729 ok( data_count == 7*sizeof(WCHAR), "data_count set to %d instead of 7*sizeof(WCHAR)\n", data_count ); 730 ok( type == REG_SZ, "type %d is not REG_SZ\n", type ); 731 ok( !memcmp( valueW, testW, sizeof(testW) ), "value is not 'Test'\n" ); 732 ok( !memcmp( dataW, foobarW, sizeof(foobarW) ), "data is not 'foobar'\n" ); 733 734 if (pRegGetValueA) /* avoid a crash on Windows 2000 */ 735 { 736 /* no valueW and no val_count parameter */ 737 data_count = 20; 738 type = 1234; 739 memcpy( dataW, xxxW, sizeof(xxxW) ); 740 res = RegEnumValueW( test_key, 0, NULL, NULL, NULL, &type, (BYTE*)dataW, &data_count ); 741 ok( res == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %d\n", res ); 742 743 /* no valueW parameter */ 744 val_count = 20; 745 data_count = 20; 746 type = 1234; 747 memcpy( dataW, xxxW, sizeof(xxxW) ); 748 res = RegEnumValueW( test_key, 0, NULL, &val_count, NULL, &type, (BYTE*)dataW, &data_count ); 749 ok( res == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %d\n", res ); 750 751 /* no val_count parameter */ 752 data_count = 20; 753 type = 1234; 754 memcpy( valueW, xxxW, sizeof(xxxW) ); 755 memcpy( dataW, xxxW, sizeof(xxxW) ); 756 res = RegEnumValueW( test_key, 0, valueW, NULL, NULL, &type, (BYTE*)dataW, &data_count ); 757 ok( res == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %d\n", res ); 758 } 759 760 cleanup: 761 RegDeleteKeyA(test_key, ""); 762 RegCloseKey(test_key); 763 } 764 765 static void test_query_value_ex(void) 766 { 767 DWORD ret, size, type; 768 BYTE buffer[10]; 769 770 size = sizeof(buffer); 771 ret = RegQueryValueExA(hkey_main, "TP1_SZ", NULL, &type, NULL, &size); 772 ok(ret == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %d\n", ret); 773 ok(size == strlen(sTestpath1) + 1, "(%d,%d)\n", (DWORD)strlen(sTestpath1) + 1, size); 774 ok(type == REG_SZ, "type %d is not REG_SZ\n", type); 775 776 type = 0xdeadbeef; 777 size = 0xdeadbeef; 778 ret = RegQueryValueExA(HKEY_CLASSES_ROOT, "Nonexistent Value", NULL, &type, NULL, &size); 779 ok(ret == ERROR_FILE_NOT_FOUND, "expected ERROR_FILE_NOT_FOUND, got %d\n", ret); 780 ok(size == 0, "size should have been set to 0 instead of %d\n", size); 781 782 size = sizeof(buffer); 783 ret = RegQueryValueExA(HKEY_CLASSES_ROOT, "Nonexistent Value", NULL, &type, buffer, &size); 784 ok(ret == ERROR_FILE_NOT_FOUND, "expected ERROR_FILE_NOT_FOUND, got %d\n", ret); 785 ok(size == sizeof(buffer), "size shouldn't have been changed to %d\n", size); 786 787 size = 4; 788 ret = RegQueryValueExA(hkey_main, "BIN32", NULL, &size, buffer, &size); 789 ok(ret == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %d\n", ret); 790 } 791 792 static void test_get_value(void) 793 { 794 DWORD ret; 795 DWORD size; 796 DWORD type; 797 DWORD dw, qw[2]; 798 CHAR buf[80]; 799 CHAR expanded[] = "bar\\subdir1"; 800 CHAR expanded2[] = "ImARatherLongButIndeedNeededString\\subdir1"; 801 802 if(!pRegGetValueA) 803 { 804 win_skip("RegGetValue not available on this platform\n"); 805 return; 806 } 807 808 /* Invalid parameter */ 809 ret = pRegGetValueA(hkey_main, NULL, "DWORD", RRF_RT_REG_DWORD, &type, &dw, NULL); 810 ok(ret == ERROR_INVALID_PARAMETER, "ret=%d\n", ret); 811 812 /* Query REG_DWORD using RRF_RT_REG_DWORD (ok) */ 813 size = type = dw = 0xdeadbeef; 814 ret = pRegGetValueA(hkey_main, NULL, "DWORD", RRF_RT_REG_DWORD, &type, &dw, &size); 815 ok(ret == ERROR_SUCCESS, "ret=%d\n", ret); 816 ok(size == 4, "size=%d\n", size); 817 ok(type == REG_DWORD, "type=%d\n", type); 818 ok(dw == 0x12345678, "dw=%d\n", dw); 819 820 /* Query by subkey-name */ 821 ret = pRegGetValueA(HKEY_CURRENT_USER, "Software\\Wine\\Test", "DWORD", RRF_RT_REG_DWORD, NULL, NULL, NULL); 822 ok(ret == ERROR_SUCCESS, "ret=%d\n", ret); 823 824 /* Query REG_DWORD using RRF_RT_REG_BINARY (restricted) */ 825 size = type = dw = 0xdeadbeef; 826 ret = pRegGetValueA(hkey_main, NULL, "DWORD", RRF_RT_REG_BINARY, &type, &dw, &size); 827 ok(ret == ERROR_UNSUPPORTED_TYPE, "ret=%d\n", ret); 828 /* Although the function failed all values are retrieved */ 829 ok(size == 4, "size=%d\n", size); 830 ok(type == REG_DWORD, "type=%d\n", type); 831 ok(dw == 0x12345678, "dw=%d\n", dw); 832 833 /* Test RRF_ZEROONFAILURE */ 834 type = dw = 0xdeadbeef; size = 4; 835 ret = pRegGetValueA(hkey_main, NULL, "DWORD", RRF_RT_REG_SZ|RRF_ZEROONFAILURE, &type, &dw, &size); 836 ok(ret == ERROR_UNSUPPORTED_TYPE, "ret=%d\n", ret); 837 /* Again all values are retrieved ... */ 838 ok(size == 4, "size=%d\n", size); 839 ok(type == REG_DWORD, "type=%d\n", type); 840 /* ... except the buffer, which is zeroed out */ 841 ok(dw == 0, "dw=%d\n", dw); 842 843 /* Test RRF_ZEROONFAILURE with a NULL buffer... */ 844 type = size = 0xbadbeef; 845 ret = pRegGetValueA(hkey_main, NULL, "DWORD", RRF_RT_REG_SZ|RRF_ZEROONFAILURE, &type, NULL, &size); 846 ok(ret == ERROR_UNSUPPORTED_TYPE, "ret=%d\n", ret); 847 ok(size == 4, "size=%d\n", size); 848 ok(type == REG_DWORD, "type=%d\n", type); 849 850 /* Query REG_DWORD using RRF_RT_DWORD (ok) */ 851 size = type = dw = 0xdeadbeef; 852 ret = pRegGetValueA(hkey_main, NULL, "DWORD", RRF_RT_DWORD, &type, &dw, &size); 853 ok(ret == ERROR_SUCCESS, "ret=%d\n", ret); 854 ok(size == 4, "size=%d\n", size); 855 ok(type == REG_DWORD, "type=%d\n", type); 856 ok(dw == 0x12345678, "dw=%d\n", dw); 857 858 /* Query 32-bit REG_BINARY using RRF_RT_DWORD (ok) */ 859 size = type = dw = 0xdeadbeef; 860 ret = pRegGetValueA(hkey_main, NULL, "BIN32", RRF_RT_DWORD, &type, &dw, &size); 861 ok(ret == ERROR_SUCCESS, "ret=%d\n", ret); 862 ok(size == 4, "size=%d\n", size); 863 ok(type == REG_BINARY, "type=%d\n", type); 864 ok(dw == 0x12345678, "dw=%d\n", dw); 865 866 /* Query 64-bit REG_BINARY using RRF_RT_DWORD (type mismatch) */ 867 qw[0] = qw[1] = size = type = 0xdeadbeef; 868 ret = pRegGetValueA(hkey_main, NULL, "BIN64", RRF_RT_DWORD, &type, qw, &size); 869 ok(ret == ERROR_DATATYPE_MISMATCH, "ret=%d\n", ret); 870 ok(size == 8, "size=%d\n", size); 871 ok(type == REG_BINARY, "type=%d\n", type); 872 ok(qw[0] == 0x12345678 && 873 qw[1] == 0x87654321, "qw={%d,%d}\n", qw[0], qw[1]); 874 875 /* Query 64-bit REG_BINARY using 32-bit buffer (buffer too small) */ 876 type = dw = 0xdeadbeef; size = 4; 877 ret = pRegGetValueA(hkey_main, NULL, "BIN64", RRF_RT_REG_BINARY, &type, &dw, &size); 878 ok(ret == ERROR_MORE_DATA, "ret=%d\n", ret); 879 ok(dw == 0xdeadbeef, "dw=%d\n", dw); 880 ok(size == 8, "size=%d\n", size); 881 882 /* Query 64-bit REG_BINARY using RRF_RT_QWORD (ok) */ 883 qw[0] = qw[1] = size = type = 0xdeadbeef; 884 ret = pRegGetValueA(hkey_main, NULL, "BIN64", RRF_RT_QWORD, &type, qw, &size); 885 ok(ret == ERROR_SUCCESS, "ret=%d\n", ret); 886 ok(size == 8, "size=%d\n", size); 887 ok(type == REG_BINARY, "type=%d\n", type); 888 ok(qw[0] == 0x12345678 && 889 qw[1] == 0x87654321, "qw={%d,%d}\n", qw[0], qw[1]); 890 891 /* Query REG_SZ using RRF_RT_REG_SZ (ok) */ 892 buf[0] = 0; type = 0xdeadbeef; size = sizeof(buf); 893 ret = pRegGetValueA(hkey_main, NULL, "TP1_SZ", RRF_RT_REG_SZ, &type, buf, &size); 894 ok(ret == ERROR_SUCCESS, "ret=%d\n", ret); 895 ok(size == strlen(sTestpath1)+1, "strlen(sTestpath1)=%d size=%d\n", lstrlenA(sTestpath1), size); 896 ok(type == REG_SZ, "type=%d\n", type); 897 ok(!strcmp(sTestpath1, buf), "sTestpath=\"%s\" buf=\"%s\"\n", sTestpath1, buf); 898 899 /* Query REG_SZ using RRF_RT_REG_SZ and no buffer (ok) */ 900 type = 0xdeadbeef; size = 0; 901 ret = pRegGetValueA(hkey_main, NULL, "TP1_SZ", RRF_RT_REG_SZ, &type, NULL, &size); 902 ok(ret == ERROR_SUCCESS, "ret=%d\n", ret); 903 /* v5.2.3790.1830 (2003 SP1) returns sTestpath1 length + 2 here. */ 904 ok(size == strlen(sTestpath1)+1 || broken(size == strlen(sTestpath1)+2), 905 "strlen(sTestpath1)=%d size=%d\n", lstrlenA(sTestpath1), size); 906 ok(type == REG_SZ, "type=%d\n", type); 907 908 /* Query REG_SZ using RRF_RT_REG_SZ on a zero-byte value (ok) */ 909 strcpy(buf, sTestpath1); 910 type = 0xdeadbeef; 911 size = sizeof(buf); 912 ret = pRegGetValueA(hkey_main, NULL, "TP1_ZB_SZ", RRF_RT_REG_SZ, &type, buf, &size); 913 ok(ret == ERROR_SUCCESS, "ret=%d\n", ret); 914 /* v5.2.3790.1830 (2003 SP1) returns sTestpath1 length + 2 here. */ 915 ok(size == 0 || 916 size == 1, /* win2k3 */ 917 "size=%d\n", size); 918 ok(type == REG_SZ, "type=%d\n", type); 919 ok(!strcmp(sTestpath1, buf) || 920 !strcmp(buf, ""), 921 "Expected \"%s\" or \"\", got \"%s\"\n", sTestpath1, buf); 922 923 /* Query REG_SZ using RRF_RT_REG_SZ|RRF_NOEXPAND (ok) */ 924 buf[0] = 0; type = 0xdeadbeef; size = sizeof(buf); 925 ret = pRegGetValueA(hkey_main, NULL, "TP1_SZ", RRF_RT_REG_SZ|RRF_NOEXPAND, &type, buf, &size); 926 ok(ret == ERROR_SUCCESS, "ret=%d\n", ret); 927 ok(size == strlen(sTestpath1)+1, "strlen(sTestpath1)=%d size=%d\n", lstrlenA(sTestpath1), size); 928 ok(type == REG_SZ, "type=%d\n", type); 929 ok(!strcmp(sTestpath1, buf), "sTestpath=\"%s\" buf=\"%s\"\n", sTestpath1, buf); 930 931 /* Query REG_EXPAND_SZ using RRF_RT_REG_SZ and no buffer (ok, expands) */ 932 size = 0; 933 ret = pRegGetValueA(hkey_main, NULL, "TP2_EXP_SZ", RRF_RT_REG_SZ, NULL, NULL, &size); 934 ok(ret == ERROR_SUCCESS, "ret=%d\n", ret); 935 ok((size == strlen(expanded2)+1) || /* win2k3 SP1 */ 936 (size == strlen(expanded2)+2) || /* win2k3 SP2 */ 937 (size == strlen(sTestpath2)+1), 938 "strlen(expanded2)=%d, strlen(sTestpath2)=%d, size=%d\n", lstrlenA(expanded2), lstrlenA(sTestpath2), size); 939 940 /* Query REG_EXPAND_SZ using RRF_RT_REG_SZ (ok, expands) */ 941 buf[0] = 0; type = 0xdeadbeef; size = sizeof(buf); 942 ret = pRegGetValueA(hkey_main, NULL, "TP1_EXP_SZ", RRF_RT_REG_SZ, &type, buf, &size); 943 ok(ret == ERROR_SUCCESS, "ret=%d\n", ret); 944 /* At least v5.2.3790.1830 (2003 SP1) returns the unexpanded sTestpath1 length + 1 here. */ 945 ok(size == strlen(expanded)+1 || broken(size == strlen(sTestpath1)+1), 946 "strlen(expanded)=%d, strlen(sTestpath1)=%d, size=%d\n", lstrlenA(expanded), lstrlenA(sTestpath1), size); 947 ok(type == REG_SZ, "type=%d\n", type); 948 ok(!strcmp(expanded, buf), "expanded=\"%s\" buf=\"%s\"\n", expanded, buf); 949 950 /* Query REG_EXPAND_SZ using RRF_RT_REG_SZ (ok, expands a lot) */ 951 buf[0] = 0; type = 0xdeadbeef; size = sizeof(buf); 952 ret = pRegGetValueA(hkey_main, NULL, "TP2_EXP_SZ", RRF_RT_REG_SZ, &type, buf, &size); 953 ok(ret == ERROR_SUCCESS, "ret=%d\n", ret); 954 /* At least v5.2.3790.1830 (2003 SP1) returns the unexpanded sTestpath2 length + 1 here. */ 955 ok(size == strlen(expanded2)+1 || broken(size == strlen(sTestpath2)+1), 956 "strlen(expanded2)=%d, strlen(sTestpath1)=%d, size=%d\n", lstrlenA(expanded2), lstrlenA(sTestpath2), size); 957 ok(type == REG_SZ, "type=%d\n", type); 958 ok(!strcmp(expanded2, buf), "expanded2=\"%s\" buf=\"%s\"\n", expanded2, buf); 959 960 /* Query REG_EXPAND_SZ using RRF_RT_REG_EXPAND_SZ|RRF_NOEXPAND (ok, doesn't expand) */ 961 buf[0] = 0; type = 0xdeadbeef; size = sizeof(buf); 962 ret = pRegGetValueA(hkey_main, NULL, "TP1_EXP_SZ", RRF_RT_REG_EXPAND_SZ|RRF_NOEXPAND, &type, buf, &size); 963 ok(ret == ERROR_SUCCESS, "ret=%d\n", ret); 964 ok(size == strlen(sTestpath1)+1, "strlen(sTestpath1)=%d size=%d\n", lstrlenA(sTestpath1), size); 965 ok(type == REG_EXPAND_SZ, "type=%d\n", type); 966 ok(!strcmp(sTestpath1, buf), "sTestpath=\"%s\" buf=\"%s\"\n", sTestpath1, buf); 967 968 /* Query REG_EXPAND_SZ using RRF_RT_REG_EXPAND_SZ|RRF_NOEXPAND and no buffer (ok, doesn't expand) */ 969 size = 0xbadbeef; 970 ret = pRegGetValueA(hkey_main, NULL, "TP1_EXP_SZ", RRF_RT_REG_EXPAND_SZ|RRF_NOEXPAND, NULL, NULL, &size); 971 ok(ret == ERROR_SUCCESS, "ret=%d\n", ret); 972 /* v5.2.3790.1830 (2003 SP1) returns sTestpath1 length + 2 here. */ 973 ok(size == strlen(sTestpath1)+1 || broken(size == strlen(sTestpath1)+2), 974 "strlen(sTestpath1)=%d size=%d\n", lstrlenA(sTestpath1), size); 975 976 /* Query REG_EXPAND_SZ using RRF_RT_REG_SZ|RRF_NOEXPAND (type mismatch) */ 977 ret = pRegGetValueA(hkey_main, NULL, "TP1_EXP_SZ", RRF_RT_REG_SZ|RRF_NOEXPAND, NULL, NULL, NULL); 978 ok(ret == ERROR_UNSUPPORTED_TYPE, "ret=%d\n", ret); 979 980 /* Query REG_EXPAND_SZ using RRF_RT_REG_EXPAND_SZ (not allowed without RRF_NOEXPAND) */ 981 ret = pRegGetValueA(hkey_main, NULL, "TP1_EXP_SZ", RRF_RT_REG_EXPAND_SZ, NULL, NULL, NULL); 982 /* before win8: ERROR_INVALID_PARAMETER, win8: ERROR_UNSUPPORTED_TYPE */ 983 ok(ret == ERROR_INVALID_PARAMETER || ret == ERROR_UNSUPPORTED_TYPE, "ret=%d\n", ret); 984 985 /* Query REG_EXPAND_SZ using RRF_RT_ANY */ 986 buf[0] = 0; type = 0xdeadbeef; size = sizeof(buf); 987 ret = pRegGetValueA(hkey_main, NULL, "TP1_EXP_SZ", RRF_RT_ANY, &type, buf, &size); 988 ok(ret == ERROR_SUCCESS, "ret=%d\n", ret); 989 /* At least v5.2.3790.1830 (2003 SP1) returns the unexpanded sTestpath1 length + 1 here. */ 990 ok(size == strlen(expanded)+1 || broken(size == strlen(sTestpath1)+1), 991 "strlen(expanded)=%d, strlen(sTestpath1)=%d, size=%d\n", lstrlenA(expanded), lstrlenA(sTestpath1), size); 992 ok(type == REG_SZ, "type=%d\n", type); 993 ok(!strcmp(expanded, buf), "expanded=\"%s\" buf=\"%s\"\n", expanded, buf); 994 } 995 996 static void test_reg_open_key(void) 997 { 998 DWORD ret = 0; 999 HKEY hkResult = NULL; 1000 HKEY hkPreserve = NULL; 1001 HKEY hkRoot64 = NULL; 1002 HKEY hkRoot32 = NULL; 1003 BOOL bRet; 1004 SID_IDENTIFIER_AUTHORITY sid_authority = {SECURITY_WORLD_SID_AUTHORITY}; 1005 PSID world_sid; 1006 EXPLICIT_ACCESSA access; 1007 PACL key_acl; 1008 SECURITY_DESCRIPTOR *sd; 1009 1010 /* successful open */ 1011 ret = RegOpenKeyA(HKEY_CURRENT_USER, "Software\\Wine\\Test", &hkResult); 1012 ok(ret == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %d\n", ret); 1013 ok(hkResult != NULL, "expected hkResult != NULL\n"); 1014 hkPreserve = hkResult; 1015 1016 /* open same key twice */ 1017 ret = RegOpenKeyA(HKEY_CURRENT_USER, "Software\\Wine\\Test", &hkResult); 1018 ok(ret == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %d\n", ret); 1019 ok(hkResult != hkPreserve, "expected hkResult != hkPreserve\n"); 1020 ok(hkResult != NULL, "hkResult != NULL\n"); 1021 RegCloseKey(hkResult); 1022 1023 /* trailing slashes */ 1024 ret = RegOpenKeyA(HKEY_CURRENT_USER, "Software\\Wine\\Test\\\\", &hkResult); 1025 ok(ret == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %d\n", ret); 1026 RegCloseKey(hkResult); 1027 1028 /* open nonexistent key 1029 * check that hkResult is set to NULL 1030 */ 1031 hkResult = hkPreserve; 1032 ret = RegOpenKeyA(HKEY_CURRENT_USER, "Software\\Wine\\Nonexistent", &hkResult); 1033 ok(ret == ERROR_FILE_NOT_FOUND, "expected ERROR_FILE_NOT_FOUND, got %d\n", ret); 1034 ok(hkResult == NULL, "expected hkResult == NULL\n"); 1035 1036 /* open the same nonexistent key again to make sure the key wasn't created */ 1037 hkResult = hkPreserve; 1038 ret = RegOpenKeyA(HKEY_CURRENT_USER, "Software\\Wine\\Nonexistent", &hkResult); 1039 ok(ret == ERROR_FILE_NOT_FOUND, "expected ERROR_FILE_NOT_FOUND, got %d\n", ret); 1040 ok(hkResult == NULL, "expected hkResult == NULL\n"); 1041 1042 /* send in NULL lpSubKey 1043 * check that hkResult receives the value of hKey 1044 */ 1045 hkResult = hkPreserve; 1046 ret = RegOpenKeyA(HKEY_CURRENT_USER, NULL, &hkResult); 1047 ok(ret == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %d\n", ret); 1048 ok(hkResult == HKEY_CURRENT_USER, "expected hkResult == HKEY_CURRENT_USER\n"); 1049 1050 /* send empty-string in lpSubKey */ 1051 hkResult = hkPreserve; 1052 ret = RegOpenKeyA(HKEY_CURRENT_USER, "", &hkResult); 1053 ok(ret == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %d\n", ret); 1054 ok(hkResult == HKEY_CURRENT_USER, "expected hkResult == HKEY_CURRENT_USER\n"); 1055 1056 /* send in NULL lpSubKey and NULL hKey 1057 * hkResult is set to NULL 1058 */ 1059 hkResult = hkPreserve; 1060 ret = RegOpenKeyA(NULL, NULL, &hkResult); 1061 ok(ret == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %d\n", ret); 1062 ok(hkResult == NULL, "expected hkResult == NULL\n"); 1063 1064 /* only send NULL hKey 1065 * the value of hkResult remains unchanged 1066 */ 1067 hkResult = hkPreserve; 1068 ret = RegOpenKeyA(NULL, "Software\\Wine\\Test", &hkResult); 1069 ok(ret == ERROR_INVALID_HANDLE || ret == ERROR_BADKEY, /* Windows 95 returns BADKEY */ 1070 "expected ERROR_INVALID_HANDLE or ERROR_BADKEY, got %d\n", ret); 1071 ok(hkResult == hkPreserve, "expected hkResult == hkPreserve\n"); 1072 1073 /* send in NULL hkResult */ 1074 ret = RegOpenKeyA(HKEY_CURRENT_USER, "Software\\Wine\\Test", NULL); 1075 ok(ret == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %d\n", ret); 1076 1077 ret = RegOpenKeyA(HKEY_CURRENT_USER, NULL, NULL); 1078 ok(ret == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %d\n", ret); 1079 1080 ret = RegOpenKeyA(NULL, NULL, NULL); 1081 ok(ret == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %d\n", ret); 1082 1083 /* beginning backslash character */ 1084 ret = RegOpenKeyA(HKEY_CURRENT_USER, "\\Software\\Wine\\Test", &hkResult); 1085 ok(ret == ERROR_BAD_PATHNAME || /* NT/2k/XP */ 1086 broken(ret == ERROR_SUCCESS), /* wow64 */ 1087 "expected ERROR_BAD_PATHNAME or ERROR_FILE_NOT_FOUND, got %d\n", ret); 1088 if (!ret) RegCloseKey(hkResult); 1089 1090 hkResult = NULL; 1091 ret = RegOpenKeyExA(HKEY_CLASSES_ROOT, "\\clsid", 0, KEY_QUERY_VALUE, &hkResult); 1092 ok(ret == ERROR_SUCCESS || /* 2k/XP */ 1093 ret == ERROR_BAD_PATHNAME, /* NT */ 1094 "expected ERROR_SUCCESS, ERROR_BAD_PATHNAME or ERROR_FILE_NOT_FOUND, got %d\n", ret); 1095 RegCloseKey(hkResult); 1096 1097 /* NULL or empty subkey of special root */ 1098 hkResult = NULL; 1099 ret = RegOpenKeyExA(HKEY_CLASSES_ROOT, NULL, 0, KEY_QUERY_VALUE, &hkResult); 1100 ok(ret == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %d\n", ret); 1101 ok(hkResult == HKEY_CLASSES_ROOT, "expected hkResult == HKEY_CLASSES_ROOT\n"); 1102 1103 hkResult = NULL; 1104 ret = RegOpenKeyExA(HKEY_CLASSES_ROOT, "", 0, KEY_QUERY_VALUE, &hkResult); 1105 ok(ret == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %d\n", ret); 1106 ok(hkResult == HKEY_CLASSES_ROOT, "expected hkResult == HKEY_CLASSES_ROOT\n"); 1107 1108 hkResult = NULL; 1109 ret = RegOpenKeyExA(HKEY_CLASSES_ROOT, "\\", 0, KEY_QUERY_VALUE, &hkResult); 1110 ok(ret == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %d\n", ret); 1111 ok(hkResult != HKEY_CLASSES_ROOT, "expected hkResult to be a new key\n"); 1112 ok(!RegCloseKey(hkResult), "got invalid hkey\n"); 1113 1114 /* empty subkey of existing handle */ 1115 hkResult = hkPreserve; 1116 ret = RegOpenKeyExA(hkPreserve, "", 0, KEY_QUERY_VALUE, &hkResult); 1117 ok(ret == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %d\n", ret); 1118 ok(hkResult != hkPreserve, "expected hkResult != hkPreserve\n"); 1119 ok(!RegCloseKey(hkResult), "got invalid hkey\n"); 1120 1121 /* NULL subkey of existing handle */ 1122 hkResult = hkPreserve; 1123 ret = RegOpenKeyExA(hkPreserve, NULL, 0, KEY_QUERY_VALUE, &hkResult); 1124 ok(ret == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %d\n", ret); 1125 ok(hkResult != hkPreserve, "expected hkResult != hkPreserve\n"); 1126 ok(!RegCloseKey(hkResult), "got invalid hkey\n"); 1127 1128 /* empty subkey of NULL */ 1129 hkResult = hkPreserve; 1130 ret = RegOpenKeyExA(NULL, "", 0, KEY_QUERY_VALUE, &hkResult); 1131 ok(ret == ERROR_INVALID_HANDLE, "expected ERROR_INVALID_HANDLE, got %d\n", ret); 1132 ok(hkResult == hkPreserve, "expected hkResult == hkPreserve\n"); 1133 1134 RegCloseKey(hkPreserve); 1135 1136 /* WOW64 flags */ 1137 hkResult = NULL; 1138 ret = RegOpenKeyExA(HKEY_LOCAL_MACHINE, "Software", 0, KEY_READ|KEY_WOW64_32KEY, &hkResult); 1139 ok((ret == ERROR_SUCCESS && hkResult != NULL) || broken(ret == ERROR_ACCESS_DENIED /* NT4, win2k */), 1140 "RegOpenKeyEx with KEY_WOW64_32KEY failed (err=%u)\n", ret); 1141 RegCloseKey(hkResult); 1142 1143 hkResult = NULL; 1144 ret = RegOpenKeyExA(HKEY_LOCAL_MACHINE, "Software", 0, KEY_READ|KEY_WOW64_64KEY, &hkResult); 1145 ok((ret == ERROR_SUCCESS && hkResult != NULL) || broken(ret == ERROR_ACCESS_DENIED /* NT4, win2k */), 1146 "RegOpenKeyEx with KEY_WOW64_64KEY failed (err=%u)\n", ret); 1147 RegCloseKey(hkResult); 1148 1149 /* check special HKEYs on 64bit 1150 * only the lower 4 bytes of the supplied key are used 1151 */ 1152 if (ptr_size == 64) 1153 { 1154 /* HKEY_CURRENT_USER */ 1155 ret = RegOpenKeyA(UlongToHandle(HandleToUlong(HKEY_CURRENT_USER)), "Software", &hkResult); 1156 ok(ret == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %d\n", ret); 1157 ok(hkResult != NULL, "expected hkResult != NULL\n"); 1158 RegCloseKey(hkResult); 1159 1160 ret = RegOpenKeyA((HKEY)(HandleToUlong(HKEY_CURRENT_USER) | (ULONG64)1 << 32), "Software", &hkResult); 1161 ok(ret == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %d\n", ret); 1162 ok(hkResult != NULL, "expected hkResult != NULL\n"); 1163 RegCloseKey(hkResult); 1164 1165 ret = RegOpenKeyA((HKEY)(HandleToUlong(HKEY_CURRENT_USER) | (ULONG64)0xdeadbeef << 32), "Software", &hkResult); 1166 ok(ret == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %d\n", ret); 1167 ok(hkResult != NULL, "expected hkResult != NULL\n"); 1168 RegCloseKey(hkResult); 1169 1170 ret = RegOpenKeyA((HKEY)(HandleToUlong(HKEY_CURRENT_USER) | (ULONG64)0xffffffff << 32), "Software", &hkResult); 1171 ok(ret == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %d\n", ret); 1172 ok(hkResult != NULL, "expected hkResult != NULL\n"); 1173 RegCloseKey(hkResult); 1174 1175 /* HKEY_LOCAL_MACHINE */ 1176 ret = RegOpenKeyA((HKEY)(HandleToUlong(HKEY_LOCAL_MACHINE) | (ULONG64)0xdeadbeef << 32), "Software", &hkResult); 1177 ok(ret == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %d\n", ret); 1178 ok(hkResult != NULL, "expected hkResult != NULL\n"); 1179 RegCloseKey(hkResult); 1180 } 1181 1182 /* Try using WOW64 flags when opening a key with a DACL set to verify that 1183 * the registry access check is performed correctly. Redirection isn't 1184 * being tested, so the tests don't care about whether the process is 1185 * running under WOW64. */ 1186 if (!pIsWow64Process) 1187 { 1188 win_skip("WOW64 flags are not recognized\n"); 1189 return; 1190 } 1191 1192 ret = RegCreateKeyExA(HKEY_LOCAL_MACHINE, "Software\\Wine", 0, NULL, 0, 1193 KEY_WOW64_32KEY | KEY_ALL_ACCESS, NULL, &hkRoot32, NULL); 1194 if (limited_user) 1195 ok(ret == ERROR_ACCESS_DENIED && hkRoot32 == NULL, 1196 "RegCreateKeyEx with KEY_WOW64_32KEY failed (err=%u)\n", ret); 1197 else 1198 ok(ret == ERROR_SUCCESS && hkRoot32 != NULL, 1199 "RegCreateKeyEx with KEY_WOW64_32KEY failed (err=%u)\n", ret); 1200 1201 ret = RegCreateKeyExA(HKEY_LOCAL_MACHINE, "Software\\Wine", 0, NULL, 0, 1202 KEY_WOW64_64KEY | KEY_ALL_ACCESS, NULL, &hkRoot64, NULL); 1203 if (limited_user) 1204 ok(ret == ERROR_ACCESS_DENIED && hkRoot64 == NULL, 1205 "RegCreateKeyEx with KEY_WOW64_64KEY failed (err=%u)\n", ret); 1206 else 1207 ok(ret == ERROR_SUCCESS && hkRoot64 != NULL, 1208 "RegCreateKeyEx with KEY_WOW64_64KEY failed (err=%u)\n", ret); 1209 1210 bRet = AllocateAndInitializeSid(&sid_authority, 1, SECURITY_WORLD_RID, 1211 0, 0, 0, 0, 0, 0, 0, &world_sid); 1212 ok(bRet == TRUE, 1213 "Expected AllocateAndInitializeSid to return TRUE, got %d, last error %u\n", bRet, GetLastError()); 1214 1215 access.grfAccessPermissions = GENERIC_ALL | STANDARD_RIGHTS_ALL; 1216 access.grfAccessMode = SET_ACCESS; 1217 access.grfInheritance = SUB_CONTAINERS_AND_OBJECTS_INHERIT; 1218 access.Trustee.pMultipleTrustee = NULL; 1219 access.Trustee.MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE; 1220 access.Trustee.TrusteeForm = TRUSTEE_IS_SID; 1221 access.Trustee.TrusteeType = TRUSTEE_IS_WELL_KNOWN_GROUP; 1222 access.Trustee.ptstrName = (char *)world_sid; 1223 1224 ret = SetEntriesInAclA(1, &access, NULL, &key_acl); 1225 ok(ret == ERROR_SUCCESS, 1226 "Expected SetEntriesInAclA to return ERROR_SUCCESS, got %u, last error %u\n", ret, GetLastError()); 1227 1228 sd = HeapAlloc(GetProcessHeap(), 0, SECURITY_DESCRIPTOR_MIN_LENGTH); 1229 bRet = InitializeSecurityDescriptor(sd, SECURITY_DESCRIPTOR_REVISION); 1230 ok(bRet == TRUE, 1231 "Expected InitializeSecurityDescriptor to return TRUE, got %d, last error %u\n", bRet, GetLastError()); 1232 1233 bRet = SetSecurityDescriptorDacl(sd, TRUE, key_acl, FALSE); 1234 ok(bRet == TRUE, 1235 "Expected SetSecurityDescriptorDacl to return TRUE, got %d, last error %u\n", bRet, GetLastError()); 1236 1237 if (limited_user) 1238 { 1239 skip("not enough privileges to modify HKLM\n"); 1240 } 1241 else 1242 { 1243 LONG error; 1244 1245 error = RegSetKeySecurity(hkRoot64, DACL_SECURITY_INFORMATION, sd); 1246 ok(error == ERROR_SUCCESS, 1247 "Expected RegSetKeySecurity to return success, got error %u\n", error); 1248 1249 error = RegSetKeySecurity(hkRoot32, DACL_SECURITY_INFORMATION, sd); 1250 ok(error == ERROR_SUCCESS, 1251 "Expected RegSetKeySecurity to return success, got error %u\n", error); 1252 1253 hkResult = NULL; 1254 ret = RegOpenKeyExA(HKEY_LOCAL_MACHINE, "Software\\Wine", 0, KEY_WOW64_64KEY | KEY_READ, &hkResult); 1255 ok(ret == ERROR_SUCCESS && hkResult != NULL, 1256 "RegOpenKeyEx with KEY_WOW64_64KEY failed (err=%u)\n", ret); 1257 RegCloseKey(hkResult); 1258 1259 hkResult = NULL; 1260 ret = RegOpenKeyExA(HKEY_LOCAL_MACHINE, "Software\\Wine", 0, KEY_WOW64_32KEY | KEY_READ, &hkResult); 1261 ok(ret == ERROR_SUCCESS && hkResult != NULL, 1262 "RegOpenKeyEx with KEY_WOW64_32KEY failed (err=%u)\n", ret); 1263 RegCloseKey(hkResult); 1264 } 1265 1266 HeapFree(GetProcessHeap(), 0, sd); 1267 LocalFree(key_acl); 1268 FreeSid(world_sid); 1269 RegDeleteKeyA(hkRoot64, ""); 1270 RegCloseKey(hkRoot64); 1271 RegDeleteKeyA(hkRoot32, ""); 1272 RegCloseKey(hkRoot32); 1273 } 1274 1275 static void test_reg_create_key(void) 1276 { 1277 LONG ret; 1278 HKEY hkey1, hkey2; 1279 HKEY hkRoot64 = NULL; 1280 HKEY hkRoot32 = NULL; 1281 DWORD dwRet; 1282 BOOL bRet; 1283 SID_IDENTIFIER_AUTHORITY sid_authority = {SECURITY_WORLD_SID_AUTHORITY}; 1284 PSID world_sid; 1285 EXPLICIT_ACCESSA access; 1286 PACL key_acl; 1287 SECURITY_DESCRIPTOR *sd; 1288 1289 ret = RegCreateKeyExA(hkey_main, "Subkey1", 0, NULL, 0, KEY_NOTIFY, NULL, &hkey1, NULL); 1290 ok(!ret, "RegCreateKeyExA failed with error %d\n", ret); 1291 /* should succeed: all versions of Windows ignore the access rights 1292 * to the parent handle */ 1293 ret = RegCreateKeyExA(hkey1, "Subkey2", 0, NULL, 0, KEY_SET_VALUE, NULL, &hkey2, NULL); 1294 ok(!ret, "RegCreateKeyExA failed with error %d\n", ret); 1295 1296 /* clean up */ 1297 RegDeleteKeyA(hkey2, ""); 1298 RegDeleteKeyA(hkey1, ""); 1299 RegCloseKey(hkey2); 1300 RegCloseKey(hkey1); 1301 1302 /* test creation of volatile keys */ 1303 ret = RegCreateKeyExA(hkey_main, "Volatile", 0, NULL, REG_OPTION_VOLATILE, KEY_ALL_ACCESS, NULL, &hkey1, NULL); 1304 ok(!ret, "RegCreateKeyExA failed with error %d\n", ret); 1305 ret = RegCreateKeyExA(hkey1, "Subkey2", 0, NULL, 0, KEY_ALL_ACCESS, NULL, &hkey2, NULL); 1306 ok(ret == ERROR_CHILD_MUST_BE_VOLATILE, "RegCreateKeyExA failed with error %d\n", ret); 1307 if (!ret) RegCloseKey( hkey2 ); 1308 ret = RegCreateKeyExA(hkey1, "Subkey2", 0, NULL, REG_OPTION_VOLATILE, KEY_ALL_ACCESS, NULL, &hkey2, NULL); 1309 ok(!ret, "RegCreateKeyExA failed with error %d\n", ret); 1310 RegCloseKey(hkey2); 1311 /* should succeed if the key already exists */ 1312 ret = RegCreateKeyExA(hkey1, "Subkey2", 0, NULL, 0, KEY_ALL_ACCESS, NULL, &hkey2, NULL); 1313 ok(!ret, "RegCreateKeyExA failed with error %d\n", ret); 1314 1315 /* clean up */ 1316 RegDeleteKeyA(hkey2, ""); 1317 RegDeleteKeyA(hkey1, ""); 1318 RegCloseKey(hkey2); 1319 RegCloseKey(hkey1); 1320 1321 /* beginning backslash character */ 1322 ret = RegCreateKeyExA(hkey_main, "\\Subkey3", 0, NULL, 0, KEY_NOTIFY, NULL, &hkey1, NULL); 1323 if (!(GetVersion() & 0x80000000)) 1324 ok(ret == ERROR_BAD_PATHNAME, "expected ERROR_BAD_PATHNAME, got %d\n", ret); 1325 else { 1326 ok(!ret, "RegCreateKeyExA failed with error %d\n", ret); 1327 RegDeleteKeyA(hkey1, ""); 1328 RegCloseKey(hkey1); 1329 } 1330 1331 /* trailing backslash characters */ 1332 ret = RegCreateKeyExA(hkey_main, "Subkey4\\\\", 0, NULL, 0, KEY_NOTIFY, NULL, &hkey1, NULL); 1333 ok(ret == ERROR_SUCCESS, "RegCreateKeyExA failed with error %d\n", ret); 1334 RegDeleteKeyA(hkey1, ""); 1335 RegCloseKey(hkey1); 1336 1337 /* System\CurrentControlSet\Control\Video should be non-volatile */ 1338 ret = RegCreateKeyExA(HKEY_LOCAL_MACHINE, "System\\CurrentControlSet\\Control\\Video\\Wine", 1339 0, NULL, 0, KEY_NOTIFY, NULL, &hkey1, NULL); 1340 ok(ret == ERROR_SUCCESS, "RegCreateKeyExA failed with error %d\n", ret); 1341 RegDeleteKeyA(hkey1, ""); 1342 RegCloseKey(hkey1); 1343 1344 /* WOW64 flags - open an existing key */ 1345 hkey1 = NULL; 1346 ret = RegCreateKeyExA(HKEY_LOCAL_MACHINE, "Software", 0, NULL, 0, KEY_READ|KEY_WOW64_32KEY, NULL, &hkey1, NULL); 1347 ok((ret == ERROR_SUCCESS && hkey1 != NULL) || broken(ret == ERROR_ACCESS_DENIED /* NT4, win2k */), 1348 "RegOpenKeyEx with KEY_WOW64_32KEY failed (err=%u)\n", ret); 1349 RegCloseKey(hkey1); 1350 1351 hkey1 = NULL; 1352 ret = RegCreateKeyExA(HKEY_LOCAL_MACHINE, "Software", 0, NULL, 0, KEY_READ|KEY_WOW64_64KEY, NULL, &hkey1, NULL); 1353 ok((ret == ERROR_SUCCESS && hkey1 != NULL) || broken(ret == ERROR_ACCESS_DENIED /* NT4, win2k */), 1354 "RegOpenKeyEx with KEY_WOW64_64KEY failed (err=%u)\n", ret); 1355 RegCloseKey(hkey1); 1356 1357 /* Try using WOW64 flags when opening a key with a DACL set to verify that 1358 * the registry access check is performed correctly. Redirection isn't 1359 * being tested, so the tests don't care about whether the process is 1360 * running under WOW64. */ 1361 if (!pIsWow64Process) 1362 { 1363 win_skip("WOW64 flags are not recognized\n"); 1364 return; 1365 } 1366 1367 ret = RegCreateKeyExA(HKEY_LOCAL_MACHINE, "Software\\Wine", 0, NULL, 0, 1368 KEY_WOW64_32KEY | KEY_ALL_ACCESS, NULL, &hkRoot32, NULL); 1369 if (limited_user) 1370 ok(ret == ERROR_ACCESS_DENIED && hkRoot32 == NULL, 1371 "RegCreateKeyEx with KEY_WOW64_32KEY failed (err=%d)\n", ret); 1372 else 1373 ok(ret == ERROR_SUCCESS && hkRoot32 != NULL, 1374 "RegCreateKeyEx with KEY_WOW64_32KEY failed (err=%d)\n", ret); 1375 1376 ret = RegCreateKeyExA(HKEY_LOCAL_MACHINE, "Software\\Wine", 0, NULL, 0, 1377 KEY_WOW64_64KEY | KEY_ALL_ACCESS, NULL, &hkRoot64, NULL); 1378 if (limited_user) 1379 ok(ret == ERROR_ACCESS_DENIED && hkRoot64 == NULL, 1380 "RegCreateKeyEx with KEY_WOW64_64KEY failed (err=%d)\n", ret); 1381 else 1382 ok(ret == ERROR_SUCCESS && hkRoot64 != NULL, 1383 "RegCreateKeyEx with KEY_WOW64_64KEY failed (err=%d)\n", ret); 1384 1385 bRet = AllocateAndInitializeSid(&sid_authority, 1, SECURITY_WORLD_RID, 1386 0, 0, 0, 0, 0, 0, 0, &world_sid); 1387 ok(bRet == TRUE, 1388 "Expected AllocateAndInitializeSid to return TRUE, got %d, last error %u\n", bRet, GetLastError()); 1389 1390 access.grfAccessPermissions = GENERIC_ALL | STANDARD_RIGHTS_ALL; 1391 access.grfAccessMode = SET_ACCESS; 1392 access.grfInheritance = SUB_CONTAINERS_AND_OBJECTS_INHERIT; 1393 access.Trustee.pMultipleTrustee = NULL; 1394 access.Trustee.MultipleTrusteeOperation = NO_MULTIPLE_TRUSTEE; 1395 access.Trustee.TrusteeForm = TRUSTEE_IS_SID; 1396 access.Trustee.TrusteeType = TRUSTEE_IS_WELL_KNOWN_GROUP; 1397 access.Trustee.ptstrName = (char *)world_sid; 1398 1399 dwRet = SetEntriesInAclA(1, &access, NULL, &key_acl); 1400 ok(dwRet == ERROR_SUCCESS, 1401 "Expected SetEntriesInAclA to return ERROR_SUCCESS, got %u, last error %u\n", dwRet, GetLastError()); 1402 1403 sd = HeapAlloc(GetProcessHeap(), 0, SECURITY_DESCRIPTOR_MIN_LENGTH); 1404 bRet = InitializeSecurityDescriptor(sd, SECURITY_DESCRIPTOR_REVISION); 1405 ok(bRet == TRUE, 1406 "Expected InitializeSecurityDescriptor to return TRUE, got %d, last error %u\n", bRet, GetLastError()); 1407 1408 bRet = SetSecurityDescriptorDacl(sd, TRUE, key_acl, FALSE); 1409 ok(bRet == TRUE, 1410 "Expected SetSecurityDescriptorDacl to return TRUE, got %d, last error %u\n", bRet, GetLastError()); 1411 1412 if (limited_user) 1413 { 1414 skip("not enough privileges to modify HKLM\n"); 1415 } 1416 else 1417 { 1418 ret = RegSetKeySecurity(hkRoot64, DACL_SECURITY_INFORMATION, sd); 1419 ok(ret == ERROR_SUCCESS, 1420 "Expected RegSetKeySecurity to return success, got error %u\n", ret); 1421 1422 ret = RegSetKeySecurity(hkRoot32, DACL_SECURITY_INFORMATION, sd); 1423 ok(ret == ERROR_SUCCESS, 1424 "Expected RegSetKeySecurity to return success, got error %u\n", ret); 1425 1426 hkey1 = NULL; 1427 ret = RegCreateKeyExA(HKEY_LOCAL_MACHINE, "Software\\Wine", 0, NULL, 0, 1428 KEY_WOW64_64KEY | KEY_READ, NULL, &hkey1, NULL); 1429 ok(ret == ERROR_SUCCESS && hkey1 != NULL, 1430 "RegOpenKeyEx with KEY_WOW64_64KEY failed (err=%u)\n", ret); 1431 RegCloseKey(hkey1); 1432 1433 hkey1 = NULL; 1434 ret = RegCreateKeyExA(HKEY_LOCAL_MACHINE, "Software\\Wine", 0, NULL, 0, 1435 KEY_WOW64_32KEY | KEY_READ, NULL, &hkey1, NULL); 1436 ok(ret == ERROR_SUCCESS && hkey1 != NULL, 1437 "RegOpenKeyEx with KEY_WOW64_32KEY failed (err=%u)\n", ret); 1438 RegCloseKey(hkey1); 1439 } 1440 1441 HeapFree(GetProcessHeap(), 0, sd); 1442 LocalFree(key_acl); 1443 FreeSid(world_sid); 1444 RegDeleteKeyA(hkRoot64, ""); 1445 RegCloseKey(hkRoot64); 1446 RegDeleteKeyA(hkRoot32, ""); 1447 RegCloseKey(hkRoot32); 1448 } 1449 1450 static void test_reg_close_key(void) 1451 { 1452 DWORD ret = 0; 1453 HKEY hkHandle; 1454 1455 /* successfully close key 1456 * hkHandle remains changed after call to RegCloseKey 1457 */ 1458 ret = RegOpenKeyA(HKEY_CURRENT_USER, "Software\\Wine\\Test", &hkHandle); 1459 ok(ret == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %d\n", ret); 1460 ret = RegCloseKey(hkHandle); 1461 ok(ret == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %d\n", ret); 1462 1463 /* try to close the key twice */ 1464 ret = RegCloseKey(hkHandle); /* Windows 95 doesn't mind. */ 1465 ok(ret == ERROR_INVALID_HANDLE || ret == ERROR_SUCCESS, 1466 "expected ERROR_INVALID_HANDLE or ERROR_SUCCESS, got %d\n", ret); 1467 1468 /* try to close a NULL handle */ 1469 ret = RegCloseKey(NULL); 1470 ok(ret == ERROR_INVALID_HANDLE || ret == ERROR_BADKEY, /* Windows 95 returns BADKEY */ 1471 "expected ERROR_INVALID_HANDLE or ERROR_BADKEY, got %d\n", ret); 1472 1473 /* Check to see if we didn't potentially close our main handle, which could happen on win98 as 1474 * win98 doesn't give a new handle when the same key is opened. 1475 * Not re-opening will make some next tests fail. 1476 */ 1477 if (hkey_main == hkHandle) 1478 { 1479 trace("The main handle is most likely closed, so re-opening\n"); 1480 RegOpenKeyA( HKEY_CURRENT_USER, "Software\\Wine\\Test", &hkey_main ); 1481 } 1482 } 1483 1484 static void test_reg_delete_key(void) 1485 { 1486 DWORD ret; 1487 HKEY key; 1488 1489 ret = RegDeleteKeyA(hkey_main, NULL); 1490 1491 /* There is a bug in NT4 and W2K that doesn't check if the subkey is NULL. If 1492 * there are also no subkeys available it will delete the key pointed to by hkey_main. 1493 * Not re-creating will make some next tests fail. 1494 */ 1495 if (ret == ERROR_SUCCESS) 1496 { 1497 trace("We are probably running on NT4 or W2K as the main key is deleted," 1498 " re-creating the main key\n"); 1499 setup_main_key(); 1500 } 1501 else 1502 ok(ret == ERROR_INVALID_PARAMETER || 1503 ret == ERROR_ACCESS_DENIED || 1504 ret == ERROR_BADKEY, /* Win95 */ 1505 "ret=%d\n", ret); 1506 1507 ret = RegCreateKeyA(hkey_main, "deleteme", &key); 1508 ok(ret == ERROR_SUCCESS, "Could not create key, got %d\n", ret); 1509 ret = RegDeleteKeyA(key, ""); 1510 ok(ret == ERROR_SUCCESS, "RegDeleteKeyA failed, got %d\n", ret); 1511 RegCloseKey(key); 1512 ret = RegOpenKeyA(hkey_main, "deleteme", &key); 1513 ok(ret == ERROR_FILE_NOT_FOUND, "Key was not deleted, got %d\n", ret); 1514 RegCloseKey(key); 1515 } 1516 1517 static BOOL set_privileges(LPCSTR privilege, BOOL set) 1518 { 1519 TOKEN_PRIVILEGES tp; 1520 HANDLE hToken; 1521 LUID luid; 1522 1523 if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &hToken)) 1524 return FALSE; 1525 1526 if(!LookupPrivilegeValueA(NULL, privilege, &luid)) 1527 { 1528 CloseHandle(hToken); 1529 return FALSE; 1530 } 1531 1532 tp.PrivilegeCount = 1; 1533 tp.Privileges[0].Luid = luid; 1534 1535 if (set) 1536 tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; 1537 else 1538 tp.Privileges[0].Attributes = 0; 1539 1540 AdjustTokenPrivileges(hToken, FALSE, &tp, sizeof(TOKEN_PRIVILEGES), NULL, NULL); 1541 if (GetLastError() != ERROR_SUCCESS) 1542 { 1543 CloseHandle(hToken); 1544 return FALSE; 1545 } 1546 1547 CloseHandle(hToken); 1548 return TRUE; 1549 } 1550 1551 static void test_reg_save_key(void) 1552 { 1553 DWORD ret; 1554 1555 if (!set_privileges(SE_BACKUP_NAME, TRUE) || 1556 !set_privileges(SE_RESTORE_NAME, FALSE)) 1557 { 1558 win_skip("Failed to set SE_BACKUP_NAME privileges, skipping tests\n"); 1559 return; 1560 } 1561 1562 ret = RegSaveKeyA(hkey_main, "saved_key", NULL); 1563 ok(ret == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %d\n", ret); 1564 1565 set_privileges(SE_BACKUP_NAME, FALSE); 1566 } 1567 1568 static void test_reg_load_key(void) 1569 { 1570 DWORD ret; 1571 HKEY hkHandle; 1572 1573 if (!set_privileges(SE_RESTORE_NAME, TRUE) || 1574 !set_privileges(SE_BACKUP_NAME, FALSE)) 1575 { 1576 win_skip("Failed to set SE_RESTORE_NAME privileges, skipping tests\n"); 1577 return; 1578 } 1579 1580 ret = RegLoadKeyA(HKEY_LOCAL_MACHINE, "Test", "saved_key"); 1581 ok(ret == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %d\n", ret); 1582 1583 set_privileges(SE_RESTORE_NAME, FALSE); 1584 1585 ret = RegOpenKeyA(HKEY_LOCAL_MACHINE, "Test", &hkHandle); 1586 ok(ret == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %d\n", ret); 1587 1588 RegCloseKey(hkHandle); 1589 } 1590 1591 static void test_reg_unload_key(void) 1592 { 1593 DWORD ret; 1594 1595 if (!set_privileges(SE_RESTORE_NAME, TRUE) || 1596 !set_privileges(SE_BACKUP_NAME, FALSE)) 1597 { 1598 win_skip("Failed to set SE_RESTORE_NAME privileges, skipping tests\n"); 1599 return; 1600 } 1601 1602 ret = RegUnLoadKeyA(HKEY_LOCAL_MACHINE, "Test"); 1603 ok(ret == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %d\n", ret); 1604 1605 set_privileges(SE_RESTORE_NAME, FALSE); 1606 1607 DeleteFileA("saved_key"); 1608 DeleteFileA("saved_key.LOG"); 1609 } 1610 1611 /* tests that show that RegConnectRegistry and 1612 OpenSCManager accept computer names without the 1613 \\ prefix (what MSDN says). */ 1614 static void test_regconnectregistry( void) 1615 { 1616 CHAR compName[MAX_COMPUTERNAME_LENGTH + 1]; 1617 CHAR netwName[MAX_COMPUTERNAME_LENGTH + 3]; /* 2 chars for double backslash */ 1618 DWORD len = sizeof(compName) ; 1619 BOOL ret; 1620 LONG retl; 1621 HKEY hkey; 1622 SC_HANDLE schnd; 1623 1624 SetLastError(0xdeadbeef); 1625 ret = GetComputerNameA(compName, &len); 1626 ok( ret, "GetComputerName failed err = %d\n", GetLastError()); 1627 if( !ret) return; 1628 1629 lstrcpyA(netwName, "\\\\"); 1630 lstrcpynA(netwName+2, compName, MAX_COMPUTERNAME_LENGTH + 1); 1631 1632 retl = RegConnectRegistryA( compName, HKEY_LOCAL_MACHINE, &hkey); 1633 ok( !retl || 1634 retl == ERROR_DLL_INIT_FAILED || 1635 retl == ERROR_BAD_NETPATH, /* some win2k */ 1636 "RegConnectRegistryA failed err = %d\n", retl); 1637 if( !retl) RegCloseKey( hkey); 1638 1639 retl = RegConnectRegistryA( netwName, HKEY_LOCAL_MACHINE, &hkey); 1640 ok( !retl || 1641 retl == ERROR_DLL_INIT_FAILED || 1642 retl == ERROR_BAD_NETPATH, /* some win2k */ 1643 "RegConnectRegistryA failed err = %d\n", retl); 1644 if( !retl) RegCloseKey( hkey); 1645 1646 SetLastError(0xdeadbeef); 1647 schnd = OpenSCManagerA( compName, NULL, GENERIC_READ); 1648 if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED) 1649 { 1650 win_skip("OpenSCManagerA is not implemented\n"); 1651 return; 1652 } 1653 1654 ok( schnd != NULL, "OpenSCManagerA failed err = %d\n", GetLastError()); 1655 CloseServiceHandle( schnd); 1656 1657 SetLastError(0xdeadbeef); 1658 schnd = OpenSCManagerA( netwName, NULL, GENERIC_READ); 1659 ok( schnd != NULL, "OpenSCManagerA failed err = %d\n", GetLastError()); 1660 CloseServiceHandle( schnd); 1661 1662 } 1663 1664 static void test_reg_query_value(void) 1665 { 1666 HKEY subkey; 1667 CHAR val[MAX_PATH]; 1668 WCHAR valW[5]; 1669 LONG size, ret; 1670 1671 static const WCHAR expected[] = {'d','a','t','a',0}; 1672 1673 ret = RegCreateKeyA(hkey_main, "subkey", &subkey); 1674 ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret); 1675 1676 ret = RegSetValueA(subkey, NULL, REG_SZ, "data", 4); 1677 ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret); 1678 1679 /* try an invalid hkey */ 1680 SetLastError(0xdeadbeef); 1681 size = MAX_PATH; 1682 ret = RegQueryValueA((HKEY)0xcafebabe, "subkey", val, &size); 1683 ok(ret == ERROR_INVALID_HANDLE || 1684 ret == ERROR_BADKEY || /* Windows 98 returns BADKEY */ 1685 ret == ERROR_ACCESS_DENIED, /* non-admin winxp */ 1686 "Expected ERROR_INVALID_HANDLE or ERROR_BADKEY, got %d\n", ret); 1687 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError()); 1688 1689 /* try a NULL hkey */ 1690 SetLastError(0xdeadbeef); 1691 size = MAX_PATH; 1692 ret = RegQueryValueA(NULL, "subkey", val, &size); 1693 ok(ret == ERROR_INVALID_HANDLE || ret == ERROR_BADKEY, /* Windows 98 returns BADKEY */ 1694 "Expected ERROR_INVALID_HANDLE or ERROR_BADKEY, got %d\n", ret); 1695 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError()); 1696 1697 /* try a NULL value */ 1698 size = MAX_PATH; 1699 ret = RegQueryValueA(hkey_main, "subkey", NULL, &size); 1700 ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret); 1701 ok(size == 5, "Expected 5, got %d\n", size); 1702 1703 /* try a NULL size */ 1704 SetLastError(0xdeadbeef); 1705 val[0] = '\0'; 1706 ret = RegQueryValueA(hkey_main, "subkey", val, NULL); 1707 ok(ret == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", ret); 1708 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError()); 1709 ok(!val[0], "Expected val to be untouched, got %s\n", val); 1710 1711 /* try a NULL value and size */ 1712 ret = RegQueryValueA(hkey_main, "subkey", NULL, NULL); 1713 ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret); 1714 1715 /* try a size too small */ 1716 SetLastError(0xdeadbeef); 1717 val[0] = '\0'; 1718 size = 1; 1719 ret = RegQueryValueA(hkey_main, "subkey", val, &size); 1720 ok(ret == ERROR_MORE_DATA, "Expected ERROR_MORE_DATA, got %d\n", ret); 1721 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError()); 1722 ok(!val[0], "Expected val to be untouched, got %s\n", val); 1723 ok(size == 5, "Expected 5, got %d\n", size); 1724 1725 /* successfully read the value using 'subkey' */ 1726 size = MAX_PATH; 1727 ret = RegQueryValueA(hkey_main, "subkey", val, &size); 1728 ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret); 1729 ok(!lstrcmpA(val, "data"), "Expected 'data', got '%s'\n", val); 1730 ok(size == 5, "Expected 5, got %d\n", size); 1731 1732 /* successfully read the value using the subkey key */ 1733 size = MAX_PATH; 1734 ret = RegQueryValueA(subkey, NULL, val, &size); 1735 ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret); 1736 ok(!lstrcmpA(val, "data"), "Expected 'data', got '%s'\n", val); 1737 ok(size == 5, "Expected 5, got %d\n", size); 1738 1739 /* unicode - try size too small */ 1740 SetLastError(0xdeadbeef); 1741 valW[0] = '\0'; 1742 size = 0; 1743 ret = RegQueryValueW(subkey, NULL, valW, &size); 1744 if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED) 1745 { 1746 win_skip("RegQueryValueW is not implemented\n"); 1747 goto cleanup; 1748 } 1749 ok(ret == ERROR_MORE_DATA, "Expected ERROR_MORE_DATA, got %d\n", ret); 1750 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError()); 1751 ok(!valW[0], "Expected valW to be untouched\n"); 1752 ok(size == sizeof(expected), "Got wrong size: %d\n", size); 1753 1754 /* unicode - try size in WCHARS */ 1755 SetLastError(0xdeadbeef); 1756 size = sizeof(valW) / sizeof(WCHAR); 1757 ret = RegQueryValueW(subkey, NULL, valW, &size); 1758 ok(ret == ERROR_MORE_DATA, "Expected ERROR_MORE_DATA, got %d\n", ret); 1759 ok(GetLastError() == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", GetLastError()); 1760 ok(!valW[0], "Expected valW to be untouched\n"); 1761 ok(size == sizeof(expected), "Got wrong size: %d\n", size); 1762 1763 /* unicode - successfully read the value */ 1764 size = sizeof(valW); 1765 ret = RegQueryValueW(subkey, NULL, valW, &size); 1766 ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret); 1767 ok(!lstrcmpW(valW, expected), "Got wrong value\n"); 1768 ok(size == sizeof(expected), "Got wrong size: %d\n", size); 1769 1770 /* unicode - set the value without a NULL terminator */ 1771 ret = RegSetValueW(subkey, NULL, REG_SZ, expected, sizeof(expected)-sizeof(WCHAR)); 1772 ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret); 1773 1774 /* unicode - read the unterminated value, value is terminated for us */ 1775 memset(valW, 'a', sizeof(valW)); 1776 size = sizeof(valW); 1777 ret = RegQueryValueW(subkey, NULL, valW, &size); 1778 ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret); 1779 ok(!lstrcmpW(valW, expected), "Got wrong value\n"); 1780 ok(size == sizeof(expected), "Got wrong size: %d\n", size); 1781 1782 cleanup: 1783 RegDeleteKeyA(subkey, ""); 1784 RegCloseKey(subkey); 1785 } 1786 1787 static void test_reg_query_info(void) 1788 { 1789 HKEY subkey; 1790 HKEY subsubkey; 1791 LONG ret; 1792 char classbuffer[32]; 1793 WCHAR classbufferW[32]; 1794 char expectbuffer[32]; 1795 WCHAR expectbufferW[32]; 1796 char subkey_class[] = "subkey class"; 1797 WCHAR subkey_classW[] = {'s','u','b','k','e','y',' ','c','l','a','s','s',0}; 1798 char subsubkey_class[] = "subsubkey class"; 1799 DWORD classlen; 1800 DWORD subkeys, maxsubkeylen, maxclasslen; 1801 DWORD values, maxvaluenamelen, maxvaluelen; 1802 DWORD sdlen; 1803 FILETIME lastwrite; 1804 1805 ret = RegCreateKeyExA(hkey_main, "subkey", 0, subkey_class, 0, KEY_ALL_ACCESS, NULL, &subkey, NULL); 1806 ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret); 1807 1808 /* all parameters NULL */ 1809 ret = RegQueryInfoKeyA(NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); 1810 ok(ret == ERROR_INVALID_HANDLE, "ret = %d\n", ret); 1811 1812 ret = RegQueryInfoKeyW(NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); 1813 ok(ret == ERROR_INVALID_HANDLE, "ret = %d\n", ret); 1814 1815 /* not requesting any information */ 1816 ret = RegQueryInfoKeyA(subkey, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); 1817 ok(ret == ERROR_SUCCESS, "ret = %d\n", ret); 1818 1819 ret = RegQueryInfoKeyW(subkey, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); 1820 ok(ret == ERROR_SUCCESS, "ret = %d\n", ret); 1821 1822 /* class without length is invalid */ 1823 memset(classbuffer, 0x55, sizeof(classbuffer)); 1824 ret = RegQueryInfoKeyA(subkey, classbuffer, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); 1825 ok(ret == ERROR_INVALID_PARAMETER, "ret = %d\n", ret); 1826 ok(classbuffer[0] == 0x55, "classbuffer[0] = 0x%x\n", classbuffer[0]); 1827 1828 memset(classbufferW, 0x55, sizeof(classbufferW)); 1829 ret = RegQueryInfoKeyW(subkey, classbufferW, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); 1830 ok(ret == ERROR_INVALID_PARAMETER, "ret = %d\n", ret); 1831 ok(classbufferW[0] == 0x5555, "classbufferW[0] = 0x%x\n", classbufferW[0]); 1832 1833 /* empty key */ 1834 sdlen = classlen =0; 1835 ret = RegQueryInfoKeyA(subkey, NULL, &classlen, NULL, &subkeys, &maxsubkeylen, &maxclasslen, &values, &maxvaluenamelen, &maxvaluelen, &sdlen, &lastwrite); 1836 ok(ret == ERROR_SUCCESS, "ret = %d\n", ret); 1837 ok(classlen == strlen(subkey_class), "classlen = %u\n", classlen); 1838 ok(subkeys == 0, "subkeys = %u\n", subkeys); 1839 ok(maxsubkeylen == 0, "maxsubkeylen = %u\n", maxsubkeylen); 1840 ok(maxclasslen == 0, "maxclasslen = %u\n", maxclasslen); 1841 ok(values == 0, "values = %u\n", values); 1842 ok(maxvaluenamelen == 0, "maxvaluenamelen = %u\n", maxvaluenamelen); 1843 ok(maxvaluelen == 0, "maxvaluelen = %u\n", maxvaluelen); 1844 todo_wine ok(sdlen != 0, "sdlen = %u\n", sdlen); 1845 ok(lastwrite.dwLowDateTime != 0, "lastwrite.dwLowDateTime = %u\n", lastwrite.dwLowDateTime); 1846 ok(lastwrite.dwHighDateTime != 0, "lastwrite.dwHighDateTime = %u\n", lastwrite.dwHighDateTime); 1847 1848 sdlen = classlen = 0; 1849 ret = RegQueryInfoKeyW(subkey, NULL, &classlen, NULL, &subkeys, &maxsubkeylen, &maxclasslen, &values, &maxvaluenamelen, &maxvaluelen, &sdlen, &lastwrite); 1850 ok(ret == ERROR_SUCCESS, "ret = %d\n", ret); 1851 ok(classlen == strlen(subkey_class), "classlen = %u\n", classlen); 1852 ok(subkeys == 0, "subkeys = %u\n", subkeys); 1853 ok(maxsubkeylen == 0, "maxsubkeylen = %u\n", maxsubkeylen); 1854 ok(maxclasslen == 0, "maxclasslen = %u\n", maxclasslen); 1855 ok(values == 0, "values = %u\n", values); 1856 ok(maxvaluenamelen == 0, "maxvaluenamelen = %u\n", maxvaluenamelen); 1857 ok(maxvaluelen == 0, "maxvaluelen = %u\n", maxvaluelen); 1858 todo_wine ok(sdlen != 0, "sdlen = %u\n", sdlen); 1859 ok(lastwrite.dwLowDateTime != 0, "lastwrite.dwLowDateTime = %u\n", lastwrite.dwLowDateTime); 1860 ok(lastwrite.dwHighDateTime != 0, "lastwrite.dwHighDateTime = %u\n", lastwrite.dwHighDateTime); 1861 1862 ret = RegCreateKeyExA(subkey, "subsubkey", 0, subsubkey_class, 0, KEY_ALL_ACCESS, NULL, &subsubkey, NULL); 1863 ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret); 1864 1865 ret = RegSetValueExA(subkey, NULL, 0, REG_SZ, (const BYTE*)"data", 5); 1866 ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret); 1867 1868 /* with subkey & default value */ 1869 sdlen = classlen = 0; 1870 ret = RegQueryInfoKeyA(subkey, NULL, &classlen, NULL, &subkeys, &maxsubkeylen, &maxclasslen, &values, &maxvaluenamelen, &maxvaluelen, &sdlen, &lastwrite); 1871 ok(ret == ERROR_SUCCESS, "ret = %d\n", ret); 1872 ok(classlen == strlen(subkey_class), "classlen = %u\n", classlen); 1873 ok(subkeys == 1, "subkeys = %u\n", subkeys); 1874 ok(maxsubkeylen == strlen("subsubkey"), "maxsubkeylen = %u\n", maxsubkeylen); 1875 ok(maxclasslen == strlen(subsubkey_class), "maxclasslen = %u\n", maxclasslen); 1876 ok(values == 1, "values = %u\n", values); 1877 ok(maxvaluenamelen == 0, "maxvaluenamelen = %u\n", maxvaluenamelen); 1878 ok(maxvaluelen == sizeof("data") * sizeof(WCHAR), "maxvaluelen = %u\n", maxvaluelen); 1879 todo_wine ok(sdlen != 0, "sdlen = %u\n", sdlen); 1880 ok(lastwrite.dwLowDateTime != 0, "lastwrite.dwLowDateTime = %u\n", lastwrite.dwLowDateTime); 1881 ok(lastwrite.dwHighDateTime != 0, "lastwrite.dwHighDateTime = %u\n", lastwrite.dwHighDateTime); 1882 1883 sdlen = classlen = 0; 1884 ret = RegQueryInfoKeyW(subkey, NULL, &classlen, NULL, &subkeys, &maxsubkeylen, &maxclasslen, &values, &maxvaluenamelen, &maxvaluelen, &sdlen, &lastwrite); 1885 ok(ret == ERROR_SUCCESS, "ret = %d\n", ret); 1886 ok(classlen == strlen(subkey_class), "classlen = %u\n", classlen); 1887 ok(subkeys == 1, "subkeys = %u\n", subkeys); 1888 ok(maxsubkeylen == strlen("subsubkey"), "maxsubkeylen = %u\n", maxsubkeylen); 1889 ok(maxclasslen == strlen(subsubkey_class), "maxclasslen = %u\n", maxclasslen); 1890 ok(values == 1, "values = %u\n", values); 1891 ok(maxvaluenamelen == 0, "maxvaluenamelen = %u\n", maxvaluenamelen); 1892 ok(maxvaluelen == sizeof("data") * sizeof(WCHAR), "maxvaluelen = %u\n", maxvaluelen); 1893 todo_wine ok(sdlen != 0, "sdlen = %u\n", sdlen); 1894 ok(lastwrite.dwLowDateTime != 0, "lastwrite.dwLowDateTime = %u\n", lastwrite.dwLowDateTime); 1895 ok(lastwrite.dwHighDateTime != 0, "lastwrite.dwHighDateTime = %u\n", lastwrite.dwHighDateTime); 1896 1897 ret = RegSetValueExA(subkey, "value one", 0, REG_SZ, (const BYTE*)"first value data", 17); 1898 ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret); 1899 1900 ret = RegSetValueExA(subkey, "value 2", 0, REG_SZ, (const BYTE*)"second value data", 18); 1901 ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret); 1902 1903 /* with named value */ 1904 classlen = 0; 1905 ret = RegQueryInfoKeyA(subkey, NULL, &classlen, NULL, &subkeys, &maxsubkeylen, &maxclasslen, &values, &maxvaluenamelen, &maxvaluelen, &sdlen, &lastwrite); 1906 ok(ret == ERROR_SUCCESS, "ret = %d\n", ret); 1907 ok(values == 3, "values = %u\n", values); 1908 ok(maxvaluenamelen == strlen("value one"), "maxvaluenamelen = %u\n", maxvaluenamelen); 1909 ok(maxvaluelen == sizeof("second value data") * sizeof(WCHAR), "maxvaluelen = %u\n", maxvaluelen); 1910 1911 classlen = 0; 1912 ret = RegQueryInfoKeyW(subkey, NULL, &classlen, NULL, &subkeys, &maxsubkeylen, &maxclasslen, &values, &maxvaluenamelen, &maxvaluelen, &sdlen, &lastwrite); 1913 ok(ret == ERROR_SUCCESS, "ret = %d\n", ret); 1914 ok(values == 3, "values = %u\n", values); 1915 ok(maxvaluenamelen == strlen("value one"), "maxvaluenamelen = %u\n", maxvaluenamelen); 1916 ok(maxvaluelen == sizeof("second value data") * sizeof(WCHAR), "maxvaluelen = %u\n", maxvaluelen); 1917 1918 /* class name with zero size buffer */ 1919 memset(classbuffer, 0x55, sizeof(classbuffer)); 1920 classlen = 0; 1921 ret = RegQueryInfoKeyA(subkey, classbuffer, &classlen, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); 1922 ok(ret == ERROR_SUCCESS, "ret = %d\n", ret); 1923 ok(classlen == strlen(subkey_class) /* win2k */ || 1924 classlen == 0, "classlen = %u\n", classlen); 1925 memset(expectbuffer, 0x55, sizeof(expectbuffer)); 1926 ok(!memcmp(classbuffer, expectbuffer, sizeof(classbuffer)), "classbuffer was modified\n"); 1927 1928 memset(classbufferW, 0x55, sizeof(classbufferW)); 1929 classlen = 0; 1930 ret = RegQueryInfoKeyW(subkey, classbufferW, &classlen, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); 1931 ok(ret == ERROR_SUCCESS, "ret = %d\n", ret); 1932 ok(classlen == strlen(subkey_class) /* win2k */ || 1933 classlen == 0, "classlen = %u\n", classlen); 1934 memset(expectbufferW, 0x55, sizeof(expectbufferW)); 1935 ok(!memcmp(classbufferW, expectbufferW, sizeof(classbufferW)), "classbufferW was modified\n"); 1936 1937 /* class name with one char buffer */ 1938 memset(classbuffer, 0x55, sizeof(classbuffer)); 1939 classlen = 1; 1940 ret = RegQueryInfoKeyA(subkey, classbuffer, &classlen, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); 1941 ok(ret == ERROR_MORE_DATA, "ret = %d\n", ret); 1942 ok(classlen == 0, "classlen = %u\n", classlen); 1943 memset(expectbuffer, 0x55, sizeof(expectbuffer)); 1944 expectbuffer[0] = 0; 1945 ok(!memcmp(classbuffer, expectbuffer, sizeof(classbuffer)), "classbuffer was modified\n"); 1946 1947 memset(classbufferW, 0x55, sizeof(classbufferW)); 1948 classlen = 1; 1949 ret = RegQueryInfoKeyW(subkey, classbufferW, &classlen, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); 1950 ok(ret == ERROR_INSUFFICIENT_BUFFER, "ret = %d\n", ret); 1951 ok(classlen == 0 /* win8 */ || 1952 classlen == strlen(subkey_class), "classlen = %u\n", classlen); 1953 memset(expectbufferW, 0x55, sizeof(expectbufferW)); 1954 ok(!memcmp(classbufferW, expectbufferW, sizeof(classbufferW)), "classbufferW was modified\n"); 1955 1956 /* class name with buffer one char too small */ 1957 memset(classbuffer, 0x55, sizeof(classbuffer)); 1958 classlen = sizeof(subkey_class) - 1; 1959 ret = RegQueryInfoKeyA(subkey, classbuffer, &classlen, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); 1960 ok(ret == ERROR_MORE_DATA, "ret = %d\n", ret); 1961 ok(classlen == sizeof(subkey_class) - 2, "classlen = %u\n", classlen); 1962 memset(expectbuffer, 0x55, sizeof(expectbuffer)); 1963 strcpy(expectbuffer, subkey_class); 1964 expectbuffer[sizeof(subkey_class) - 2] = 0; 1965 expectbuffer[sizeof(subkey_class) - 1] = 0x55; 1966 ok(!memcmp(classbuffer, expectbuffer, sizeof(classbuffer)), 1967 "classbuffer = %.*s, expected %s\n", 1968 (int)sizeof(classbuffer), classbuffer, expectbuffer); 1969 1970 memset(classbufferW, 0x55, sizeof(classbufferW)); 1971 classlen = sizeof(subkey_class) - 1; 1972 ret = RegQueryInfoKeyW(subkey, classbufferW, &classlen, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); 1973 ok(ret == ERROR_INSUFFICIENT_BUFFER, "ret = %d\n", ret); 1974 ok(classlen == sizeof(subkey_class) - 2 /* win8 */ || 1975 classlen == strlen(subkey_class), "classlen = %u\n", classlen); 1976 memset(expectbufferW, 0x55, sizeof(expectbufferW)); 1977 ok(!memcmp(classbufferW, expectbufferW, sizeof(classbufferW)), "classbufferW was modified\n"); 1978 1979 /* class name with large enough buffer */ 1980 memset(classbuffer, 0x55, sizeof(classbuffer)); 1981 classlen = sizeof(subkey_class); 1982 ret = RegQueryInfoKeyA(subkey, classbuffer, &classlen, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); 1983 ok(ret == ERROR_SUCCESS, "ret = %d\n", ret); 1984 ok(classlen == sizeof(subkey_class) - 1, "classlen = %u\n", classlen); 1985 memset(expectbuffer, 0x55, sizeof(expectbuffer)); 1986 strcpy(expectbuffer, subkey_class); 1987 ok(!memcmp(classbuffer, expectbuffer, sizeof(classbuffer)), 1988 "classbuffer = \"%.*s\", expected %s\n", 1989 (int)sizeof(classbuffer), classbuffer, expectbuffer); 1990 1991 memset(classbuffer, 0x55, sizeof(classbuffer)); 1992 classlen = 0xdeadbeef; 1993 ret = RegQueryInfoKeyA(subkey, classbuffer, &classlen, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); 1994 ok(ret == ERROR_SUCCESS, "ret = %d\n", ret); 1995 ok(classlen == sizeof(subkey_class) - 1, "classlen = %u\n", classlen); 1996 memset(expectbuffer, 0x55, sizeof(expectbuffer)); 1997 strcpy(expectbuffer, subkey_class); 1998 ok(!memcmp(classbuffer, expectbuffer, sizeof(classbuffer)), 1999 "classbuffer = \"%.*s\", expected %s\n", 2000 (int)sizeof(classbuffer), classbuffer, expectbuffer); 2001 2002 memset(classbufferW, 0x55, sizeof(classbufferW)); 2003 classlen = sizeof(subkey_class); 2004 ret = RegQueryInfoKeyW(subkey, classbufferW, &classlen, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); 2005 ok(ret == ERROR_SUCCESS, "ret = %d\n", ret); 2006 ok(classlen == sizeof(subkey_class) - 1, "classlen = %u\n", classlen); 2007 memset(expectbufferW, 0x55, sizeof(expectbufferW)); 2008 lstrcpyW(expectbufferW, subkey_classW); 2009 ok(!memcmp(classbufferW, expectbufferW, sizeof(classbufferW)), 2010 "classbufferW = %s, expected %s\n", 2011 wine_dbgstr_wn(classbufferW, sizeof(classbufferW) / sizeof(WCHAR)), wine_dbgstr_w(expectbufferW)); 2012 2013 memset(classbufferW, 0x55, sizeof(classbufferW)); 2014 classlen = 0xdeadbeef; 2015 ret = RegQueryInfoKeyW(subkey, classbufferW, &classlen, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); 2016 ok(ret == ERROR_SUCCESS, "ret = %d\n", ret); 2017 ok(classlen == sizeof(subkey_class) - 1, "classlen = %u\n", classlen); 2018 memset(expectbufferW, 0x55, sizeof(expectbufferW)); 2019 lstrcpyW(expectbufferW, subkey_classW); 2020 ok(!memcmp(classbufferW, expectbufferW, sizeof(classbufferW)), 2021 "classbufferW = %s, expected %s\n", 2022 wine_dbgstr_wn(classbufferW, sizeof(classbufferW) / sizeof(WCHAR)), wine_dbgstr_w(expectbufferW)); 2023 2024 RegDeleteKeyA(subsubkey, ""); 2025 RegCloseKey(subsubkey); 2026 RegDeleteKeyA(subkey, ""); 2027 RegCloseKey(subkey); 2028 } 2029 2030 static void test_string_termination(void) 2031 { 2032 HKEY subkey; 2033 LSTATUS ret; 2034 static const char string[] = "FullString"; 2035 char name[11]; 2036 BYTE buffer[11]; 2037 DWORD insize, outsize, nsize; 2038 2039 ret = RegCreateKeyA(hkey_main, "string_termination", &subkey); 2040 ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret); 2041 2042 /* Off-by-one RegSetValueExA -> adds a trailing '\0'! */ 2043 insize=sizeof(string)-1; 2044 ret = RegSetValueExA(subkey, "stringtest", 0, REG_SZ, (BYTE*)string, insize); 2045 ok(ret == ERROR_SUCCESS, "RegSetValueExA failed: %d\n", ret); 2046 outsize=insize; 2047 ret = RegQueryValueExA(subkey, "stringtest", NULL, NULL, buffer, &outsize); 2048 ok(ret == ERROR_MORE_DATA, "RegQueryValueExA returned: %d\n", ret); 2049 2050 /* Off-by-two RegSetValueExA -> no trailing '\0' */ 2051 insize=sizeof(string)-2; 2052 ret = RegSetValueExA(subkey, "stringtest", 0, REG_SZ, (BYTE*)string, insize); 2053 ok(ret == ERROR_SUCCESS, "RegSetValueExA failed: %d\n", ret); 2054 outsize=0; 2055 ret = RegQueryValueExA(subkey, "stringtest", NULL, NULL, NULL, &outsize); 2056 ok(ret == ERROR_SUCCESS, "RegQueryValueExA failed: %d\n", ret); 2057 ok(outsize == insize, "wrong size %u != %u\n", outsize, insize); 2058 2059 /* RegQueryValueExA may return a string with no trailing '\0' */ 2060 outsize=insize; 2061 memset(buffer, 0xbd, sizeof(buffer)); 2062 ret = RegQueryValueExA(subkey, "stringtest", NULL, NULL, buffer, &outsize); 2063 ok(ret == ERROR_SUCCESS, "RegQueryValueExA failed: %d\n", ret); 2064 ok(outsize == insize, "wrong size: %u != %u\n", outsize, insize); 2065 ok(memcmp(buffer, string, outsize) == 0, "bad string: %s/%u != %s\n", 2066 wine_debugstr_an((char*)buffer, outsize), outsize, string); 2067 ok(buffer[insize] == 0xbd, "buffer overflow at %u %02x\n", insize, buffer[insize]); 2068 2069 /* RegQueryValueExA adds a trailing '\0' if there is room */ 2070 outsize=insize+1; 2071 memset(buffer, 0xbd, sizeof(buffer)); 2072 ret = RegQueryValueExA(subkey, "stringtest", NULL, NULL, buffer, &outsize); 2073 ok(ret == ERROR_SUCCESS, "RegQueryValueExA failed: %d\n", ret); 2074 ok(outsize == insize, "wrong size: %u != %u\n", outsize, insize); 2075 ok(memcmp(buffer, string, outsize) == 0, "bad string: %s/%u != %s\n", 2076 wine_debugstr_an((char*)buffer, outsize), outsize, string); 2077 ok(buffer[insize] == 0, "buffer overflow at %u %02x\n", insize, buffer[insize]); 2078 2079 /* RegEnumValueA may return a string with no trailing '\0' */ 2080 outsize=insize; 2081 memset(buffer, 0xbd, sizeof(buffer)); 2082 nsize=sizeof(name); 2083 ret = RegEnumValueA(subkey, 0, name, &nsize, NULL, NULL, buffer, &outsize); 2084 ok(ret == ERROR_SUCCESS, "RegEnumValueA failed: %d\n", ret); 2085 ok(strcmp(name, "stringtest") == 0, "wrong name: %s\n", name); 2086 ok(outsize == insize, "wrong size: %u != %u\n", outsize, insize); 2087 ok(memcmp(buffer, string, outsize) == 0, "bad string: %s/%u != %s\n", 2088 wine_debugstr_an((char*)buffer, outsize), outsize, string); 2089 ok(buffer[insize] == 0xbd, "buffer overflow at %u %02x\n", insize, buffer[insize]); 2090 2091 /* RegEnumValueA adds a trailing '\0' if there is room */ 2092 outsize=insize+1; 2093 memset(buffer, 0xbd, sizeof(buffer)); 2094 nsize=sizeof(name); 2095 ret = RegEnumValueA(subkey, 0, name, &nsize, NULL, NULL, buffer, &outsize); 2096 ok(ret == ERROR_SUCCESS, "RegEnumValueA failed: %d\n", ret); 2097 ok(strcmp(name, "stringtest") == 0, "wrong name: %s\n", name); 2098 ok(outsize == insize, "wrong size: %u != %u\n", outsize, insize); 2099 ok(memcmp(buffer, string, outsize) == 0, "bad string: %s/%u != %s\n", 2100 wine_debugstr_an((char*)buffer, outsize), outsize, string); 2101 ok(buffer[insize] == 0, "buffer overflow at %u %02x\n", insize, buffer[insize]); 2102 2103 RegDeleteKeyA(subkey, ""); 2104 RegCloseKey(subkey); 2105 } 2106 2107 static void test_reg_copy_tree(void) 2108 { 2109 HKEY src, dst, subkey; 2110 CHAR buffer[MAX_PATH]; 2111 DWORD dwsize, type; 2112 LONG size, ret; 2113 2114 if (!pRegCopyTreeA) 2115 { 2116 win_skip("Skipping RegCopyTreeA tests, function not present\n"); 2117 return; 2118 } 2119 2120 ret = RegCreateKeyA(hkey_main, "src", &src); 2121 ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret); 2122 ret = RegCreateKeyA(hkey_main, "dst", &dst); 2123 ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret); 2124 2125 /* Copy nonexistent subkey */ 2126 ret = pRegCopyTreeA(src, "nonexistent_subkey", dst); 2127 ok(ret == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %d\n", ret); 2128 2129 /* Create test keys and values */ 2130 ret = RegSetValueA(src, NULL, REG_SZ, "data", 4); 2131 ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret); 2132 ret = RegSetValueExA(src, "value", 0, REG_SZ, (const BYTE *)"data2", 5); 2133 ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret); 2134 2135 ret = RegCreateKeyA(src, "subkey2", &subkey); 2136 ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret); 2137 ret = RegSetValueA(subkey, NULL, REG_SZ, "data3", 5); 2138 ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret); 2139 ret = RegSetValueExA(subkey, "value", 0, REG_SZ, (const BYTE *)"data4", 5); 2140 ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret); 2141 ret = RegCloseKey(subkey); 2142 ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret); 2143 2144 ret = RegCreateKeyA(src, "subkey3", &subkey); 2145 ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret); 2146 ret = RegCloseKey(subkey); 2147 ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret); 2148 2149 /* Copy subkey */ 2150 ret = pRegCopyTreeA(src, "subkey2", dst); 2151 ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret); 2152 2153 size = MAX_PATH; 2154 ret = RegQueryValueA(dst, NULL, buffer, &size); 2155 ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret); 2156 ok(!strcmp(buffer, "data3"), "Expected 'data3', got '%s'\n", buffer); 2157 2158 dwsize = MAX_PATH; 2159 ret = RegQueryValueExA(dst, "value", NULL, &type, (BYTE *)buffer, &dwsize); 2160 ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret); 2161 ok(type == REG_SZ, "Expected REG_SZ, got %u\n", type); 2162 ok(!strcmp(buffer, "data4"), "Expected 'data4', got '%s'\n", buffer); 2163 2164 /* Copy full tree */ 2165 ret = pRegCopyTreeA(src, NULL, dst); 2166 ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret); 2167 2168 size = MAX_PATH; 2169 ret = RegQueryValueA(dst, NULL, buffer, &size); 2170 ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret); 2171 ok(!strcmp(buffer, "data"), "Expected 'data', got '%s'\n", buffer); 2172 2173 dwsize = MAX_PATH; 2174 ret = RegQueryValueExA(dst, "value", NULL, &type, (BYTE *)buffer, &dwsize); 2175 ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret); 2176 ok(type == REG_SZ, "Expected REG_SZ, got %u\n", type); 2177 ok(!strcmp(buffer, "data2"), "Expected 'data2', got '%s'\n", buffer); 2178 2179 ret = RegOpenKeyA(dst, "subkey2", &subkey); 2180 ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret); 2181 size = MAX_PATH; 2182 ret = RegQueryValueA(subkey, NULL, buffer, &size); 2183 ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret); 2184 ok(!strcmp(buffer, "data3"), "Expected 'data3', got '%s'\n", buffer); 2185 dwsize = MAX_PATH; 2186 ret = RegQueryValueExA(subkey, "value", NULL, &type, (BYTE *)buffer, &dwsize); 2187 ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret); 2188 ok(type == REG_SZ, "Expected REG_SZ, got %u\n", type); 2189 ok(!strcmp(buffer, "data4"), "Expected 'data4', got '%s'\n", buffer); 2190 ret = RegCloseKey(subkey); 2191 ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret); 2192 2193 ret = RegOpenKeyA(dst, "subkey3", &subkey); 2194 ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret); 2195 ret = RegCloseKey(subkey); 2196 ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret); 2197 2198 delete_key(src); 2199 delete_key(dst); 2200 } 2201 2202 static void test_reg_delete_tree(void) 2203 { 2204 CHAR buffer[MAX_PATH]; 2205 HKEY subkey, subkey2; 2206 DWORD dwsize, type; 2207 LONG size, ret; 2208 2209 if(!pRegDeleteTreeA) { 2210 win_skip("Skipping RegDeleteTreeA tests, function not present\n"); 2211 return; 2212 } 2213 2214 ret = RegCreateKeyA(hkey_main, "subkey", &subkey); 2215 ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret); 2216 ret = RegCreateKeyA(subkey, "subkey2", &subkey2); 2217 ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret); 2218 ret = RegSetValueA(subkey, NULL, REG_SZ, "data", 4); 2219 ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret); 2220 ret = RegSetValueA(subkey2, NULL, REG_SZ, "data2", 5); 2221 ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret); 2222 ret = RegCloseKey(subkey2); 2223 ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret); 2224 2225 ret = pRegDeleteTreeA(subkey, "subkey2"); 2226 ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret); 2227 ok(RegOpenKeyA(subkey, "subkey2", &subkey2), 2228 "subkey2 was not deleted\n"); 2229 size = MAX_PATH; 2230 ok(!RegQueryValueA(subkey, NULL, buffer, &size), 2231 "Default value of subkey no longer present\n"); 2232 2233 ret = RegCreateKeyA(subkey, "subkey2", &subkey2); 2234 ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret); 2235 ret = RegCloseKey(subkey2); 2236 ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret); 2237 ret = pRegDeleteTreeA(hkey_main, "subkey\\subkey2"); 2238 ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret); 2239 ok(RegOpenKeyA(subkey, "subkey2", &subkey2), 2240 "subkey2 was not deleted\n"); 2241 ok(!RegQueryValueA(subkey, NULL, buffer, &size), 2242 "Default value of subkey no longer present\n"); 2243 2244 ret = RegCreateKeyA(subkey, "subkey2", &subkey2); 2245 ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret); 2246 ret = RegCloseKey(subkey2); 2247 ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret); 2248 ret = RegCreateKeyA(subkey, "subkey3", &subkey2); 2249 ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret); 2250 ret = RegCloseKey(subkey2); 2251 ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret); 2252 ret = RegSetValueA(subkey, NULL, REG_SZ, "data", 4); 2253 ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret); 2254 ret = RegSetValueExA(subkey, "value", 0, REG_SZ, (const BYTE *)"data2", 5); 2255 ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret); 2256 ret = pRegDeleteTreeA(subkey, NULL); 2257 ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret); 2258 ok(!RegOpenKeyA(hkey_main, "subkey", &subkey), 2259 "subkey was deleted\n"); 2260 ok(RegOpenKeyA(subkey, "subkey2", &subkey2), 2261 "subkey2 was not deleted\n"); 2262 ok(RegOpenKeyA(subkey, "subkey3", &subkey2), 2263 "subkey3 was not deleted\n"); 2264 size = MAX_PATH; 2265 ret = RegQueryValueA(subkey, NULL, buffer, &size); 2266 ok(ret == ERROR_SUCCESS, 2267 "Default value of subkey is not present\n"); 2268 ok(!buffer[0], "Expected length 0 got length %u(%s)\n", lstrlenA(buffer), buffer); 2269 dwsize = MAX_PATH; 2270 ok(RegQueryValueExA(subkey, "value", NULL, &type, (BYTE *)buffer, &dwsize), 2271 "Value is still present\n"); 2272 ret = RegCloseKey(subkey); 2273 ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret); 2274 2275 ret = RegOpenKeyA(hkey_main, "subkey", &subkey); 2276 ok(ret == ERROR_SUCCESS, "subkey was deleted\n"); 2277 ret = pRegDeleteTreeA(subkey, ""); 2278 ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret); 2279 ret = RegCloseKey(subkey); 2280 ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret); 2281 2282 ret = RegOpenKeyA(hkey_main, "subkey", &subkey); 2283 ok(ret == ERROR_SUCCESS, "subkey was deleted\n"); 2284 ret = RegCloseKey(subkey); 2285 ok(ret == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", ret); 2286 2287 ret = pRegDeleteTreeA(hkey_main, "not-here"); 2288 ok(ret == ERROR_FILE_NOT_FOUND, 2289 "Expected ERROR_FILE_NOT_FOUND, got %d\n", ret); 2290 } 2291 2292 static void test_rw_order(void) 2293 { 2294 HKEY hKey; 2295 DWORD dw = 0; 2296 static const char keyname[] = "test_rw_order"; 2297 char value_buf[2]; 2298 DWORD values, value_len, value_name_max_len; 2299 LSTATUS ret; 2300 2301 RegDeleteKeyA(HKEY_CURRENT_USER, keyname); 2302 ret = RegCreateKeyA(HKEY_CURRENT_USER, keyname, &hKey); 2303 if(ret != ERROR_SUCCESS) { 2304 skip("Couldn't create key. Skipping.\n"); 2305 return; 2306 } 2307 2308 ok(!RegSetValueExA(hKey, "A", 0, REG_DWORD, (LPBYTE)&dw, sizeof(dw)), 2309 "RegSetValueExA for value \"A\" failed\n"); 2310 ok(!RegSetValueExA(hKey, "C", 0, REG_DWORD, (LPBYTE)&dw, sizeof(dw)), 2311 "RegSetValueExA for value \"C\" failed\n"); 2312 ok(!RegSetValueExA(hKey, "D", 0, REG_DWORD, (LPBYTE)&dw, sizeof(dw)), 2313 "RegSetValueExA for value \"D\" failed\n"); 2314 ok(!RegSetValueExA(hKey, "B", 0, REG_DWORD, (LPBYTE)&dw, sizeof(dw)), 2315 "RegSetValueExA for value \"B\" failed\n"); 2316 2317 ok(!RegQueryInfoKeyA(hKey, NULL, NULL, NULL, NULL, NULL, NULL, &values, 2318 &value_name_max_len, NULL, NULL, NULL), "RegQueryInfoKeyA failed\n"); 2319 ok(values == 4, "Expected 4 values, got %u\n", values); 2320 2321 /* Value enumeration preserves RegSetValueEx call order */ 2322 value_len = 2; 2323 ok(!RegEnumValueA(hKey, 0, value_buf, &value_len, NULL, NULL, NULL, NULL), "RegEnumValueA failed\n"); 2324 ok(strcmp(value_buf, "A") == 0, "Expected name \"A\", got %s\n", value_buf); 2325 value_len = 2; 2326 ok(!RegEnumValueA(hKey, 1, value_buf, &value_len, NULL, NULL, NULL, NULL), "RegEnumValueA failed\n"); 2327 todo_wine ok(strcmp(value_buf, "C") == 0, "Expected name \"C\", got %s\n", value_buf); 2328 value_len = 2; 2329 ok(!RegEnumValueA(hKey, 2, value_buf, &value_len, NULL, NULL, NULL, NULL), "RegEnumValueA failed\n"); 2330 todo_wine ok(strcmp(value_buf, "D") == 0, "Expected name \"D\", got %s\n", value_buf); 2331 value_len = 2; 2332 ok(!RegEnumValueA(hKey, 3, value_buf, &value_len, NULL, NULL, NULL, NULL), "RegEnumValueA failed\n"); 2333 todo_wine ok(strcmp(value_buf, "B") == 0, "Expected name \"B\", got %s\n", value_buf); 2334 2335 ok(!RegDeleteKeyA(HKEY_CURRENT_USER, keyname), "Failed to delete key\n"); 2336 } 2337 2338 static void test_symlinks(void) 2339 { 2340 static const WCHAR targetW[] = {'\\','S','o','f','t','w','a','r','e','\\','W','i','n','e', 2341 '\\','T','e','s','t','\\','t','a','r','g','e','t',0}; 2342 BYTE buffer[1024]; 2343 UNICODE_STRING target_str; 2344 WCHAR *target; 2345 HKEY key, link; 2346 NTSTATUS status; 2347 DWORD target_len, type, len, dw, err; 2348 2349 if (!pRtlFormatCurrentUserKeyPath || !pNtDeleteKey) 2350 { 2351 win_skip( "Can't perform symlink tests\n" ); 2352 return; 2353 } 2354 2355 pRtlFormatCurrentUserKeyPath( &target_str ); 2356 2357 target_len = target_str.Length + sizeof(targetW); 2358 target = HeapAlloc( GetProcessHeap(), 0, target_len ); 2359 memcpy( target, target_str.Buffer, target_str.Length ); 2360 memcpy( target + target_str.Length/sizeof(WCHAR), targetW, sizeof(targetW) ); 2361 2362 err = RegCreateKeyExA( hkey_main, "link", 0, NULL, REG_OPTION_CREATE_LINK, 2363 KEY_ALL_ACCESS, NULL, &link, NULL ); 2364 ok( err == ERROR_SUCCESS, "RegCreateKeyEx failed: %u\n", err ); 2365 2366 /* REG_SZ is not allowed */ 2367 err = RegSetValueExA( link, "SymbolicLinkValue", 0, REG_SZ, (BYTE *)"foobar", sizeof("foobar") ); 2368 ok( err == ERROR_ACCESS_DENIED, "RegSetValueEx wrong error %u\n", err ); 2369 err = RegSetValueExA( link, "SymbolicLinkValue", 0, REG_LINK, 2370 (BYTE *)target, target_len - sizeof(WCHAR) ); 2371 ok( err == ERROR_SUCCESS, "RegSetValueEx failed error %u\n", err ); 2372 /* other values are not allowed */ 2373 err = RegSetValueExA( link, "link", 0, REG_LINK, (BYTE *)target, target_len - sizeof(WCHAR) ); 2374 ok( err == ERROR_ACCESS_DENIED, "RegSetValueEx wrong error %u\n", err ); 2375 2376 /* try opening the target through the link */ 2377 2378 err = RegOpenKeyA( hkey_main, "link", &key ); 2379 ok( err == ERROR_FILE_NOT_FOUND, "RegOpenKey wrong error %u\n", err ); 2380 2381 err = RegCreateKeyExA( hkey_main, "target", 0, NULL, 0, KEY_ALL_ACCESS, NULL, &key, NULL ); 2382 ok( err == ERROR_SUCCESS, "RegCreateKeyEx failed error %u\n", err ); 2383 2384 dw = 0xbeef; 2385 err = RegSetValueExA( key, "value", 0, REG_DWORD, (BYTE *)&dw, sizeof(dw) ); 2386 ok( err == ERROR_SUCCESS, "RegSetValueEx failed error %u\n", err ); 2387 RegCloseKey( key ); 2388 2389 err = RegOpenKeyA( hkey_main, "link", &key ); 2390 ok( err == ERROR_SUCCESS, "RegOpenKey failed error %u\n", err ); 2391 2392 len = sizeof(buffer); 2393 err = RegQueryValueExA( key, "value", NULL, &type, buffer, &len ); 2394 ok( err == ERROR_SUCCESS, "RegOpenKey failed error %u\n", err ); 2395 ok( len == sizeof(DWORD), "wrong len %u\n", len ); 2396 2397 len = sizeof(buffer); 2398 err = RegQueryValueExA( key, "SymbolicLinkValue", NULL, &type, buffer, &len ); 2399 ok( err == ERROR_FILE_NOT_FOUND, "RegQueryValueEx wrong error %u\n", err ); 2400 2401 /* REG_LINK can be created in non-link keys */ 2402 err = RegSetValueExA( key, "SymbolicLinkValue", 0, REG_LINK, 2403 (BYTE *)target, target_len - sizeof(WCHAR) ); 2404 ok( err == ERROR_SUCCESS, "RegSetValueEx failed error %u\n", err ); 2405 len = sizeof(buffer); 2406 err = RegQueryValueExA( key, "SymbolicLinkValue", NULL, &type, buffer, &len ); 2407 ok( err == ERROR_SUCCESS, "RegQueryValueEx failed error %u\n", err ); 2408 ok( len == target_len - sizeof(WCHAR), "wrong len %u\n", len ); 2409 err = RegDeleteValueA( key, "SymbolicLinkValue" ); 2410 ok( err == ERROR_SUCCESS, "RegDeleteValue failed error %u\n", err ); 2411 2412 RegCloseKey( key ); 2413 2414 err = RegCreateKeyExA( hkey_main, "link", 0, NULL, 0, KEY_ALL_ACCESS, NULL, &key, NULL ); 2415 ok( err == ERROR_SUCCESS, "RegCreateKeyEx failed error %u\n", err ); 2416 2417 len = sizeof(buffer); 2418 err = RegQueryValueExA( key, "value", NULL, &type, buffer, &len ); 2419 ok( err == ERROR_SUCCESS, "RegQueryValueEx failed error %u\n", err ); 2420 ok( len == sizeof(DWORD), "wrong len %u\n", len ); 2421 2422 err = RegQueryValueExA( key, "SymbolicLinkValue", NULL, &type, buffer, &len ); 2423 ok( err == ERROR_FILE_NOT_FOUND, "RegQueryValueEx wrong error %u\n", err ); 2424 RegCloseKey( key ); 2425 2426 /* now open the symlink itself */ 2427 2428 err = RegOpenKeyExA( hkey_main, "link", REG_OPTION_OPEN_LINK, KEY_ALL_ACCESS, &key ); 2429 ok( err == ERROR_SUCCESS, "RegOpenKeyEx failed error %u\n", err ); 2430 len = sizeof(buffer); 2431 err = RegQueryValueExA( key, "SymbolicLinkValue", NULL, &type, buffer, &len ); 2432 ok( err == ERROR_SUCCESS, "RegQueryValueEx failed error %u\n", err ); 2433 ok( len == target_len - sizeof(WCHAR), "wrong len %u\n", len ); 2434 RegCloseKey( key ); 2435 2436 err = RegCreateKeyExA( hkey_main, "link", 0, NULL, REG_OPTION_OPEN_LINK, 2437 KEY_ALL_ACCESS, NULL, &key, NULL ); 2438 ok( err == ERROR_SUCCESS, "RegCreateKeyEx failed error %u\n", err ); 2439 len = sizeof(buffer); 2440 err = RegQueryValueExA( key, "SymbolicLinkValue", NULL, &type, buffer, &len ); 2441 ok( err == ERROR_SUCCESS, "RegQueryValueEx failed error %u\n", err ); 2442 ok( len == target_len - sizeof(WCHAR), "wrong len %u\n", len ); 2443 RegCloseKey( key ); 2444 2445 err = RegCreateKeyExA( hkey_main, "link", 0, NULL, REG_OPTION_CREATE_LINK, 2446 KEY_ALL_ACCESS, NULL, &key, NULL ); 2447 ok( err == ERROR_ALREADY_EXISTS, "RegCreateKeyEx wrong error %u\n", err ); 2448 2449 err = RegCreateKeyExA( hkey_main, "link", 0, NULL, REG_OPTION_CREATE_LINK | REG_OPTION_OPEN_LINK, 2450 KEY_ALL_ACCESS, NULL, &key, NULL ); 2451 ok( err == ERROR_ALREADY_EXISTS, "RegCreateKeyEx wrong error %u\n", err ); 2452 2453 err = RegDeleteKeyA( hkey_main, "target" ); 2454 ok( err == ERROR_SUCCESS, "RegDeleteKey failed error %u\n", err ); 2455 2456 err = RegDeleteKeyA( hkey_main, "link" ); 2457 ok( err == ERROR_FILE_NOT_FOUND, "RegDeleteKey wrong error %u\n", err ); 2458 2459 status = pNtDeleteKey( link ); 2460 ok( !status, "NtDeleteKey failed: 0x%08x\n", status ); 2461 RegCloseKey( link ); 2462 2463 HeapFree( GetProcessHeap(), 0, target ); 2464 pRtlFreeUnicodeString( &target_str ); 2465 } 2466 2467 static DWORD get_key_value( HKEY root, const char *name, DWORD flags ) 2468 { 2469 HKEY key; 2470 DWORD err, type, dw, len = sizeof(dw); 2471 2472 err = RegCreateKeyExA( root, name, 0, NULL, 0, flags | KEY_ALL_ACCESS, NULL, &key, NULL ); 2473 if (err == ERROR_FILE_NOT_FOUND) return 0; 2474 ok( err == ERROR_SUCCESS, "%08x: RegCreateKeyEx failed: %u\n", flags, err ); 2475 2476 err = RegQueryValueExA( key, "value", NULL, &type, (BYTE *)&dw, &len ); 2477 if (err == ERROR_FILE_NOT_FOUND) 2478 dw = 0; 2479 else 2480 ok( err == ERROR_SUCCESS, "%08x: RegQueryValueEx failed: %u\n", flags, err ); 2481 RegCloseKey( key ); 2482 return dw; 2483 } 2484 2485 static void _check_key_value( int line, HANDLE root, const char *name, DWORD flags, DWORD expect ) 2486 { 2487 DWORD dw = get_key_value( root, name, flags ); 2488 ok_(__FILE__,line)( dw == expect, "%08x: wrong value %u/%u\n", flags, dw, expect ); 2489 } 2490 #define check_key_value(root,name,flags,expect) _check_key_value( __LINE__, root, name, flags, expect ) 2491 2492 static void test_redirection(void) 2493 { 2494 DWORD err, type, dw, len; 2495 HKEY key, root32, root64, key32, key64, native, op_key; 2496 BOOL is_vista = FALSE; 2497 REGSAM opposite = (sizeof(void*) == 8 ? KEY_WOW64_32KEY : KEY_WOW64_64KEY); 2498 2499 if (ptr_size != 64) 2500 { 2501 BOOL is_wow64; 2502 if (!pIsWow64Process || !pIsWow64Process( GetCurrentProcess(), &is_wow64 ) || !is_wow64) 2503 { 2504 skip( "Not on Wow64, no redirection\n" ); 2505 return; 2506 } 2507 } 2508 2509 err = RegCreateKeyExA( HKEY_LOCAL_MACHINE, "Software\\Wine", 0, NULL, 0, 2510 KEY_WOW64_64KEY | KEY_ALL_ACCESS, NULL, &root64, NULL ); 2511 ok( err == ERROR_SUCCESS, "RegCreateKeyExA failed: %u\n", err ); 2512 2513 err = RegCreateKeyExA( HKEY_LOCAL_MACHINE, "Software\\Wine", 0, NULL, 0, 2514 KEY_WOW64_32KEY | KEY_ALL_ACCESS, NULL, &root32, NULL ); 2515 ok( err == ERROR_SUCCESS, "RegCreateKeyExA failed: %u\n", err ); 2516 2517 err = RegCreateKeyExA( HKEY_LOCAL_MACHINE, "Software\\Wine\\Winetest", 0, NULL, 0, 2518 KEY_WOW64_64KEY | KEY_ALL_ACCESS, NULL, &key64, NULL ); 2519 ok( err == ERROR_SUCCESS, "RegCreateKeyExA failed: %u\n", err ); 2520 2521 err = RegCreateKeyExA( HKEY_LOCAL_MACHINE, "Software\\Wine\\Winetest", 0, NULL, 0, 2522 KEY_WOW64_32KEY | KEY_ALL_ACCESS, NULL, &key32, NULL ); 2523 ok( err == ERROR_SUCCESS, "RegCreateKeyExA failed: %u\n", err ); 2524 2525 dw = 64; 2526 err = RegSetValueExA( key64, "value", 0, REG_DWORD, (BYTE *)&dw, sizeof(dw) ); 2527 ok( err == ERROR_SUCCESS, "RegSetValueExA failed: %u\n", err ); 2528 2529 dw = 32; 2530 err = RegSetValueExA( key32, "value", 0, REG_DWORD, (BYTE *)&dw, sizeof(dw) ); 2531 ok( err == ERROR_SUCCESS, "RegSetValueExA failed: %u\n", err ); 2532 2533 dw = 0; 2534 len = sizeof(dw); 2535 err = RegQueryValueExA( key32, "value", NULL, &type, (BYTE *)&dw, &len ); 2536 ok( err == ERROR_SUCCESS, "RegQueryValueExA failed: %u\n", err ); 2537 ok( dw == 32, "wrong value %u\n", dw ); 2538 2539 dw = 0; 2540 len = sizeof(dw); 2541 err = RegQueryValueExA( key64, "value", NULL, &type, (BYTE *)&dw, &len ); 2542 ok( err == ERROR_SUCCESS, "RegQueryValueExA failed: %u\n", err ); 2543 ok( dw == 64, "wrong value %u\n", dw ); 2544 2545 err = RegCreateKeyExA( HKEY_LOCAL_MACHINE, "Software", 0, NULL, 0, 2546 KEY_ALL_ACCESS, NULL, &key, NULL ); 2547 ok( err == ERROR_SUCCESS, "RegCreateKeyExA failed: %u\n", err ); 2548 2549 if (ptr_size == 32) 2550 { 2551 /* the Vista mechanism allows opening Wow6432Node from a 32-bit key too */ 2552 /* the new (and simpler) Win7 mechanism doesn't */ 2553 if (get_key_value( key, "Wow6432Node\\Wine\\Winetest", 0 ) == 32) 2554 { 2555 trace( "using Vista-style Wow6432Node handling\n" ); 2556 is_vista = TRUE; 2557 } 2558 check_key_value( key, "Wine\\Winetest", 0, 32 ); 2559 check_key_value( key, "Wine\\Winetest", KEY_WOW64_64KEY, is_vista ? 64 : 32 ); 2560 check_key_value( key, "Wine\\Winetest", KEY_WOW64_32KEY, 32 ); 2561 check_key_value( key, "Wow6432Node\\Wine\\Winetest", 0, is_vista ? 32 : 0 ); 2562 check_key_value( key, "Wow6432Node\\Wine\\Winetest", KEY_WOW64_64KEY, is_vista ? 64 : 0 ); 2563 check_key_value( key, "Wow6432Node\\Wine\\Winetest", KEY_WOW64_32KEY, is_vista ? 32 : 0 ); 2564 } 2565 else 2566 { 2567 if (get_key_value( HKEY_LOCAL_MACHINE, "Software\\Wow6432Node\\Wine\\Winetest", KEY_WOW64_64KEY ) == 64) 2568 { 2569 trace( "using Vista-style Wow6432Node handling\n" ); 2570 is_vista = TRUE; 2571 } 2572 check_key_value( key, "Wine\\Winetest", 0, 64 ); 2573 check_key_value( key, "Wow6432Node\\Wine\\Winetest", 0, 32 ); 2574 } 2575 RegCloseKey( key ); 2576 2577 if (ptr_size == 32) 2578 { 2579 err = RegCreateKeyExA( HKEY_LOCAL_MACHINE, "Software", 0, NULL, 0, 2580 KEY_WOW64_64KEY | KEY_ALL_ACCESS, NULL, &key, NULL ); 2581 ok( err == ERROR_SUCCESS, "RegCreateKeyExA failed: %u\n", err ); 2582 dw = get_key_value( key, "Wine\\Winetest", 0 ); 2583 ok( dw == 64 || broken(dw == 32) /* xp64 */, "wrong value %u\n", dw ); 2584 check_key_value( key, "Wine\\Winetest", KEY_WOW64_64KEY, 64 ); 2585 check_key_value( key, "Wine\\Winetest", KEY_WOW64_32KEY, 32 ); 2586 check_key_value( key, "Wow6432Node\\Wine\\Winetest", 0, 32 ); 2587 dw = get_key_value( key, "Wow6432Node\\Wine\\Winetest", KEY_WOW64_64KEY ); 2588 ok( dw == 32 || broken(dw == 64) /* xp64 */, "wrong value %u\n", dw ); 2589 check_key_value( key, "Wow6432Node\\Wine\\Winetest", KEY_WOW64_32KEY, 32 ); 2590 RegCloseKey( key ); 2591 2592 err = RegCreateKeyExA( HKEY_LOCAL_MACHINE, "Software", 0, NULL, 0, 2593 KEY_WOW64_32KEY | KEY_ALL_ACCESS, NULL, &key, NULL ); 2594 ok( err == ERROR_SUCCESS, "RegCreateKeyExA failed: %u\n", err ); 2595 check_key_value( key, "Wine\\Winetest", 0, 32 ); 2596 check_key_value( key, "Wine\\Winetest", KEY_WOW64_64KEY, is_vista ? 64 : 32 ); 2597 check_key_value( key, "Wine\\Winetest", KEY_WOW64_32KEY, 32 ); 2598 check_key_value( key, "Wow6432Node\\Wine\\Winetest", 0, is_vista ? 32 : 0 ); 2599 check_key_value( key, "Wow6432Node\\Wine\\Winetest", KEY_WOW64_64KEY, is_vista ? 64 : 0 ); 2600 check_key_value( key, "Wow6432Node\\Wine\\Winetest", KEY_WOW64_32KEY, is_vista ? 32 : 0 ); 2601 RegCloseKey( key ); 2602 } 2603 else 2604 { 2605 err = RegCreateKeyExA( HKEY_LOCAL_MACHINE, "Software", 0, NULL, 0, 2606 KEY_WOW64_64KEY | KEY_ALL_ACCESS, NULL, &key, NULL ); 2607 ok( err == ERROR_SUCCESS, "RegCreateKeyExA failed: %u\n", err ); 2608 check_key_value( key, "Wine\\Winetest", 0, 64 ); 2609 check_key_value( key, "Wine\\Winetest", KEY_WOW64_64KEY, 64 ); 2610 dw = get_key_value( key, "Wine\\Winetest", KEY_WOW64_32KEY ); 2611 todo_wine ok( dw == 32, "wrong value %u\n", dw ); 2612 check_key_value( key, "Wow6432Node\\Wine\\Winetest", 0, 32 ); 2613 RegCloseKey( key ); 2614 2615 err = RegCreateKeyExA( HKEY_LOCAL_MACHINE, "Software", 0, NULL, 0, 2616 KEY_WOW64_32KEY | KEY_ALL_ACCESS, NULL, &key, NULL ); 2617 ok( err == ERROR_SUCCESS, "RegCreateKeyExA failed: %u\n", err ); 2618 check_key_value( key, "Wine\\Winetest", 0, 32 ); 2619 dw = get_key_value( key, "Wine\\Winetest", KEY_WOW64_64KEY ); 2620 ok( dw == 32 || broken(dw == 64) /* vista */, "wrong value %u\n", dw ); 2621 check_key_value( key, "Wine\\Winetest", KEY_WOW64_32KEY, 32 ); 2622 RegCloseKey( key ); 2623 } 2624 2625 check_key_value( HKEY_LOCAL_MACHINE, "Software\\Wine\\Winetest", 0, ptr_size ); 2626 check_key_value( HKEY_LOCAL_MACHINE, "Software\\Wow6432Node\\Wine\\Winetest", 0, 32 ); 2627 if (ptr_size == 64) 2628 { 2629 /* KEY_WOW64 flags have no effect on 64-bit */ 2630 check_key_value( HKEY_LOCAL_MACHINE, "Software\\Wine\\Winetest", KEY_WOW64_64KEY, 64 ); 2631 check_key_value( HKEY_LOCAL_MACHINE, "Software\\Wine\\Winetest", KEY_WOW64_32KEY, 32 ); 2632 check_key_value( HKEY_LOCAL_MACHINE, "Software\\Wow6432Node\\Wine\\Winetest", KEY_WOW64_64KEY, is_vista ? 64 : 32 ); 2633 check_key_value( HKEY_LOCAL_MACHINE, "Software\\Wow6432Node\\Wine\\Winetest", KEY_WOW64_32KEY, 32 ); 2634 } 2635 else 2636 { 2637 check_key_value( HKEY_LOCAL_MACHINE, "Software\\Wine\\Winetest", KEY_WOW64_64KEY, 64 ); 2638 check_key_value( HKEY_LOCAL_MACHINE, "Software\\Wine\\Winetest", KEY_WOW64_32KEY, 32 ); 2639 check_key_value( HKEY_LOCAL_MACHINE, "Software\\Wow6432Node\\Wine\\Winetest", KEY_WOW64_64KEY, is_vista ? 64 : 32 ); 2640 check_key_value( HKEY_LOCAL_MACHINE, "Software\\Wow6432Node\\Wine\\Winetest", KEY_WOW64_32KEY, 32 ); 2641 } 2642 2643 err = RegCreateKeyExA( HKEY_LOCAL_MACHINE, "Software\\Wow6432Node", 0, NULL, 0, 2644 KEY_ALL_ACCESS, NULL, &key, NULL ); 2645 ok( err == ERROR_SUCCESS, "RegCreateKeyExA failed: %u\n", err ); 2646 check_key_value( key, "Wine\\Winetest", 0, 32 ); 2647 check_key_value( key, "Wine\\Winetest", KEY_WOW64_64KEY, is_vista ? 64 : 32 ); 2648 check_key_value( key, "Wine\\Winetest", KEY_WOW64_32KEY, 32 ); 2649 RegCloseKey( key ); 2650 2651 if (ptr_size == 32) 2652 { 2653 err = RegCreateKeyExA( HKEY_LOCAL_MACHINE, "Software\\Wow6432Node", 0, NULL, 0, 2654 KEY_WOW64_64KEY | KEY_ALL_ACCESS, NULL, &key, NULL ); 2655 ok( err == ERROR_SUCCESS, "RegCreateKeyExA failed: %u\n", err ); 2656 dw = get_key_value( key, "Wine\\Winetest", 0 ); 2657 ok( dw == (is_vista ? 64 : 32) || broken(dw == 32) /* xp64 */, "wrong value %u\n", dw ); 2658 check_key_value( key, "Wine\\Winetest", KEY_WOW64_64KEY, is_vista ? 64 : 32 ); 2659 check_key_value( key, "Wine\\Winetest", KEY_WOW64_32KEY, 32 ); 2660 RegCloseKey( key ); 2661 2662 err = RegCreateKeyExA( HKEY_LOCAL_MACHINE, "Software\\Wow6432Node", 0, NULL, 0, 2663 KEY_WOW64_32KEY | KEY_ALL_ACCESS, NULL, &key, NULL ); 2664 ok( err == ERROR_SUCCESS, "RegCreateKeyExA failed: %u\n", err ); 2665 check_key_value( key, "Wine\\Winetest", 0, 32 ); 2666 check_key_value( key, "Wine\\Winetest", KEY_WOW64_64KEY, is_vista ? 64 : 32 ); 2667 check_key_value( key, "Wine\\Winetest", KEY_WOW64_32KEY, 32 ); 2668 RegCloseKey( key ); 2669 } 2670 2671 err = RegCreateKeyExA( HKEY_LOCAL_MACHINE, "Software\\Wow6432Node\\Wine", 0, NULL, 0, 2672 KEY_ALL_ACCESS, NULL, &key, NULL ); 2673 ok( err == ERROR_SUCCESS, "RegCreateKeyExA failed: %u\n", err ); 2674 check_key_value( key, "Winetest", 0, 32 ); 2675 check_key_value( key, "Winetest", KEY_WOW64_64KEY, is_vista ? 64 : 32 ); 2676 check_key_value( key, "Winetest", KEY_WOW64_32KEY, 32 ); 2677 RegCloseKey( key ); 2678 2679 if (ptr_size == 32) 2680 { 2681 err = RegCreateKeyExA( HKEY_LOCAL_MACHINE, "Software\\Wow6432Node\\Wine", 0, NULL, 0, 2682 KEY_WOW64_64KEY | KEY_ALL_ACCESS, NULL, &key, NULL ); 2683 ok( err == ERROR_SUCCESS, "RegCreateKeyExA failed: %u\n", err ); 2684 dw = get_key_value( key, "Winetest", 0 ); 2685 ok( dw == 32 || (is_vista && dw == 64), "wrong value %u\n", dw ); 2686 check_key_value( key, "Winetest", KEY_WOW64_64KEY, is_vista ? 64 : 32 ); 2687 check_key_value( key, "Winetest", KEY_WOW64_32KEY, 32 ); 2688 RegCloseKey( key ); 2689 2690 err = RegCreateKeyExA( HKEY_LOCAL_MACHINE, "Software\\Wow6432Node\\Wine", 0, NULL, 0, 2691 KEY_WOW64_32KEY | KEY_ALL_ACCESS, NULL, &key, NULL ); 2692 ok( err == ERROR_SUCCESS, "RegCreateKeyExA failed: %u\n", err ); 2693 check_key_value( key, "Winetest", 0, 32 ); 2694 check_key_value( key, "Winetest", KEY_WOW64_64KEY, is_vista ? 64 : 32 ); 2695 check_key_value( key, "Winetest", KEY_WOW64_32KEY, 32 ); 2696 RegCloseKey( key ); 2697 } 2698 2699 err = RegCreateKeyExA( HKEY_LOCAL_MACHINE, "Software\\Wine", 0, NULL, 0, 2700 KEY_ALL_ACCESS, NULL, &key, NULL ); 2701 ok( err == ERROR_SUCCESS, "RegCreateKeyExA failed: %u\n", err ); 2702 check_key_value( key, "Winetest", 0, ptr_size ); 2703 check_key_value( key, "Winetest", KEY_WOW64_64KEY, is_vista ? 64 : ptr_size ); 2704 dw = get_key_value( key, "Winetest", KEY_WOW64_32KEY ); 2705 todo_wine_if (ptr_size != 32) 2706 ok( dw == 32, "wrong value %u\n", dw ); 2707 RegCloseKey( key ); 2708 2709 if (ptr_size == 32) 2710 { 2711 err = RegCreateKeyExA( HKEY_LOCAL_MACHINE, "Software\\Wine", 0, NULL, 0, 2712 KEY_WOW64_64KEY | KEY_ALL_ACCESS, NULL, &key, NULL ); 2713 ok( err == ERROR_SUCCESS, "RegCreateKeyExA failed: %u\n", err ); 2714 dw = get_key_value( key, "Winetest", 0 ); 2715 ok( dw == 64 || broken(dw == 32) /* xp64 */, "wrong value %u\n", dw ); 2716 check_key_value( key, "Winetest", KEY_WOW64_64KEY, 64 ); 2717 dw = get_key_value( key, "Winetest", KEY_WOW64_32KEY ); 2718 todo_wine ok( dw == 32, "wrong value %u\n", dw ); 2719 RegCloseKey( key ); 2720 2721 err = RegCreateKeyExA( HKEY_LOCAL_MACHINE, "Software\\Wine", 0, NULL, 0, 2722 KEY_WOW64_32KEY | KEY_ALL_ACCESS, NULL, &key, NULL ); 2723 ok( err == ERROR_SUCCESS, "RegCreateKeyExA failed: %u\n", err ); 2724 check_key_value( key, "Winetest", 0, 32 ); 2725 check_key_value( key, "Winetest", KEY_WOW64_64KEY, is_vista ? 64 : 32 ); 2726 check_key_value( key, "Winetest", KEY_WOW64_32KEY, 32 ); 2727 RegCloseKey( key ); 2728 } 2729 2730 if (pRegDeleteKeyExA) 2731 { 2732 err = pRegDeleteKeyExA( key32, "", KEY_WOW64_32KEY, 0 ); 2733 ok( err == ERROR_SUCCESS, "RegDeleteKey failed: %u\n", err ); 2734 err = pRegDeleteKeyExA( key64, "", KEY_WOW64_64KEY, 0 ); 2735 ok( err == ERROR_SUCCESS, "RegDeleteKey failed: %u\n", err ); 2736 pRegDeleteKeyExA( key64, "", KEY_WOW64_64KEY, 0 ); 2737 pRegDeleteKeyExA( root64, "", KEY_WOW64_64KEY, 0 ); 2738 } 2739 else 2740 { 2741 err = RegDeleteKeyA( key32, "" ); 2742 ok( err == ERROR_SUCCESS, "RegDeleteKey failed: %u\n", err ); 2743 err = RegDeleteKeyA( key64, "" ); 2744 ok( err == ERROR_SUCCESS, "RegDeleteKey failed: %u\n", err ); 2745 RegDeleteKeyA( key64, "" ); 2746 RegDeleteKeyA( root64, "" ); 2747 } 2748 RegCloseKey( key32 ); 2749 RegCloseKey( key64 ); 2750 RegCloseKey( root32 ); 2751 RegCloseKey( root64 ); 2752 2753 /* open key in native bit mode */ 2754 err = RegOpenKeyExA(HKEY_CLASSES_ROOT, "Interface", 0, KEY_ALL_ACCESS, &native); 2755 ok(err == ERROR_SUCCESS, "got %i\n", err); 2756 2757 pRegDeleteKeyExA(native, "AWineTest", 0, 0); 2758 2759 /* write subkey in opposite bit mode */ 2760 err = RegOpenKeyExA(HKEY_CLASSES_ROOT, "Interface", 0, KEY_ALL_ACCESS | opposite, &op_key); 2761 ok(err == ERROR_SUCCESS, "got %i\n", err); 2762 2763 err = RegCreateKeyExA(op_key, "AWineTest", 0, NULL, 0, KEY_ALL_ACCESS | opposite, 2764 NULL, &key, NULL); 2765 ok(err == ERROR_SUCCESS || err == ERROR_ACCESS_DENIED, "got %i\n", err); 2766 if(err != ERROR_SUCCESS){ 2767 win_skip("Can't write to registry\n"); 2768 RegCloseKey(op_key); 2769 RegCloseKey(native); 2770 return; 2771 } 2772 RegCloseKey(key); 2773 2774 /* verify subkey is not present in native mode */ 2775 err = RegOpenKeyExA(native, "AWineTest", 0, KEY_ALL_ACCESS, &key); 2776 ok(err == ERROR_FILE_NOT_FOUND || 2777 broken(err == ERROR_SUCCESS), /* before Win7, HKCR is reflected instead of redirected */ 2778 "got %i\n", err); 2779 2780 err = pRegDeleteKeyExA(op_key, "AWineTest", opposite, 0); 2781 ok(err == ERROR_SUCCESS, "got %i\n", err); 2782 2783 RegCloseKey(op_key); 2784 RegCloseKey(native); 2785 } 2786 2787 static void test_classesroot(void) 2788 { 2789 HKEY hkey, hklm, hkcr, hkeysub1, hklmsub1, hkcrsub1, hklmsub2, hkcrsub2; 2790 DWORD size = 8; 2791 DWORD type = REG_SZ; 2792 static CHAR buffer[8]; 2793 LONG res; 2794 2795 /* create a key in the user's classes */ 2796 if (!RegOpenKeyA( HKEY_CURRENT_USER, "Software\\Classes\\WineTestCls", &hkey )) 2797 { 2798 delete_key( hkey ); 2799 RegCloseKey( hkey ); 2800 } 2801 res = RegCreateKeyExA( HKEY_CURRENT_USER, "Software\\Classes\\WineTestCls", 0, NULL, 0, 2802 KEY_QUERY_VALUE|KEY_SET_VALUE, NULL, &hkey, NULL ); 2803 if (res == ERROR_ACCESS_DENIED) 2804 { 2805 skip("not enough privileges to add a user class\n"); 2806 return; 2807 } 2808 ok(!IS_HKCR(hkey), "hkcr mask set in %p\n", hkey); 2809 2810 /* try to open that key in hkcr */ 2811 res = RegOpenKeyExA( HKEY_CLASSES_ROOT, "WineTestCls", 0, 2812 KEY_QUERY_VALUE|KEY_SET_VALUE, &hkcr ); 2813 todo_wine ok(res == ERROR_SUCCESS || 2814 broken(res == ERROR_FILE_NOT_FOUND /* WinNT */), 2815 "test key not found in hkcr: %d\n", res); 2816 if (res) 2817 { 2818 skip("HKCR key merging not supported\n"); 2819 delete_key( hkey ); 2820 RegCloseKey( hkey ); 2821 return; 2822 } 2823 2824 todo_wine ok(IS_HKCR(hkcr), "hkcr mask not set in %p\n", hkcr); 2825 2826 /* set a value in user's classes */ 2827 res = RegSetValueExA(hkey, "val1", 0, REG_SZ, (const BYTE *)"user", sizeof("user")); 2828 ok(res == ERROR_SUCCESS, "RegSetValueExA failed: %d, GLE=%x\n", res, GetLastError()); 2829 2830 /* try to find the value in hkcr */ 2831 res = RegQueryValueExA(hkcr, "val1", NULL, &type, (LPBYTE)buffer, &size); 2832 ok(res == ERROR_SUCCESS, "RegQueryValueExA failed: %d\n", res); 2833 ok(!strcmp( buffer, "user" ), "value set to '%s'\n", buffer ); 2834 2835 /* modify the value in hkcr */ 2836 res = RegSetValueExA(hkcr, "val1", 0, REG_SZ, (const BYTE *)"hkcr", sizeof("hkcr")); 2837 ok(res == ERROR_SUCCESS, "RegSetValueExA failed: %d, GLE=%x\n", res, GetLastError()); 2838 2839 /* check if the value is also modified in user's classes */ 2840 res = RegQueryValueExA(hkey, "val1", NULL, &type, (LPBYTE)buffer, &size); 2841 ok(res == ERROR_SUCCESS, "RegQueryValueExA failed: %d, GLE=%x\n", res, GetLastError()); 2842 ok(!strcmp( buffer, "hkcr" ), "value set to '%s'\n", buffer ); 2843 2844 /* set a value in hkcr */ 2845 res = RegSetValueExA(hkcr, "val0", 0, REG_SZ, (const BYTE *)"hkcr", sizeof("hkcr")); 2846 ok(res == ERROR_SUCCESS, "RegSetValueExA failed: %d, GLE=%x\n", res, GetLastError()); 2847 2848 /* try to find the value in user's classes */ 2849 res = RegQueryValueExA(hkey, "val0", NULL, &type, (LPBYTE)buffer, &size); 2850 ok(res == ERROR_SUCCESS, "RegQueryValueExA failed: %d\n", res); 2851 ok(!strcmp( buffer, "hkcr" ), "value set to '%s'\n", buffer ); 2852 2853 /* modify the value in user's classes */ 2854 res = RegSetValueExA(hkey, "val0", 0, REG_SZ, (const BYTE *)"user", sizeof("user")); 2855 ok(res == ERROR_SUCCESS, "RegSetValueExA failed: %d, GLE=%x\n", res, GetLastError()); 2856 2857 /* check if the value is also modified in hkcr */ 2858 res = RegQueryValueExA(hkcr, "val0", NULL, &type, (LPBYTE)buffer, &size); 2859 ok(res == ERROR_SUCCESS, "RegQueryValueExA failed: %d, GLE=%x\n", res, GetLastError()); 2860 ok(!strcmp( buffer, "user" ), "value set to '%s'\n", buffer ); 2861 2862 /* cleanup */ 2863 delete_key( hkey ); 2864 delete_key( hkcr ); 2865 RegCloseKey( hkey ); 2866 RegCloseKey( hkcr ); 2867 2868 /* create a key in the hklm classes */ 2869 if (!RegOpenKeyA( HKEY_LOCAL_MACHINE, "Software\\Classes\\WineTestCls", &hklm )) 2870 { 2871 delete_key( hklm ); 2872 RegCloseKey( hklm ); 2873 } 2874 res = RegCreateKeyExA( HKEY_LOCAL_MACHINE, "Software\\Classes\\WineTestCls", 0, NULL, REG_OPTION_NON_VOLATILE, 2875 KEY_ALL_ACCESS, NULL, &hklm, NULL ); 2876 if (res == ERROR_ACCESS_DENIED) 2877 { 2878 skip("not enough privileges to add a system class\n"); 2879 return; 2880 } 2881 ok(!IS_HKCR(hklm), "hkcr mask set in %p\n", hklm); 2882 2883 /* try to open that key in hkcr */ 2884 res = RegOpenKeyExA( HKEY_CLASSES_ROOT, "WineTestCls", 0, 2885 KEY_QUERY_VALUE|KEY_SET_VALUE, &hkcr ); 2886 ok(res == ERROR_SUCCESS, 2887 "test key not found in hkcr: %d\n", res); 2888 ok(IS_HKCR(hkcr), "hkcr mask not set in %p\n", hkcr); 2889 if (res) 2890 { 2891 delete_key( hklm ); 2892 RegCloseKey( hklm ); 2893 return; 2894 } 2895 2896 /* set a value in hklm classes */ 2897 res = RegSetValueExA(hklm, "val2", 0, REG_SZ, (const BYTE *)"hklm", sizeof("hklm")); 2898 ok(res == ERROR_SUCCESS, "RegSetValueExA failed: %d, GLE=%x\n", res, GetLastError()); 2899 2900 /* try to find the value in hkcr */ 2901 res = RegQueryValueExA(hkcr, "val2", NULL, &type, (LPBYTE)buffer, &size); 2902 ok(res == ERROR_SUCCESS, "RegQueryValueExA failed: %d\n", res); 2903 ok(!strcmp( buffer, "hklm" ), "value set to '%s'\n", buffer ); 2904 2905 /* modify the value in hkcr */ 2906 res = RegSetValueExA(hkcr, "val2", 0, REG_SZ, (const BYTE *)"hkcr", sizeof("hkcr")); 2907 ok(res == ERROR_SUCCESS, "RegSetValueExA failed: %d, GLE=%x\n", res, GetLastError()); 2908 2909 /* check that the value is modified in hklm classes */ 2910 res = RegQueryValueExA(hklm, "val2", NULL, &type, (LPBYTE)buffer, &size); 2911 ok(res == ERROR_SUCCESS, "RegQueryValueExA failed: %d, GLE=%x\n", res, GetLastError()); 2912 ok(!strcmp( buffer, "hkcr" ), "value set to '%s'\n", buffer ); 2913 2914 if (RegCreateKeyExA( HKEY_CURRENT_USER, "Software\\Classes\\WineTestCls", 0, NULL, 0, 2915 KEY_QUERY_VALUE|KEY_SET_VALUE, NULL, &hkey, NULL )) return; 2916 ok(!IS_HKCR(hkey), "hkcr mask set in %p\n", hkey); 2917 2918 /* try to open that key in hkcr */ 2919 res = RegOpenKeyExA( HKEY_CLASSES_ROOT, "WineTestCls", 0, 2920 KEY_QUERY_VALUE|KEY_SET_VALUE, &hkcr ); 2921 ok(res == ERROR_SUCCESS, 2922 "test key not found in hkcr: %d\n", res); 2923 ok(IS_HKCR(hkcr), "hkcr mask not set in %p\n", hkcr); 2924 2925 /* set a value in user's classes */ 2926 res = RegSetValueExA(hkey, "val2", 0, REG_SZ, (const BYTE *)"user", sizeof("user")); 2927 ok(res == ERROR_SUCCESS, "RegSetValueExA failed: %d, GLE=%x\n", res, GetLastError()); 2928 2929 /* try to find the value in hkcr */ 2930 res = RegQueryValueExA(hkcr, "val2", NULL, &type, (LPBYTE)buffer, &size); 2931 ok(res == ERROR_SUCCESS, "RegQueryValueExA failed: %d\n", res); 2932 ok(!strcmp( buffer, "user" ), "value set to '%s'\n", buffer ); 2933 2934 /* modify the value in hklm */ 2935 res = RegSetValueExA(hklm, "val2", 0, REG_SZ, (const BYTE *)"hklm", sizeof("hklm")); 2936 ok(res == ERROR_SUCCESS, "RegSetValueExA failed: %d, GLE=%x\n", res, GetLastError()); 2937 2938 /* check that the value is not overwritten in hkcr or user's classes */ 2939 res = RegQueryValueExA(hkcr, "val2", NULL, &type, (LPBYTE)buffer, &size); 2940 ok(res == ERROR_SUCCESS, "RegQueryValueExA failed: %d\n", res); 2941 ok(!strcmp( buffer, "user" ), "value set to '%s'\n", buffer ); 2942 res = RegQueryValueExA(hkey, "val2", NULL, &type, (LPBYTE)buffer, &size); 2943 ok(res == ERROR_SUCCESS, "RegQueryValueExA failed: %d, GLE=%x\n", res, GetLastError()); 2944 ok(!strcmp( buffer, "user" ), "value set to '%s'\n", buffer ); 2945 2946 /* modify the value in hkcr */ 2947 res = RegSetValueExA(hkcr, "val2", 0, REG_SZ, (const BYTE *)"hkcr", sizeof("hkcr")); 2948 ok(res == ERROR_SUCCESS, "RegSetValueExA failed: %d, GLE=%x\n", res, GetLastError()); 2949 2950 /* check that the value is overwritten in hklm and user's classes */ 2951 res = RegQueryValueExA(hkcr, "val2", NULL, &type, (LPBYTE)buffer, &size); 2952 ok(res == ERROR_SUCCESS, "RegQueryValueExA failed: %d\n", res); 2953 ok(!strcmp( buffer, "hkcr" ), "value set to '%s'\n", buffer ); 2954 res = RegQueryValueExA(hkey, "val2", NULL, &type, (LPBYTE)buffer, &size); 2955 ok(res == ERROR_SUCCESS, "RegQueryValueExA failed: %d, GLE=%x\n", res, GetLastError()); 2956 ok(!strcmp( buffer, "hkcr" ), "value set to '%s'\n", buffer ); 2957 2958 /* create a subkey in hklm */ 2959 if (RegCreateKeyExA( hklm, "subkey1", 0, NULL, 0, 2960 KEY_QUERY_VALUE|KEY_SET_VALUE, NULL, &hklmsub1, NULL )) return; 2961 ok(!IS_HKCR(hklmsub1), "hkcr mask set in %p\n", hklmsub1); 2962 /* try to open that subkey in hkcr */ 2963 res = RegOpenKeyExA( hkcr, "subkey1", 0, KEY_QUERY_VALUE|KEY_SET_VALUE, &hkcrsub1 ); 2964 ok(res == ERROR_SUCCESS, "test key not found in hkcr: %d\n", res); 2965 ok(IS_HKCR(hkcrsub1), "hkcr mask not set in %p\n", hkcrsub1); 2966 2967 /* set a value in hklm classes */ 2968 res = RegSetValueExA(hklmsub1, "subval1", 0, REG_SZ, (const BYTE *)"hklm", sizeof("hklm")); 2969 ok(res == ERROR_SUCCESS, "RegSetValueExA failed: %d, GLE=%x\n", res, GetLastError()); 2970 2971 /* try to find the value in hkcr */ 2972 res = RegQueryValueExA(hkcrsub1, "subval1", NULL, &type, (LPBYTE)buffer, &size); 2973 ok(res == ERROR_SUCCESS, "RegQueryValueExA failed: %d\n", res); 2974 ok(!strcmp( buffer, "hklm" ), "value set to '%s'\n", buffer ); 2975 2976 /* modify the value in hkcr */ 2977 res = RegSetValueExA(hkcrsub1, "subval1", 0, REG_SZ, (const BYTE *)"hkcr", sizeof("hkcr")); 2978 ok(res == ERROR_SUCCESS, "RegSetValueExA failed: %d, GLE=%x\n", res, GetLastError()); 2979 2980 /* check that the value is modified in hklm classes */ 2981 res = RegQueryValueExA(hklmsub1, "subval1", NULL, &type, (LPBYTE)buffer, &size); 2982 ok(res == ERROR_SUCCESS, "RegQueryValueExA failed: %d, GLE=%x\n", res, GetLastError()); 2983 ok(!strcmp( buffer, "hkcr" ), "value set to '%s'\n", buffer ); 2984 2985 /* create a subkey in user's classes */ 2986 if (RegCreateKeyExA( hkey, "subkey1", 0, NULL, 0, 2987 KEY_QUERY_VALUE|KEY_SET_VALUE, NULL, &hkeysub1, NULL )) return; 2988 ok(!IS_HKCR(hkeysub1), "hkcr mask set in %p\n", hkeysub1); 2989 2990 /* set a value in user's classes */ 2991 res = RegSetValueExA(hkeysub1, "subval1", 0, REG_SZ, (const BYTE *)"user", sizeof("user")); 2992 ok(res == ERROR_SUCCESS, "RegSetValueExA failed: %d, GLE=%x\n", res, GetLastError()); 2993 2994 /* try to find the value in hkcr */ 2995 res = RegQueryValueExA(hkcrsub1, "subval1", NULL, &type, (LPBYTE)buffer, &size); 2996 ok(res == ERROR_SUCCESS, "RegQueryValueExA failed: %d\n", res); 2997 ok(!strcmp( buffer, "user" ), "value set to '%s'\n", buffer ); 2998 2999 /* modify the value in hklm */ 3000 res = RegSetValueExA(hklmsub1, "subval1", 0, REG_SZ, (const BYTE *)"hklm", sizeof("hklm")); 3001 ok(res == ERROR_SUCCESS, "RegSetValueExA failed: %d, GLE=%x\n", res, GetLastError()); 3002 3003 /* check that the value is not overwritten in hkcr or user's classes */ 3004 res = RegQueryValueExA(hkcrsub1, "subval1", NULL, &type, (LPBYTE)buffer, &size); 3005 ok(res == ERROR_SUCCESS, "RegQueryValueExA failed: %d\n", res); 3006 ok(!strcmp( buffer, "user" ), "value set to '%s'\n", buffer ); 3007 res = RegQueryValueExA(hkeysub1, "subval1", NULL, &type, (LPBYTE)buffer, &size); 3008 ok(res == ERROR_SUCCESS, "RegQueryValueExA failed: %d, GLE=%x\n", res, GetLastError()); 3009 ok(!strcmp( buffer, "user" ), "value set to '%s'\n", buffer ); 3010 3011 /* modify the value in hkcr */ 3012 res = RegSetValueExA(hkcrsub1, "subval1", 0, REG_SZ, (const BYTE *)"hkcr", sizeof("hkcr")); 3013 ok(res == ERROR_SUCCESS, "RegSetValueExA failed: %d, GLE=%x\n", res, GetLastError()); 3014 3015 /* check that the value is not overwritten in hklm, but in user's classes */ 3016 res = RegQueryValueExA(hklmsub1, "subval1", NULL, &type, (LPBYTE)buffer, &size); 3017 ok(res == ERROR_SUCCESS, "RegQueryValueExA failed: %d\n", res); 3018 ok(!strcmp( buffer, "hklm" ), "value set to '%s'\n", buffer ); 3019 res = RegQueryValueExA(hkeysub1, "subval1", NULL, &type, (LPBYTE)buffer, &size); 3020 ok(res == ERROR_SUCCESS, "RegQueryValueExA failed: %d, GLE=%x\n", res, GetLastError()); 3021 ok(!strcmp( buffer, "hkcr" ), "value set to '%s'\n", buffer ); 3022 3023 /* new subkey in hkcr */ 3024 if (RegCreateKeyExA( hkcr, "subkey2", 0, NULL, 0, 3025 KEY_QUERY_VALUE|KEY_SET_VALUE, NULL, &hkcrsub2, NULL )) return; 3026 ok(IS_HKCR(hkcrsub2), "hkcr mask not set in %p\n", hkcrsub2); 3027 res = RegSetValueExA(hkcrsub2, "subval1", 0, REG_SZ, (const BYTE *)"hkcr", sizeof("hkcr")); 3028 ok(res == ERROR_SUCCESS, "RegSetValueExA failed: %d, GLE=%x\n", res, GetLastError()); 3029 3030 /* try to open that new subkey in user's classes and hklm */ 3031 res = RegOpenKeyExA( hkey, "subkey2", 0, KEY_QUERY_VALUE|KEY_SET_VALUE, &hklmsub2 ); 3032 ok(res != ERROR_SUCCESS, "test key found in user's classes: %d\n", res); 3033 hklmsub2 = 0; 3034 res = RegOpenKeyExA( hklm, "subkey2", 0, KEY_QUERY_VALUE|KEY_SET_VALUE, &hklmsub2 ); 3035 ok(res == ERROR_SUCCESS, "test key not found in hklm: %d\n", res); 3036 ok(!IS_HKCR(hklmsub2), "hkcr mask set in %p\n", hklmsub2); 3037 3038 /* check that the value is present in hklm */ 3039 res = RegQueryValueExA(hklmsub2, "subval1", NULL, &type, (LPBYTE)buffer, &size); 3040 ok(res == ERROR_SUCCESS, "RegQueryValueExA failed: %d\n", res); 3041 ok(!strcmp( buffer, "hkcr" ), "value set to '%s'\n", buffer ); 3042 3043 /* cleanup */ 3044 RegCloseKey( hkeysub1 ); 3045 RegCloseKey( hklmsub1 ); 3046 3047 /* delete subkey1 from hkcr (should point at user's classes) */ 3048 res = RegDeleteKeyA(hkcr, "subkey1"); 3049 ok(res == ERROR_SUCCESS, "RegDeleteKey failed: %d\n", res); 3050 3051 /* confirm key was removed in hkey but not hklm */ 3052 res = RegOpenKeyExA(hkey, "subkey1", 0, KEY_READ, &hkeysub1); 3053 ok(res == ERROR_FILE_NOT_FOUND, "test key found in user's classes: %d\n", res); 3054 res = RegOpenKeyExA(hklm, "subkey1", 0, KEY_READ, &hklmsub1); 3055 ok(res == ERROR_SUCCESS, "test key not found in hklm: %d\n", res); 3056 ok(!IS_HKCR(hklmsub1), "hkcr mask set in %p\n", hklmsub1); 3057 3058 /* delete subkey1 from hkcr again (which should now point at hklm) */ 3059 res = RegDeleteKeyA(hkcr, "subkey1"); 3060 ok(res == ERROR_SUCCESS, "RegDeleteKey failed: %d\n", res); 3061 3062 /* confirm hkey was removed in hklm */ 3063 RegCloseKey( hklmsub1 ); 3064 res = RegOpenKeyExA(hklm, "subkey1", 0, KEY_READ, &hklmsub1); 3065 ok(res == ERROR_FILE_NOT_FOUND, "test key found in hklm: %d\n", res); 3066 3067 /* final cleanup */ 3068 delete_key( hkey ); 3069 delete_key( hklm ); 3070 delete_key( hkcr ); 3071 delete_key( hkeysub1 ); 3072 delete_key( hklmsub1 ); 3073 delete_key( hkcrsub1 ); 3074 delete_key( hklmsub2 ); 3075 delete_key( hkcrsub2 ); 3076 RegCloseKey( hkey ); 3077 RegCloseKey( hklm ); 3078 RegCloseKey( hkcr ); 3079 RegCloseKey( hkeysub1 ); 3080 RegCloseKey( hklmsub1 ); 3081 RegCloseKey( hkcrsub1 ); 3082 RegCloseKey( hklmsub2 ); 3083 RegCloseKey( hkcrsub2 ); 3084 } 3085 3086 static void test_classesroot_enum(void) 3087 { 3088 HKEY hkcu=0, hklm=0, hkcr=0, hkcusub[2]={0}, hklmsub[2]={0}; 3089 DWORD size; 3090 static CHAR buffer[2]; 3091 LONG res; 3092 3093 /* prepare initial testing env in HKCU */ 3094 if (!RegOpenKeyA( HKEY_CURRENT_USER, "Software\\Classes\\WineTestCls", &hkcu )) 3095 { 3096 delete_key( hkcu ); 3097 RegCloseKey( hkcu ); 3098 } 3099 res = RegCreateKeyExA( HKEY_CURRENT_USER, "Software\\Classes\\WineTestCls", 0, NULL, 0, 3100 KEY_SET_VALUE|KEY_ENUMERATE_SUB_KEYS, NULL, &hkcu, NULL ); 3101 3102 if (res != ERROR_SUCCESS) 3103 { 3104 skip("failed to add a user class\n"); 3105 return; 3106 } 3107 3108 res = RegOpenKeyA( HKEY_CLASSES_ROOT, "WineTestCls", &hkcr ); 3109 todo_wine ok(res == ERROR_SUCCESS || 3110 broken(res == ERROR_FILE_NOT_FOUND /* WinNT */), 3111 "test key not found in hkcr: %d\n", res); 3112 if (res) 3113 { 3114 skip("HKCR key merging not supported\n"); 3115 delete_key( hkcu ); 3116 RegCloseKey( hkcu ); 3117 return; 3118 } 3119 3120 res = RegSetValueExA( hkcu, "X", 0, REG_SZ, (const BYTE *) "AA", 3 ); 3121 ok(res == ERROR_SUCCESS, "RegSetValueExA failed: %d\n", res); 3122 res = RegSetValueExA( hkcu, "Y", 0, REG_SZ, (const BYTE *) "B", 2 ); 3123 ok(res == ERROR_SUCCESS, "RegSetValueExA failed: %d\n", res); 3124 res = RegCreateKeyA( hkcu, "A", &hkcusub[0] ); 3125 ok(res == ERROR_SUCCESS, "RegCreateKeyA failed: %d\n", res); 3126 res = RegCreateKeyA( hkcu, "B", &hkcusub[1] ); 3127 ok(res == ERROR_SUCCESS, "RegCreateKeyA failed: %d\n", res); 3128 3129 /* test on values in HKCU */ 3130 size = sizeof(buffer); 3131 res = RegEnumValueA( hkcr, 0, buffer, &size, NULL, NULL, NULL, NULL ); 3132 ok(res == ERROR_SUCCESS, "RegEnumValueA failed: %d\n", res ); 3133 ok(!strcmp( buffer, "X" ), "expected 'X', got '%s'\n", buffer); 3134 size = sizeof(buffer); 3135 res = RegEnumValueA( hkcr, 1, buffer, &size, NULL, NULL, NULL, NULL ); 3136 ok(res == ERROR_SUCCESS, "RegEnumValueA failed: %d\n", res ); 3137 ok(!strcmp( buffer, "Y" ), "expected 'Y', got '%s'\n", buffer); 3138 size = sizeof(buffer); 3139 res = RegEnumValueA( hkcr, 2, buffer, &size, NULL, NULL, NULL, NULL ); 3140 ok(res == ERROR_NO_MORE_ITEMS, "expected ERROR_NO_MORE_ITEMS, got %d\n", res ); 3141 3142 res = RegEnumKeyA( hkcr, 0, buffer, size ); 3143 ok(res == ERROR_SUCCESS, "RegEnumKey failed: %d\n", res ); 3144 ok(!strcmp( buffer, "A" ), "expected 'A', got '%s'\n", buffer); 3145 res = RegEnumKeyA( hkcr, 1, buffer, size ); 3146 ok(res == ERROR_SUCCESS, "RegEnumKey failed: %d\n", res ); 3147 ok(!strcmp( buffer, "B" ), "expected 'B', got '%s'\n", buffer); 3148 res = RegEnumKeyA( hkcr, 2, buffer, size ); 3149 ok(res == ERROR_NO_MORE_ITEMS, "expected ERROR_NO_MORE_ITEMS, got %d\n", res ); 3150 3151 /* prepare test env in HKLM */ 3152 if (!RegOpenKeyA( HKEY_LOCAL_MACHINE, "Software\\Classes\\WineTestCls", &hklm )) 3153 { 3154 delete_key( hklm ); 3155 RegCloseKey( hklm ); 3156 } 3157 3158 res = RegCreateKeyExA( HKEY_LOCAL_MACHINE, "Software\\Classes\\WineTestCls", 0, NULL, 0, 3159 KEY_SET_VALUE|KEY_ENUMERATE_SUB_KEYS, NULL, &hklm, NULL ); 3160 3161 if (res == ERROR_ACCESS_DENIED) 3162 { 3163 RegCloseKey( hkcusub[0] ); 3164 RegCloseKey( hkcusub[1] ); 3165 delete_key( hkcu ); 3166 RegCloseKey( hkcu ); 3167 RegCloseKey( hkcr ); 3168 skip("not enough privileges to add a system class\n"); 3169 return; 3170 } 3171 3172 res = RegSetValueExA( hklm, "X", 0, REG_SZ, (const BYTE *) "AB", 3 ); 3173 ok(res == ERROR_SUCCESS, "RegSetValueExA failed: %d\n", res); 3174 res = RegSetValueExA( hklm, "Z", 0, REG_SZ, (const BYTE *) "C", 2 ); 3175 ok(res == ERROR_SUCCESS, "RegSetValueExA failed: %d\n", res); 3176 res = RegCreateKeyA( hklm, "A", &hklmsub[0] ); 3177 ok(res == ERROR_SUCCESS, "RegCreateKeyA failed: %d\n", res); 3178 res = RegCreateKeyA( hklm, "C", &hklmsub[1] ); 3179 ok(res == ERROR_SUCCESS, "RegCreateKeyA failed: %d\n", res); 3180 3181 /* test on values/keys in both HKCU and HKLM */ 3182 size = sizeof(buffer); 3183 res = RegEnumValueA( hkcr, 0, buffer, &size, NULL, NULL, NULL, NULL ); 3184 ok(res == ERROR_SUCCESS, "RegEnumValueA failed: %d\n", res ); 3185 ok(!strcmp( buffer, "X" ), "expected 'X', got '%s'\n", buffer); 3186 size = sizeof(buffer); 3187 res = RegEnumValueA( hkcr, 1, buffer, &size, NULL, NULL, NULL, NULL ); 3188 ok(res == ERROR_SUCCESS, "RegEnumValueA failed: %d\n", res ); 3189 ok(!strcmp( buffer, "Y" ), "expected 'Y', got '%s'\n", buffer); 3190 size = sizeof(buffer); 3191 res = RegEnumValueA( hkcr, 2, buffer, &size, NULL, NULL, NULL, NULL ); 3192 ok(res == ERROR_SUCCESS, "RegEnumValueA failed: %d\n", res ); 3193 ok(!strcmp( buffer, "Z" ), "expected 'Z', got '%s'\n", buffer); 3194 size = sizeof(buffer); 3195 res = RegEnumValueA( hkcr, 3, buffer, &size, NULL, NULL, NULL, NULL ); 3196 ok(res == ERROR_NO_MORE_ITEMS, "expected ERROR_NO_MORE_ITEMS, got %d\n", res ); 3197 3198 res = RegEnumKeyA( hkcr, 0, buffer, size ); 3199 ok(res == ERROR_SUCCESS, "RegEnumKey failed: %d\n", res ); 3200 ok(!strcmp( buffer, "A" ), "expected 'A', got '%s'\n", buffer); 3201 res = RegEnumKeyA( hkcr, 1, buffer, size ); 3202 ok(res == ERROR_SUCCESS, "RegEnumKey failed: %d\n", res ); 3203 ok(!strcmp( buffer, "B" ), "expected 'B', got '%s'\n", buffer); 3204 res = RegEnumKeyA( hkcr, 2, buffer, size ); 3205 ok(res == ERROR_SUCCESS, "RegEnumKey failed: %d\n", res ); 3206 ok(!strcmp( buffer, "C" ), "expected 'C', got '%s'\n", buffer); 3207 res = RegEnumKeyA( hkcr, 3, buffer, size ); 3208 ok(res == ERROR_NO_MORE_ITEMS, "expected ERROR_NO_MORE_ITEMS, got %d\n", res ); 3209 3210 /* delete values/keys from HKCU to test only on HKLM */ 3211 RegCloseKey( hkcusub[0] ); 3212 RegCloseKey( hkcusub[1] ); 3213 delete_key( hkcu ); 3214 RegCloseKey( hkcu ); 3215 3216 size = sizeof(buffer); 3217 res = RegEnumValueA( hkcr, 0, buffer, &size, NULL, NULL, NULL, NULL ); 3218 ok(res == ERROR_KEY_DELETED || 3219 res == ERROR_NO_SYSTEM_RESOURCES, /* Windows XP */ 3220 "expected ERROR_KEY_DELETED, got %d\n", res); 3221 size = sizeof(buffer); 3222 res = RegEnumKeyA( hkcr, 0, buffer, size ); 3223 ok(res == ERROR_KEY_DELETED || 3224 res == ERROR_NO_SYSTEM_RESOURCES, /* Windows XP */ 3225 "expected ERROR_KEY_DELETED, got %d\n", res); 3226 3227 /* reopen HKCR handle */ 3228 RegCloseKey( hkcr ); 3229 res = RegOpenKeyA( HKEY_CLASSES_ROOT, "WineTestCls", &hkcr ); 3230 ok(res == ERROR_SUCCESS, "test key not found in hkcr: %d\n", res); 3231 if (res) goto cleanup; 3232 3233 /* test on values/keys in HKLM */ 3234 size = sizeof(buffer); 3235 res = RegEnumValueA( hkcr, 0, buffer, &size, NULL, NULL, NULL, NULL ); 3236 ok(res == ERROR_SUCCESS, "RegEnumValueA failed: %d\n", res ); 3237 ok(!strcmp( buffer, "X" ), "expected 'X', got '%s'\n", buffer); 3238 size = sizeof(buffer); 3239 res = RegEnumValueA( hkcr, 1, buffer, &size, NULL, NULL, NULL, NULL ); 3240 ok(res == ERROR_SUCCESS, "RegEnumValueA failed: %d\n", res ); 3241 ok(!strcmp( buffer, "Z" ), "expected 'Z', got '%s'\n", buffer); 3242 size = sizeof(buffer); 3243 res = RegEnumValueA( hkcr, 2, buffer, &size, NULL, NULL, NULL, NULL ); 3244 ok(res == ERROR_NO_MORE_ITEMS, "expected ERROR_NO_MORE_ITEMS, got %d\n", res ); 3245 3246 res = RegEnumKeyA( hkcr, 0, buffer, size ); 3247 ok(res == ERROR_SUCCESS, "RegEnumKey failed: %d\n", res ); 3248 ok(!strcmp( buffer, "A" ), "expected 'A', got '%s'\n", buffer); 3249 res = RegEnumKeyA( hkcr, 1, buffer, size ); 3250 ok(res == ERROR_SUCCESS, "RegEnumKey failed: %d\n", res ); 3251 ok(!strcmp( buffer, "C" ), "expected 'C', got '%s'\n", buffer); 3252 res = RegEnumKeyA( hkcr, 2, buffer, size ); 3253 ok(res == ERROR_NO_MORE_ITEMS, "expected ERROR_NO_MORE_ITEMS, got %d\n", res ); 3254 3255 cleanup: 3256 RegCloseKey( hklmsub[0] ); 3257 RegCloseKey( hklmsub[1] ); 3258 delete_key( hklm ); 3259 RegCloseKey( hklm ); 3260 RegCloseKey( hkcr ); 3261 } 3262 3263 static void test_classesroot_mask(void) 3264 { 3265 HKEY hkey; 3266 LSTATUS res; 3267 3268 res = RegOpenKeyA( HKEY_CLASSES_ROOT, "CLSID", &hkey ); 3269 ok(res == ERROR_SUCCESS, "RegOpenKeyA failed: %d\n", res); 3270 todo_wine ok(IS_HKCR(hkey) || broken(!IS_HKCR(hkey)) /* WinNT */, 3271 "hkcr mask not set in %p\n", hkey); 3272 RegCloseKey( hkey ); 3273 3274 res = RegOpenKeyA( HKEY_CURRENT_USER, "Software", &hkey ); 3275 ok(res == ERROR_SUCCESS, "RegOpenKeyA failed: %d\n", res); 3276 ok(!IS_HKCR(hkey), "hkcr mask set in %p\n", hkey); 3277 RegCloseKey( hkey ); 3278 3279 res = RegOpenKeyA( HKEY_LOCAL_MACHINE, "Software", &hkey ); 3280 ok(res == ERROR_SUCCESS, "RegOpenKeyA failed: %d\n", res); 3281 ok(!IS_HKCR(hkey), "hkcr mask set in %p\n", hkey); 3282 RegCloseKey( hkey ); 3283 3284 res = RegOpenKeyA( HKEY_USERS, ".Default", &hkey ); 3285 ok(res == ERROR_SUCCESS, "RegOpenKeyA failed: %d\n", res); 3286 ok(!IS_HKCR(hkey), "hkcr mask set in %p\n", hkey); 3287 RegCloseKey( hkey ); 3288 3289 res = RegOpenKeyA( HKEY_CURRENT_CONFIG, "Software", &hkey ); 3290 ok(res == ERROR_SUCCESS, "RegOpenKeyA failed: %d\n", res); 3291 ok(!IS_HKCR(hkey), "hkcr mask set in %p\n", hkey); 3292 RegCloseKey( hkey ); 3293 } 3294 3295 static void test_perflib_key(void) 3296 { 3297 DWORD size; 3298 LONG ret; 3299 HKEY key; 3300 3301 ret = RegOpenKeyA(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Perflib\\009", &key); 3302 ok(ret == ERROR_SUCCESS, "RegOpenKeyA failed with error %u\n", ret); 3303 3304 ret = RegQueryValueExA(key, "Counter", NULL, NULL, NULL, &size); 3305 if (ret != ERROR_SUCCESS) 3306 { 3307 skip("Perflib\\009\\Counter does not exist, skipping perflib test\n"); 3308 goto done; 3309 } 3310 ok(ret == ERROR_SUCCESS, "RegQueryValueExA failed with error %u\n", ret); 3311 3312 /* Windows only compares the first few characters of the value name. 3313 * On Windows XP / 2003, it is sufficient to use "Cou", newer versions 3314 * require a longer substring. */ 3315 3316 ret = RegQueryValueExA(key, "Counters", NULL, NULL, NULL, &size); 3317 ok(ret == ERROR_SUCCESS, "RegQueryValueExA failed with error %u\n", ret); 3318 ret = RegQueryValueExA(key, "Counter2", NULL, NULL, NULL, &size); 3319 todo_wine ok(ret == ERROR_SUCCESS, "RegQueryValueExA failed with error %u\n", ret); 3320 ret = RegQueryValueExA(key, "CounterWine", NULL, NULL, NULL, &size); 3321 todo_wine ok(ret == ERROR_SUCCESS, "RegQueryValueExA failed with error %u\n", ret); 3322 3323 done: 3324 RegCloseKey(key); 3325 } 3326 3327 static void test_deleted_key(void) 3328 { 3329 HKEY hkey, hkey2; 3330 char value[20]; 3331 DWORD val_count, type; 3332 LONG res; 3333 3334 /* Open the test key, then delete it while it's open */ 3335 RegOpenKeyA( HKEY_CURRENT_USER, "Software\\Wine\\Test", &hkey ); 3336 3337 delete_key( hkey_main ); 3338 3339 val_count = sizeof(value); 3340 type = 0; 3341 res = RegEnumValueA( hkey, 0, value, &val_count, NULL, &type, 0, 0 ); 3342 ok(res == ERROR_KEY_DELETED, "expect ERROR_KEY_DELETED, got %i\n", res); 3343 3344 res = RegEnumKeyA( hkey, 0, value, sizeof(value) ); 3345 ok(res == ERROR_KEY_DELETED, "expect ERROR_KEY_DELETED, got %i\n", res); 3346 3347 val_count = sizeof(value); 3348 type = 0; 3349 res = RegQueryValueExA( hkey, "test", NULL, &type, (BYTE *)value, &val_count ); 3350 ok(res == ERROR_KEY_DELETED, "expect ERROR_KEY_DELETED, got %i\n", res); 3351 3352 res = RegSetValueExA( hkey, "test", 0, REG_SZ, (const BYTE*)"value", 6); 3353 ok(res == ERROR_KEY_DELETED, "expect ERROR_KEY_DELETED, got %i\n", res); 3354 3355 res = RegOpenKeyA( hkey, "test", &hkey2 ); 3356 ok(res == ERROR_KEY_DELETED, "expect ERROR_KEY_DELETED, got %i\n", res); 3357 if (res == 0) 3358 RegCloseKey( hkey2 ); 3359 3360 res = RegCreateKeyA( hkey, "test", &hkey2 ); 3361 ok(res == ERROR_KEY_DELETED, "expect ERROR_KEY_DELETED, got %i\n", res); 3362 if (res == 0) 3363 RegCloseKey( hkey2 ); 3364 3365 res = RegFlushKey( hkey ); 3366 ok(res == ERROR_KEY_DELETED, "expect ERROR_KEY_DELETED, got %i\n", res); 3367 3368 RegCloseKey( hkey ); 3369 3370 setup_main_key(); 3371 } 3372 3373 static void test_delete_value(void) 3374 { 3375 LONG res; 3376 char longname[401]; 3377 3378 res = RegSetValueExA( hkey_main, "test", 0, REG_SZ, (const BYTE*)"value", 6 ); 3379 ok(res == ERROR_SUCCESS, "expect ERROR_SUCCESS, got %i\n", res); 3380 3381 res = RegQueryValueExA( hkey_main, "test", NULL, NULL, NULL, NULL); 3382 ok(res == ERROR_SUCCESS, "expect ERROR_SUCCESS, got %i\n", res); 3383 3384 res = RegDeleteValueA( hkey_main, "test" ); 3385 ok(res == ERROR_SUCCESS, "expect ERROR_SUCCESS, got %i\n", res); 3386 3387 res = RegQueryValueExA( hkey_main, "test", NULL, NULL, NULL, NULL); 3388 ok(res == ERROR_FILE_NOT_FOUND, "expect ERROR_FILE_NOT_FOUND, got %i\n", res); 3389 3390 res = RegDeleteValueA( hkey_main, "test" ); 3391 ok(res == ERROR_FILE_NOT_FOUND, "expect ERROR_FILE_NOT_FOUND, got %i\n", res); 3392 3393 memset(longname, 'a', 400); 3394 longname[400] = 0; 3395 res = RegDeleteValueA( hkey_main, longname ); 3396 ok(res == ERROR_FILE_NOT_FOUND || broken(res == ERROR_MORE_DATA), /* nt4, win2k */ 3397 "expect ERROR_FILE_NOT_FOUND, got %i\n", res); 3398 3399 /* Default registry value */ 3400 res = RegSetValueExA(hkey_main, "", 0, REG_SZ, (const BYTE *)"value", 6); 3401 ok(res == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %d\n", res); 3402 3403 res = RegQueryValueExA(hkey_main, "", NULL, NULL, NULL, NULL); 3404 ok(res == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %d\n", res); 3405 3406 res = RegDeleteValueA(hkey_main, "" ); 3407 ok(res == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %d\n", res); 3408 3409 res = RegQueryValueExA(hkey_main, "", NULL, NULL, NULL, NULL); 3410 ok(res == ERROR_FILE_NOT_FOUND, "expected ERROR_FILE_NOT_FOUND, got %d\n", res); 3411 } 3412 3413 static void test_delete_key_value(void) 3414 { 3415 HKEY subkey; 3416 LONG ret; 3417 3418 if (!pRegDeleteKeyValueA) 3419 { 3420 win_skip("RegDeleteKeyValue is not available.\n"); 3421 return; 3422 } 3423 3424 ret = pRegDeleteKeyValueA(NULL, NULL, NULL); 3425 ok(ret == ERROR_INVALID_HANDLE, "got %d\n", ret); 3426 3427 ret = pRegDeleteKeyValueA(hkey_main, NULL, NULL); 3428 ok(ret == ERROR_FILE_NOT_FOUND, "got %d\n", ret); 3429 3430 ret = RegSetValueExA(hkey_main, "test", 0, REG_SZ, (const BYTE*)"value", 6); 3431 ok(ret == ERROR_SUCCESS, "got %d\n", ret); 3432 3433 ret = RegQueryValueExA(hkey_main, "test", NULL, NULL, NULL, NULL); 3434 ok(ret == ERROR_SUCCESS, "got %d\n", ret); 3435 3436 /* NULL subkey name means delete from open key */ 3437 ret = pRegDeleteKeyValueA(hkey_main, NULL, "test"); 3438 ok(ret == ERROR_SUCCESS, "got %d\n", ret); 3439 3440 ret = RegQueryValueExA(hkey_main, "test", NULL, NULL, NULL, NULL); 3441 ok(ret == ERROR_FILE_NOT_FOUND, "got %d\n", ret); 3442 3443 /* now with real subkey */ 3444 ret = RegCreateKeyExA(hkey_main, "Subkey1", 0, NULL, 0, KEY_WRITE|KEY_READ, NULL, &subkey, NULL); 3445 ok(!ret, "failed with error %d\n", ret); 3446 3447 ret = RegSetValueExA(subkey, "test", 0, REG_SZ, (const BYTE*)"value", 6); 3448 ok(ret == ERROR_SUCCESS, "got %d\n", ret); 3449 3450 ret = RegQueryValueExA(subkey, "test", NULL, NULL, NULL, NULL); 3451 ok(ret == ERROR_SUCCESS, "got %d\n", ret); 3452 3453 ret = pRegDeleteKeyValueA(hkey_main, "Subkey1", "test"); 3454 ok(ret == ERROR_SUCCESS, "got %d\n", ret); 3455 3456 ret = RegQueryValueExA(subkey, "test", NULL, NULL, NULL, NULL); 3457 ok(ret == ERROR_FILE_NOT_FOUND, "got %d\n", ret); 3458 3459 /* Default registry value */ 3460 ret = RegSetValueExA(subkey, "", 0, REG_SZ, (const BYTE *)"value", 6); 3461 ok(ret == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %d\n", ret); 3462 3463 ret = RegQueryValueExA(subkey, "", NULL, NULL, NULL, NULL); 3464 ok(ret == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %d\n", ret); 3465 3466 ret = pRegDeleteKeyValueA(hkey_main, "Subkey1", "" ); 3467 ok(ret == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %d\n", ret); 3468 3469 ret = RegQueryValueExA(subkey, "", NULL, NULL, NULL, NULL); 3470 ok(ret == ERROR_FILE_NOT_FOUND, "expected ERROR_FILE_NOT_FOUND, got %d\n", ret); 3471 3472 RegDeleteKeyA(subkey, ""); 3473 RegCloseKey(subkey); 3474 } 3475 3476 static void test_RegOpenCurrentUser(void) 3477 { 3478 HKEY key; 3479 LONG ret; 3480 3481 key = HKEY_CURRENT_USER; 3482 ret = RegOpenCurrentUser(KEY_READ, &key); 3483 ok(!ret, "got %d, error %d\n", ret, GetLastError()); 3484 ok(key != HKEY_CURRENT_USER, "got %p\n", key); 3485 RegCloseKey(key); 3486 } 3487 3488 static void test_RegNotifyChangeKeyValue(void) 3489 { 3490 HKEY key, subkey; 3491 HANDLE event; 3492 DWORD dwret; 3493 LONG ret; 3494 3495 event = CreateEventW(NULL, FALSE, TRUE, NULL); 3496 ok(event != NULL, "CreateEvent failed, error %u\n", GetLastError()); 3497 ret = RegCreateKeyA(hkey_main, "TestKey", &key); 3498 ok(ret == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %d\n", ret); 3499 3500 ret = RegNotifyChangeKeyValue(key, TRUE, REG_NOTIFY_CHANGE_NAME, event, TRUE); 3501 ok(ret == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %d\n", ret); 3502 dwret = WaitForSingleObject(event, 0); 3503 ok(dwret == WAIT_TIMEOUT, "expected WAIT_TIMEOUT, got %u\n", dwret); 3504 3505 ret = RegCreateKeyA(key, "SubKey", &subkey); 3506 ok(ret == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %d\n", ret); 3507 dwret = WaitForSingleObject(event, 0); 3508 ok(dwret == WAIT_OBJECT_0, "expected WAIT_OBJECT_0, got %u\n", dwret); 3509 3510 RegDeleteKeyA(key, ""); 3511 RegCloseKey(key); 3512 CloseHandle(event); 3513 } 3514 3515 static const char *dbgstr_longlong(ULONGLONG ll) 3516 { 3517 static char buf[16][64]; 3518 static int idx; 3519 3520 idx &= 0x0f; 3521 3522 if (sizeof(ll) > sizeof(unsigned long) && ll >> 32) 3523 sprintf(buf[idx], "0x%lx%08lx", (unsigned long)(ll >> 32), (unsigned long)ll); 3524 else 3525 sprintf(buf[idx], "0x%08lx", (unsigned long)ll); 3526 3527 return buf[idx++]; 3528 } 3529 3530 #define cmp_li(a, b, c) cmp_li_real(a, b, c, __LINE__) 3531 static void cmp_li_real(LARGE_INTEGER *l1, LARGE_INTEGER *l2, LONGLONG slack, int line) 3532 { 3533 LONGLONG diff = l2->QuadPart - l1->QuadPart; 3534 if (diff < 0) diff = -diff; 3535 ok_(__FILE__, line)(diff <= slack, "values don't match: %s/%s\n", 3536 dbgstr_longlong(l1->QuadPart), dbgstr_longlong(l2->QuadPart)); 3537 } 3538 3539 static void test_RegQueryValueExPerformanceData(void) 3540 { 3541 static const WCHAR globalW[] = { 'G','l','o','b','a','l',0 }; 3542 static const WCHAR dummyW[5] = { 'd','u','m','m','y' }; 3543 static const char * const names[] = { NULL, "", "Global", "2" "invalid counter name" }; 3544 DWORD cbData, len, i, type; 3545 BYTE *value; 3546 DWORD dwret; 3547 LONG limit = 6; 3548 PERF_DATA_BLOCK *pdb; 3549 HKEY hkey; 3550 BYTE buf[256 + sizeof(PERF_DATA_BLOCK)]; 3551 3552 /* Test with data == NULL */ 3553 dwret = RegQueryValueExA( HKEY_PERFORMANCE_DATA, "Global", NULL, NULL, NULL, &cbData ); 3554 ok( dwret == ERROR_MORE_DATA, "expected ERROR_MORE_DATA, got %d\n", dwret ); 3555 3556 dwret = RegQueryValueExW( HKEY_PERFORMANCE_DATA, globalW, NULL, NULL, NULL, &cbData ); 3557 ok( dwret == ERROR_MORE_DATA, "expected ERROR_MORE_DATA, got %d\n", dwret ); 3558 3559 /* Test ERROR_MORE_DATA, start with small buffer */ 3560 len = 10; 3561 value = HeapAlloc(GetProcessHeap(), 0, len); 3562 cbData = len; 3563 type = 0xdeadbeef; 3564 dwret = RegQueryValueExA( HKEY_PERFORMANCE_DATA, "Global", NULL, &type, value, &cbData ); 3565 ok( dwret == ERROR_MORE_DATA, "expected ERROR_MORE_DATA, got %d\n", dwret ); 3566 ok(type == REG_BINARY, "got %u\n", type); 3567 while( dwret == ERROR_MORE_DATA && limit) 3568 { 3569 len = len * 10; 3570 value = HeapReAlloc( GetProcessHeap(), 0, value, len ); 3571 cbData = len; 3572 type = 0xdeadbeef; 3573 dwret = RegQueryValueExA( HKEY_PERFORMANCE_DATA, "Global", NULL, &type, value, &cbData ); 3574 limit--; 3575 } 3576 ok(limit > 0, "too many times ERROR_MORE_DATA returned\n"); 3577 3578 ok(dwret == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %d\n", dwret); 3579 ok(type == REG_BINARY, "got %u\n", type); 3580 3581 /* Check returned data */ 3582 if (dwret == ERROR_SUCCESS) 3583 { 3584 ok(len >= sizeof(PERF_DATA_BLOCK), "got size %d\n", len); 3585 if (len >= sizeof(PERF_DATA_BLOCK)) { 3586 pdb = (PERF_DATA_BLOCK*) value; 3587 ok(pdb->Signature[0] == 'P', "expected Signature[0] = 'P', got 0x%x\n", pdb->Signature[0]); 3588 ok(pdb->Signature[1] == 'E', "expected Signature[1] = 'E', got 0x%x\n", pdb->Signature[1]); 3589 ok(pdb->Signature[2] == 'R', "expected Signature[2] = 'R', got 0x%x\n", pdb->Signature[2]); 3590 ok(pdb->Signature[3] == 'F', "expected Signature[3] = 'F', got 0x%x\n", pdb->Signature[3]); 3591 /* TODO: check other field */ 3592 } 3593 } 3594 3595 HeapFree(GetProcessHeap(), 0, value); 3596 3597 for (i = 0; i < sizeof(names)/sizeof(names[0]); i++) 3598 { 3599 cbData = 0xdeadbeef; 3600 dwret = RegQueryValueExA(HKEY_PERFORMANCE_DATA, names[i], NULL, NULL, NULL, &cbData); 3601 ok(dwret == ERROR_MORE_DATA, "%u/%s: got %u\n", i, names[i], dwret); 3602 ok(cbData == 0, "got %u\n", cbData); 3603 3604 cbData = 0; 3605 dwret = RegQueryValueExA(HKEY_PERFORMANCE_DATA, names[i], NULL, NULL, NULL, &cbData); 3606 ok(dwret == ERROR_MORE_DATA, "%u/%s: got %u\n", i, names[i], dwret); 3607 ok(cbData == 0, "got %u\n", cbData); 3608 3609 cbData = 0xdeadbeef; 3610 dwret = RegQueryValueExA(HKEY_PERFORMANCE_TEXT, names[i], NULL, NULL, NULL, &cbData); 3611 todo_wine 3612 ok(dwret == ERROR_MORE_DATA, "%u/%s: got %u\n", i, names[i], dwret); 3613 ok(cbData == 0, "got %u\n", cbData); 3614 3615 cbData = 0; 3616 dwret = RegQueryValueExA(HKEY_PERFORMANCE_TEXT, names[i], NULL, NULL, NULL, &cbData); 3617 todo_wine 3618 ok(dwret == ERROR_MORE_DATA, "%u/%s: got %u\n", i, names[i], dwret); 3619 ok(cbData == 0, "got %u\n", cbData); 3620 3621 cbData = 0xdeadbeef; 3622 dwret = RegQueryValueExA(HKEY_PERFORMANCE_NLSTEXT, names[i], NULL, NULL, NULL, &cbData); 3623 todo_wine 3624 ok(dwret == ERROR_MORE_DATA, "%u/%s: got %u\n", i, names[i], dwret); 3625 ok(cbData == 0, "got %u\n", cbData); 3626 3627 cbData = 0; 3628 dwret = RegQueryValueExA(HKEY_PERFORMANCE_NLSTEXT, names[i], NULL, NULL, NULL, &cbData); 3629 todo_wine 3630 ok(dwret == ERROR_MORE_DATA, "%u/%s: got %u\n", i, names[i], dwret); 3631 ok(cbData == 0, "got %u\n", cbData); 3632 } 3633 3634 memset(buf, 0x77, sizeof(buf)); 3635 type = 0xdeadbeef; 3636 cbData = sizeof(buf); 3637 dwret = RegQueryValueExA(HKEY_PERFORMANCE_DATA, "invalid counter name", NULL, &type, buf, &cbData); 3638 ok(dwret == ERROR_SUCCESS, "got %u\n", dwret); 3639 ok(type == REG_BINARY, "got %u\n", type); 3640 if (dwret == ERROR_SUCCESS) 3641 { 3642 SYSTEMTIME st; 3643 WCHAR sysname[MAX_COMPUTERNAME_LENGTH + 1]; 3644 DWORD sysname_len; 3645 LARGE_INTEGER counter, freq, ftime; 3646 3647 GetSystemTime(&st); 3648 GetSystemTimeAsFileTime((FILETIME *)&ftime); 3649 QueryPerformanceCounter(&counter); 3650 QueryPerformanceFrequency(&freq); 3651 3652 sysname_len = MAX_COMPUTERNAME_LENGTH + 1; 3653 GetComputerNameW(sysname, &sysname_len); 3654 3655 pdb = (PERF_DATA_BLOCK *)buf; 3656 ok(pdb->Signature[0] == 'P', "got '%c'\n", pdb->Signature[0]); 3657 ok(pdb->Signature[1] == 'E', "got '%c'\n", pdb->Signature[1]); 3658 ok(pdb->Signature[2] == 'R', "got '%c'\n", pdb->Signature[2]); 3659 ok(pdb->Signature[3] == 'F', "got '%c'\n", pdb->Signature[3]); 3660 3661 ok(pdb->LittleEndian == 1, "got %u\n", pdb->LittleEndian); 3662 ok(pdb->Version == 1, "got %u\n", pdb->Version); 3663 ok(pdb->Revision == 1, "got %u\n", pdb->Revision); 3664 len = (sizeof(*pdb) + pdb->SystemNameLength + 7) & ~7; 3665 ok(pdb->TotalByteLength == len, "got %u vs %u\n", pdb->TotalByteLength, len); 3666 ok(pdb->HeaderLength == pdb->TotalByteLength, "got %u\n", pdb->HeaderLength); 3667 ok(pdb->NumObjectTypes == 0, "got %u\n", pdb->NumObjectTypes); 3668 todo_wine 3669 ok(pdb->DefaultObject != 0, "got %u\n", pdb->DefaultObject); 3670 ok(pdb->SystemTime.wYear == st.wYear, "got %u\n", pdb->SystemTime.wYear); 3671 ok(pdb->SystemTime.wMonth == st.wMonth, "got %u\n", pdb->SystemTime.wMonth); 3672 ok(pdb->SystemTime.wDayOfWeek == st.wDayOfWeek, "got %u\n", pdb->SystemTime.wDayOfWeek); 3673 ok(pdb->SystemTime.wDay == st.wDay, "got %u\n", pdb->SystemTime.wDay); 3674 if (U(pdb->PerfTime).LowPart != 0x77777777) /* TestBot is broken */ 3675 cmp_li(&pdb->PerfTime, &counter, freq.QuadPart); 3676 if (U(pdb->PerfFreq).LowPart != 0x77777777) /* TestBot is broken */ 3677 cmp_li(&pdb->PerfFreq, &freq, 0); 3678 cmp_li(&pdb->PerfTime100nSec, &ftime, 200000); /* TestBot needs huge slack value */ 3679 ok(pdb->SystemNameLength == (sysname_len + 1) * sizeof(WCHAR), "expected %u, got %u\n", 3680 (sysname_len + 1) * sizeof(WCHAR), pdb->SystemNameLength); 3681 ok(pdb->SystemNameOffset == sizeof(*pdb), "got %u\n", pdb->SystemNameOffset); 3682 ok(!lstrcmpW(sysname, (LPCWSTR)(pdb + 1)), "%s != %s\n", 3683 wine_dbgstr_w(sysname), wine_dbgstr_w((LPCWSTR)(pdb + 1))); 3684 3685 len = pdb->TotalByteLength - (sizeof(*pdb) + pdb->SystemNameLength); 3686 if (len) 3687 { 3688 BYTE remainder[8], *p; 3689 3690 memset(remainder, 0x77, sizeof(remainder)); 3691 p = buf + sizeof(*pdb) + pdb->SystemNameLength; 3692 ok(!memcmp(p, remainder, len), "remainder: %02x,%02x...\n", p[0], p[1]); 3693 } 3694 } 3695 3696 dwret = RegOpenKeyA(HKEY_PERFORMANCE_DATA, NULL, &hkey); 3697 todo_wine 3698 ok(dwret == ERROR_INVALID_HANDLE, "got %u\n", dwret); 3699 3700 dwret = RegOpenKeyA(HKEY_PERFORMANCE_DATA, "Global", &hkey); 3701 todo_wine 3702 ok(dwret == ERROR_INVALID_HANDLE, "got %u\n", dwret); 3703 3704 dwret = RegOpenKeyExA(HKEY_PERFORMANCE_DATA, "Global", 0, KEY_READ, &hkey); 3705 todo_wine 3706 ok(dwret == ERROR_INVALID_HANDLE, "got %u\n", dwret); 3707 3708 dwret = RegQueryValueA(HKEY_PERFORMANCE_DATA, "Global", NULL, (LONG *)&cbData); 3709 todo_wine 3710 ok(dwret == ERROR_INVALID_HANDLE, "got %u\n", dwret); 3711 3712 dwret = RegSetValueA(HKEY_PERFORMANCE_DATA, "Global", REG_SZ, "dummy", 4); 3713 todo_wine 3714 ok(dwret == ERROR_INVALID_HANDLE, "got %u\n", dwret); 3715 3716 dwret = RegSetValueExA(HKEY_PERFORMANCE_DATA, "Global", 0, REG_SZ, (const BYTE *)"dummy", 40); 3717 todo_wine 3718 ok(dwret == ERROR_INVALID_HANDLE, "got %u\n", dwret); 3719 3720 cbData = sizeof(buf); 3721 dwret = RegEnumKeyA(HKEY_PERFORMANCE_DATA, 0, (LPSTR)buf, cbData); 3722 todo_wine 3723 ok(dwret == ERROR_INVALID_HANDLE, "got %u\n", dwret); 3724 3725 cbData = sizeof(buf); 3726 dwret = RegEnumValueA(HKEY_PERFORMANCE_DATA, 0, (LPSTR)buf, &cbData, NULL, NULL, NULL, NULL); 3727 todo_wine 3728 ok(dwret == ERROR_MORE_DATA, "got %u\n", dwret); 3729 todo_wine 3730 ok(cbData == sizeof(buf), "got %u\n", cbData); 3731 3732 dwret = RegEnumValueA(HKEY_PERFORMANCE_DATA, 0, NULL, &cbData, NULL, NULL, NULL, NULL); 3733 ok(dwret == ERROR_INVALID_PARAMETER, "got %u\n", dwret); 3734 3735 if (pRegSetKeyValueW) 3736 { 3737 dwret = pRegSetKeyValueW(HKEY_PERFORMANCE_DATA, NULL, globalW, REG_SZ, dummyW, sizeof(dummyW)); 3738 todo_wine 3739 ok(dwret == ERROR_INVALID_HANDLE, "got %u\n", dwret); 3740 } 3741 3742 dwret = RegCloseKey(HKEY_PERFORMANCE_DATA); 3743 ok(dwret == ERROR_SUCCESS, "got %u\n", dwret); 3744 } 3745 3746 START_TEST(registry) 3747 { 3748 /* Load pointers for functions that are not available in all Windows versions */ 3749 InitFunctionPtrs(); 3750 3751 setup_main_key(); 3752 check_user_privs(); 3753 test_set_value(); 3754 create_test_entries(); 3755 test_enum_value(); 3756 test_query_value_ex(); 3757 test_get_value(); 3758 test_reg_open_key(); 3759 test_reg_create_key(); 3760 test_reg_close_key(); 3761 test_reg_delete_key(); 3762 test_reg_query_value(); 3763 test_reg_query_info(); 3764 test_string_termination(); 3765 test_symlinks(); 3766 test_redirection(); 3767 test_classesroot(); 3768 test_classesroot_enum(); 3769 test_classesroot_mask(); 3770 test_perflib_key(); 3771 test_reg_save_key(); 3772 test_reg_load_key(); 3773 test_reg_unload_key(); 3774 test_reg_copy_tree(); 3775 test_reg_delete_tree(); 3776 test_rw_order(); 3777 test_deleted_key(); 3778 test_delete_value(); 3779 test_delete_key_value(); 3780 test_RegOpenCurrentUser(); 3781 test_RegNotifyChangeKeyValue(); 3782 test_RegQueryValueExPerformanceData(); 3783 3784 /* cleanup */ 3785 delete_key( hkey_main ); 3786 3787 test_regconnectregistry(); 3788 } 3789