ReactOS  0.4.13-dev-92-gf251225
registry.c
Go to the documentation of this file.
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 
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])
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 */
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  }
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)
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);
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));
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 */
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 */
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  {
445  ok(ret == ERROR_NOACCESS, "RegSetValueExW should have failed with ERROR_NOACCESS: %d, GLE=%d\n", ret, GetLastError());
446 
448  ok(ret == ERROR_SUCCESS, "got %d\n", ret);
449 
451  ok(ret == ERROR_NOACCESS, "RegSetValueExW should have failed with ERROR_NOACCESS: %d, GLE=%d\n", ret, GetLastError());
452 
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) );
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. */
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) */
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. */
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 */
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;
1013  PSID world_sid;
1015  PACL key_acl;
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 
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;
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 
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 
1254  ok(error == ERROR_SUCCESS,
1255  "Expected RegSetKeySecurity to return success, got error %u\n", error);
1256 
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;
1292  PSID world_sid;
1294  PACL key_acl;
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 */
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 
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  {
1427  ok(ret == ERROR_SUCCESS,
1428  "Expected RegSetKeySecurity to return success, got error %u\n", ret);
1429 
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. */
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 
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
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 {
1528  HANDLE hToken;
1529  LUID luid;
1530 
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 
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 
1574 }
1575 
1576 static void test_reg_load_key(void)
1577 {
1578  DWORD ret;
1579  HKEY hkHandle;
1580 
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 
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 
1605  {
1606  win_skip("Failed to set SE_RESTORE_NAME privileges, skipping tests\n");
1607  return;
1608  }
1609 
1611  ok(ret == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %d\n", ret);
1612 
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);
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);
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);
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 */
1818  ok(ret == ERROR_INVALID_HANDLE, "ret = %d\n", ret);
1819 
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;
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;
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");
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 
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 
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 
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 
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 
2454  KEY_ALL_ACCESS, NULL, &key, NULL );
2455  ok( err == ERROR_ALREADY_EXISTS, "RegCreateKeyEx wrong error %u\n", err );
2456 
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 
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 {
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,
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,
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,
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,
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,
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,
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,
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,
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,
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,
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);
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,
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 );
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