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