xref: /reactos/modules/rostests/winetests/reg/add.c (revision 1a6f523e)
1 /*
2  * Copyright 2014 Akihiro Sagawa
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
17  */
18 
19 #include "reg_test.h"
20 
run_reg_exe_(const char * file,unsigned line,const char * cmd,DWORD * rc)21 BOOL run_reg_exe_(const char *file, unsigned line, const char *cmd, DWORD *rc)
22 {
23     STARTUPINFOA si = {sizeof(STARTUPINFOA)};
24     PROCESS_INFORMATION pi;
25     BOOL bret;
26     DWORD ret;
27     char cmdline[256];
28 
29     si.dwFlags = STARTF_USESTDHANDLES;
30     si.hStdInput  = INVALID_HANDLE_VALUE;
31     si.hStdOutput = INVALID_HANDLE_VALUE;
32     si.hStdError  = INVALID_HANDLE_VALUE;
33 
34     strcpy(cmdline, cmd);
35     if (!CreateProcessA(NULL, cmdline, NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi))
36         return FALSE;
37 
38     ret = WaitForSingleObject(pi.hProcess, 10000);
39     if (ret == WAIT_TIMEOUT)
40         TerminateProcess(pi.hProcess, 1);
41 
42     bret = GetExitCodeProcess(pi.hProcess, rc);
43     lok(bret, "GetExitCodeProcess failed: %d\n", GetLastError());
44 
45     CloseHandle(pi.hThread);
46     CloseHandle(pi.hProcess);
47     return bret;
48 }
49 
verify_reg_(const char * file,unsigned line,HKEY hkey,const char * value,DWORD exp_type,const void * exp_data,DWORD exp_size,DWORD todo)50 void verify_reg_(const char *file, unsigned line, HKEY hkey, const char *value,
51                  DWORD exp_type, const void *exp_data, DWORD exp_size, DWORD todo)
52 {
53     DWORD type, size;
54     BYTE data[256];
55     LONG err;
56 
57     size = sizeof(data);
58     memset(data, 0xdd, size);
59     err = RegQueryValueExA(hkey, value, NULL, &type, data, &size);
60     lok(err == ERROR_SUCCESS, "RegQueryValueEx failed: got error %d\n", err);
61     if (err != ERROR_SUCCESS)
62         return;
63 
64     todo_wine_if (todo & TODO_REG_TYPE)
65         lok(type == exp_type, "got registry type %d, expected %d\n", type, exp_type);
66     todo_wine_if (todo & TODO_REG_SIZE)
67         lok(size == exp_size, "got data size %d, expected %d\n", size, exp_size);
68     if (exp_data)
69     {
70         todo_wine_if (todo & TODO_REG_DATA)
71             lok(memcmp(data, exp_data, size) == 0, "registry data does not match\n");
72     }
73 }
74 
verify_reg_nonexist_(const char * file,unsigned line,HKEY hkey,const char * value)75 void verify_reg_nonexist_(const char *file, unsigned line, HKEY hkey, const char *value)
76 {
77     LONG err;
78 
79     err = RegQueryValueExA(hkey, value, NULL, NULL, NULL, NULL);
80     lok(err == ERROR_FILE_NOT_FOUND, "registry value '%s' shouldn't exist; got %d, expected 2\n",
81         (value && *value) ? value : "(Default)", err);
82 }
83 
open_key_(const char * file,unsigned line,HKEY root,const char * path,REGSAM sam,HKEY * hkey)84 void open_key_(const char *file, unsigned line, HKEY root, const char *path, REGSAM sam, HKEY *hkey)
85 {
86     LONG err;
87 
88     err = RegOpenKeyExA(root, path, 0, KEY_READ|sam, hkey);
89     lok(err == ERROR_SUCCESS, "RegOpenKeyExA failed: got error %d\n", err);
90 }
91 
close_key_(const char * file,unsigned line,HKEY hkey)92 void close_key_(const char *file, unsigned line, HKEY hkey)
93 {
94     LONG err;
95 
96     err = RegCloseKey(hkey);
97     lok(err == ERROR_SUCCESS, "RegCloseKey failed: got error %d\n", err);
98 }
99 
verify_key_(const char * file,unsigned line,HKEY root,const char * path,REGSAM sam)100 void verify_key_(const char *file, unsigned line, HKEY root, const char *path, REGSAM sam)
101 {
102     HKEY hkey;
103     LONG err;
104 
105     err = RegOpenKeyExA(root, path, 0, KEY_READ|sam, &hkey);
106     lok(err == ERROR_SUCCESS, "RegOpenKeyExA failed: got error %d\n", err);
107 
108     if (hkey)
109         RegCloseKey(hkey);
110 }
111 
verify_key_nonexist_(const char * file,unsigned line,HKEY root,const char * path,REGSAM sam)112 void verify_key_nonexist_(const char *file, unsigned line, HKEY root, const char *path, REGSAM sam)
113 {
114     HKEY hkey;
115     LONG err;
116 
117     err = RegOpenKeyExA(root, path, 0, KEY_READ|sam, &hkey);
118     lok(err == ERROR_FILE_NOT_FOUND, "registry key '%s' shouldn't exist; got %d, expected 2\n", path, err);
119 
120     if (hkey)
121         RegCloseKey(hkey);
122 }
123 
add_key_(const char * file,unsigned line,const HKEY root,const char * path,REGSAM sam,HKEY * hkey)124 void add_key_(const char *file, unsigned line, const HKEY root, const char *path, REGSAM sam, HKEY *hkey)
125 {
126     LONG err;
127     HKEY new_key;
128 
129     err = RegCreateKeyExA(root, path, 0, NULL, REG_OPTION_NON_VOLATILE,
130                           KEY_READ|KEY_WRITE|sam, NULL, &new_key, NULL);
131     lok(err == ERROR_SUCCESS, "RegCreateKeyExA failed: got error %d\n", err);
132 
133     if (hkey)
134         *hkey = new_key;
135     else
136         RegCloseKey(new_key);
137 }
138 
delete_key_(const char * file,unsigned line,HKEY root,const char * path,REGSAM sam)139 void delete_key_(const char *file, unsigned line, HKEY root, const char *path, REGSAM sam)
140 {
141     LONG err;
142 
143     if (!path) return;
144 
145     if (!sam)
146     {
147         err = RegDeleteKeyA(root, path);
148         lok(err == ERROR_SUCCESS, "RegDeleteKeyA failed: got error %d\n", err);
149     }
150     else
151     {
152         err = RegDeleteKeyExA(root, path, sam, 0);
153         lok(err == ERROR_SUCCESS, "RegDeleteKeyExA failed: got error %d\n", err);
154     }
155 }
156 
delete_tree_(const char * file,unsigned line,HKEY root,const char * path,REGSAM sam)157 LONG delete_tree_(const char *file, unsigned line, HKEY root, const char *path, REGSAM sam)
158 {
159     HKEY hkey;
160     LONG ret;
161     char *subkey_name = NULL;
162     DWORD max_subkey_len, subkey_len;
163     static const char empty[1];
164 
165     ret = RegOpenKeyExA(root, path, 0, KEY_READ|sam, &hkey);
166     lok(!ret || ret == ERROR_FILE_NOT_FOUND, "RegOpenKeyExA failed, got error %d\n", ret);
167     if (ret) return ret;
168 
169     ret = RegQueryInfoKeyA(hkey, NULL, NULL, NULL, NULL, &max_subkey_len,
170                            NULL, NULL, NULL, NULL, NULL, NULL);
171     if (ret) goto cleanup;
172 
173     max_subkey_len++;
174 
175     subkey_name = HeapAlloc(GetProcessHeap(), 0, max_subkey_len);
176     if (!subkey_name)
177     {
178         ret = ERROR_NOT_ENOUGH_MEMORY;
179         goto cleanup;
180     }
181 
182     for (;;)
183     {
184         subkey_len = max_subkey_len;
185         ret = RegEnumKeyExA(hkey, 0, subkey_name, &subkey_len, NULL, NULL, NULL, NULL);
186         if (ret == ERROR_NO_MORE_ITEMS) break;
187         if (ret) goto cleanup;
188         ret = delete_tree_(file, line, hkey, subkey_name, sam);
189         if (ret) goto cleanup;
190     }
191 
192     if (!sam)
193         ret = RegDeleteKeyA(hkey, empty);
194     else
195         ret = RegDeleteKeyExA(hkey, empty, sam, 0);
196 
197 cleanup:
198     lok(!ret, "Failed to delete registry key, got error %d\n", ret);
199     HeapFree(GetProcessHeap(), 0, subkey_name);
200     RegCloseKey(hkey);
201     return ret;
202 }
203 
add_value_(const char * file,unsigned line,HKEY hkey,const char * name,DWORD type,const void * data,size_t size)204 void add_value_(const char *file, unsigned line, HKEY hkey, const char *name,
205                 DWORD type, const void *data, size_t size)
206 {
207     LONG err;
208 
209     err = RegSetValueExA(hkey, name, 0, type, (const BYTE *)data, size);
210     lok(err == ERROR_SUCCESS, "RegSetValueExA failed: got error %d\n", err);
211 }
212 
delete_value_(const char * file,unsigned line,HKEY hkey,const char * name)213 void delete_value_(const char *file, unsigned line, HKEY hkey, const char *name)
214 {
215     LONG err;
216 
217     err = RegDeleteValueA(hkey, name);
218     lok(err == ERROR_SUCCESS, "RegDeleteValueA failed: got error %d\n", err);
219 }
220 
221 /* Unit tests */
222 
test_command_syntax(void)223 static void test_command_syntax(void)
224 {
225     DWORD r;
226 
227     delete_tree(HKEY_CURRENT_USER, KEY_BASE, 0);
228 
229     run_reg_exe("reg add", &r);
230     ok(r == REG_EXIT_FAILURE, "got exit code %d, expected 1\n", r);
231 
232     run_reg_exe("reg add /?", &r);
233     ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r);
234 
235     run_reg_exe("reg add /h", &r);
236     ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r);
237 
238     run_reg_exe("reg add -H", &r);
239     ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r);
240 
241     /* Duplicate switches */
242     run_reg_exe("reg add HKCU\\" KEY_BASE " /v Wine /t REG_DWORD /d 0x1 /v Test /f", &r);
243     ok(r == REG_EXIT_FAILURE, "got exit code %d, expected 1\n", r);
244 
245     run_reg_exe("reg add HKCU\\" KEY_BASE " /v dup1 /t REG_DWORD /d 123 /f /t REG_SZ", &r);
246     ok(r == REG_EXIT_FAILURE || broken(r == REG_EXIT_SUCCESS /* WinXP */),
247        "got exit code %d, expected 1\n", r);
248 
249     run_reg_exe("reg add HKCU\\" KEY_BASE " /v dup2 /t REG_DWORD /d 123 /f /d 456", &r);
250     ok(r == REG_EXIT_FAILURE, "got exit code %d, expected 1\n", r);
251 
252     run_reg_exe("reg add HKCU\\" KEY_BASE " /f /f", &r);
253     ok(r == REG_EXIT_FAILURE, "got exit code %d, expected 1\n", r);
254 
255     run_reg_exe("reg add HKCU\\" KEY_BASE " /v Wine /ve", &r);
256     ok(r == REG_EXIT_FAILURE, "got exit code %d, expected 1\n", r);
257 
258     /* No /v argument */
259     run_reg_exe("reg add HKCU\\" KEY_BASE " /v", &r);
260     ok(r == REG_EXIT_FAILURE, "got exit code %d, expected 1\n", r);
261 
262     run_reg_exe("reg add HKCU\\" KEY_BASE " /d Test /f /v", &r);
263     ok(r == REG_EXIT_FAILURE, "got exit code %d, expected 1\n", r);
264 
265     /* Test invalid switches */
266     run_reg_exe("reg add HKCU\\" KEY_BASE " /v invalid1 /a", &r);
267     ok(r == REG_EXIT_FAILURE, "got exit code %d, expected 1\n", r);
268 
269     run_reg_exe("reg add HKCU\\" KEY_BASE " /v invalid2 /ae", &r);
270     ok(r == REG_EXIT_FAILURE, "got exit code %d, expected 1\n", r);
271 
272     run_reg_exe("reg add HKCU\\" KEY_BASE " /v invalid3 /", &r);
273     ok(r == REG_EXIT_FAILURE, "got exit code %d, expected 1\n", r);
274 
275     run_reg_exe("reg add HKCU\\" KEY_BASE " /v invalid4 -", &r);
276     ok(r == REG_EXIT_FAILURE, "got exit code %d, expected 1\n", r);
277 
278     /* Test empty type */
279     run_reg_exe("reg add HKCU\\" KEY_BASE " /v emptyType /t \"\" /d WineTest /f", &r);
280     ok(r == REG_EXIT_FAILURE, "got exit code %d, expected 1\n", r);
281 
282     /* Test registry view */
283     run_reg_exe("reg add HKCU\\" KEY_BASE " /v abc /d 123 /f /reg:32 /reg:32", &r);
284     ok(r == REG_EXIT_FAILURE, "got exit code %d, expected 1\n", r);
285 
286     run_reg_exe("reg add HKCU\\" KEY_BASE " /v abc /d 123 /f /reg:32 /reg:64", &r);
287     ok(r == REG_EXIT_FAILURE, "got exit code %d, expected 1\n", r);
288 
289     run_reg_exe("reg add HKCU\\" KEY_BASE " /v abc /d 123 /f /reg:64 /reg:64", &r);
290     ok(r == REG_EXIT_FAILURE, "got exit code %d, expected 1\n", r);
291 }
292 
test_key_formats(void)293 static void test_key_formats(void)
294 {
295     HKEY hkey;
296     DWORD r;
297     LONG err;
298 
299     add_key(HKEY_CURRENT_USER, KEY_BASE, 0, &hkey);
300 
301     run_reg_exe("reg add \\HKCU\\" KEY_BASE "\\keytest0 /f", &r);
302     ok(r == REG_EXIT_FAILURE, "got exit code %u, expected 1\n", r);
303     verify_key_nonexist(hkey, "keytest0", 0);
304 
305     run_reg_exe("reg add \\\\HKCU\\" KEY_BASE "\\keytest1 /f", &r);
306     ok(r == REG_EXIT_FAILURE, "got exit code %u, expected 1\n", r);
307     verify_key_nonexist(hkey, "keytest1", 0);
308 
309     run_reg_exe("reg add HKCU\\" KEY_BASE "\\keytest2\\\\ /f", &r);
310     ok(r == REG_EXIT_FAILURE || broken(r == REG_EXIT_SUCCESS /* WinXP */),
311         "got exit code %u, expected 1\n", r);
312     err = RegDeleteKeyA(HKEY_CURRENT_USER, KEY_BASE "\\keytest2");
313     ok(err == ERROR_FILE_NOT_FOUND || broken(err == ERROR_SUCCESS /* WinXP */),
314         "got exit code %d, expected 2\n", err);
315 
316     run_reg_exe("reg add HKCU\\" KEY_BASE "\\keytest3\\ /f", &r);
317     ok(r == REG_EXIT_SUCCESS, "got exit code %u, expected 0\n", r);
318     verify_key(hkey, "keytest3", 0);
319 
320     run_reg_exe("reg add HKCU\\" KEY_BASE "\\keytest4 /f", &r);
321     ok(r == REG_EXIT_SUCCESS, "got exit code %u, expected 0\n", r);
322     verify_key(hkey, "keytest4", 0);
323 
324     run_reg_exe("reg add HKCU\\" KEY_BASE "\\https://winehq.org /f", &r);
325     ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r);
326     verify_key(hkey, "https://winehq.org", 0);
327 
328     close_key(hkey);
329     delete_tree(HKEY_CURRENT_USER, KEY_BASE, 0);
330 
331     /* Test validity of trailing backslash after system key */
332     run_reg_exe("reg add HKCU\\ /v Value1 /t REG_SZ /d foo /f", &r);
333     ok(r == REG_EXIT_FAILURE, "got exit code %d, expected 1\n", r);
334     verify_reg_nonexist(HKEY_CURRENT_USER, "Value1");
335 
336     run_reg_exe("reg add HKEY_CURRENT_USER\\ /v Value2 /t REG_SZ /d bar /f", &r);
337     ok(r == REG_EXIT_FAILURE, "got exit code %d, expected 1\n", r);
338     verify_reg_nonexist(HKEY_CURRENT_USER, "Value2");
339 }
340 
test_add(void)341 static void test_add(void)
342 {
343     HKEY hkey;
344     DWORD r, dword;
345 
346     run_reg_exe("reg add HKCU\\" KEY_BASE " /f", &r);
347     ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r);
348 
349     open_key(HKEY_CURRENT_USER, KEY_BASE, KEY_WRITE, &hkey);
350 
351     /* The Default value is initialized if no parameters are specified */
352     verify_reg(hkey, NULL, REG_SZ, "", 1, 0);
353     delete_value(hkey, NULL);
354 
355     /* This also occurs when specifying a registry type and passing data */
356     run_reg_exe("reg add HKCU\\" KEY_BASE " /t REG_DWORD /d 0x5 /f", &r);
357     ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r);
358     dword = 0x5;
359     verify_reg(hkey, NULL, REG_DWORD, &dword, sizeof(dword), 0);
360 
361     /* The Default value can also be overwritten as an empty string */
362     run_reg_exe("reg add HKCU\\" KEY_BASE " /f", &r);
363     ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r);
364     verify_reg(hkey, NULL, REG_SZ, "", 1, 0);
365 
366     close_key(hkey);
367     delete_key(HKEY_CURRENT_USER, KEY_BASE, 0);
368 
369     /* Specifying a value name doesn't initialize the Default value in a new key */
370     run_reg_exe("reg add HKCU\\" KEY_BASE " /v Test /t REG_SZ /d \"Just me here\" /f", &r);
371     ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r);
372 
373     open_key(HKEY_CURRENT_USER, KEY_BASE, 0, &hkey);
374 
375     verify_reg(hkey, "Test", REG_SZ, "Just me here", 13, 0);
376     verify_reg_nonexist(hkey, NULL);
377 
378     close_key(hkey);
379     delete_key(HKEY_CURRENT_USER, KEY_BASE, 0);
380 
381     /* Adding a registry key via WinAPI doesn't initialize the Default value... */
382     add_key(HKEY_CURRENT_USER, KEY_BASE, 0, &hkey);
383     verify_reg_nonexist(hkey, NULL);
384 
385     /* ... but we can add it without passing [/f] to reg.exe */
386     run_reg_exe("reg add HKCU\\" KEY_BASE, &r);
387     ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r);
388     verify_reg(hkey, NULL, REG_SZ, "", 1, 0);
389     delete_value(hkey, NULL);
390 
391     /* Test whether overwriting a registry key modifies existing keys and values */
392     add_key(hkey, "Subkey", 0, NULL);
393     add_value(hkey, "Test1", REG_SZ, "Value1", 7);
394     dword = 0x123;
395     add_value(hkey, "Test2", REG_DWORD, &dword, sizeof(dword));
396 
397     run_reg_exe("reg add HKCU\\" KEY_BASE " /f", &r);
398     ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r);
399 
400     verify_key(HKEY_CURRENT_USER, KEY_BASE, 0);
401     verify_key(hkey, "Subkey", 0);
402     verify_reg(hkey, "Test1", REG_SZ, "Value1", 7, 0);
403     verify_reg(hkey, "Test2", REG_DWORD, &dword, sizeof(dword), 0);
404     verify_reg(hkey, NULL, REG_SZ, "", 1, 0);
405 
406     run_reg_exe("reg add HKCU\\" KEY_BASE " /t REG_NONE /d Test /f", &r);
407     ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r);
408 
409     verify_key(HKEY_CURRENT_USER, KEY_BASE, 0);
410     verify_key(hkey, "Subkey", 0);
411     verify_reg(hkey, "Test1", REG_SZ, "Value1", 7, 0);
412     verify_reg(hkey, "Test2", REG_DWORD, &dword, sizeof(dword), 0);
413     verify_reg(hkey, NULL, REG_NONE, "T\0e\0s\0t\0\0", 10, 0);
414 
415     close_key(hkey);
416     delete_tree(HKEY_CURRENT_USER, KEY_BASE, 0);
417 }
418 
test_reg_none(void)419 static void test_reg_none(void)
420 {
421     HKEY hkey;
422     DWORD r;
423 
424     add_key(HKEY_CURRENT_USER, KEY_BASE, 0, &hkey);
425 
426     run_reg_exe("reg add HKCU\\" KEY_BASE " /t REG_NONE /f", &r);
427     ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r);
428     verify_reg(hkey, NULL, REG_NONE, "\0", 2, 0);
429 
430     delete_value(hkey, NULL);
431 
432     run_reg_exe("reg add HKCU\\" KEY_BASE " /ve /t REG_NONE /f", &r);
433     ok(r == REG_EXIT_SUCCESS, "got exit code %u, expected 0\n", r);
434     verify_reg(hkey, NULL, REG_NONE, "\0", 2, 0);
435 
436     run_reg_exe("reg add HKCU\\" KEY_BASE " /v none0 /d deadbeef /t REG_NONE /f", &r);
437     ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r);
438     verify_reg(hkey, "none0", REG_NONE, "d\0e\0a\0d\0b\0e\0e\0f\0\0", 18, 0);
439 
440     run_reg_exe("reg add HKCU\\" KEY_BASE " /v none1 /t REG_NONE /f", &r);
441     ok(r == REG_EXIT_SUCCESS, "got exit code %u, expected 0\n", r);
442     verify_reg(hkey, "none1", REG_NONE, "\0", 2, 0);
443 
444     close_key(hkey);
445     delete_key(HKEY_CURRENT_USER, KEY_BASE, 0);
446 }
447 
test_reg_sz(void)448 static void test_reg_sz(void)
449 {
450     HKEY hkey;
451     DWORD r;
452 
453     add_key(HKEY_CURRENT_USER, KEY_BASE, 0, &hkey);
454 
455     run_reg_exe("reg add HKCU\\" KEY_BASE " /t REG_SZ /f", &r);
456     ok(r == REG_EXIT_SUCCESS, "got exit code %u, expected 0\n", r);
457     verify_reg(hkey, NULL, REG_SZ, "", 1, 0);
458 
459     run_reg_exe("reg add HKCU\\" KEY_BASE " /d WineTest /f", &r);
460     ok(r == REG_EXIT_SUCCESS || broken(r == REG_EXIT_FAILURE /* WinXP */),
461        "got exit code %d, expected 0\n", r);
462     if (r == REG_EXIT_SUCCESS)
463         verify_reg(hkey, "", REG_SZ, "WineTest", 9, 0);
464     else
465         win_skip("broken reg.exe detected\n");
466 
467     run_reg_exe("reg add HKCU\\" KEY_BASE " /ve /f", &r);
468     ok(r == REG_EXIT_SUCCESS, "got exit code %u, expected 0\n", r);
469     verify_reg(hkey, NULL, REG_SZ, "", 1, 0);
470 
471     run_reg_exe("reg add HKCU\\" KEY_BASE " /ve /f /ve", &r);
472     ok(r == REG_EXIT_FAILURE, "got exit code %d, expected 1\n", r);
473 
474     run_reg_exe("reg add HKEY_CURRENT_USER\\" KEY_BASE " /ve /d WineTEST /f", &r);
475     ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r);
476     verify_reg(hkey, "", REG_SZ, "WineTEST", 9, 0);
477 
478     run_reg_exe("reg add HKCU\\" KEY_BASE " /ve /t REG_SZ /f", &r);
479     ok(r == REG_EXIT_SUCCESS, "got exit code %u, expected 0\n", r);
480     verify_reg(hkey, NULL, REG_SZ, "", 1, 0);
481 
482     run_reg_exe("reg add HKCU\\" KEY_BASE " /v test0 /d deadbeef /f", &r);
483     ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r);
484     verify_reg(hkey, "test0", REG_SZ, "deadbeef", 9, 0);
485 
486     run_reg_exe("reg add HKCU\\" KEY_BASE " /v test0 /f", &r);
487     ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r);
488     verify_reg(hkey, "test0", REG_SZ, "", 1, 0);
489 
490     run_reg_exe("reg add HKCU\\" KEY_BASE " /v test1 /t REG_SZ /f /d", &r);
491     ok(r == REG_EXIT_FAILURE, "got exit code %d, expected 1\n", r);
492 
493     run_reg_exe("reg add HKCU\\" KEY_BASE " /t REG_SZ /v test2 /f", &r);
494     ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r);
495     verify_reg(hkey, "test2", REG_SZ, "", 1, 0);
496 
497     run_reg_exe("reg add HKCU\\" KEY_BASE " /t REG_SZ /v test3 /f /d \"\"", &r);
498     ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r);
499     verify_reg(hkey, "test3", REG_SZ, "", 1, 0);
500 
501     run_reg_exe("reg add HKCU\\" KEY_BASE " /v string\\04 /t REG_SZ /d \"Value\" /f", &r);
502     ok(r == REG_EXIT_SUCCESS, "got exit code %u, expected 0\n", r);
503     verify_reg(hkey, "string\\04", REG_SZ, "Value", 6, 0);
504 
505     run_reg_exe("reg add HKCU\\" KEY_BASE " /v string5 /t REG_SZ /d \"foo\\0bar\" /f", &r);
506     ok(r == REG_EXIT_SUCCESS, "got exit code %u, expected 0\n", r);
507     verify_reg(hkey, "string5", REG_SZ, "foo\\0bar", 9, 0);
508 
509     run_reg_exe("reg add HKCU\\" KEY_BASE " /v \\0 /t REG_SZ /d \"Value\" /f", &r);
510     ok(r == REG_EXIT_SUCCESS, "got exit code %u, expected 0\n", r);
511     verify_reg(hkey, "\\0", REG_SZ, "Value", 6, 0);
512 
513     /* Test support for forward and back slashes in value names */
514     run_reg_exe("reg add HKCU\\" KEY_BASE " /v count/up /d one/two/three /f", &r);
515     ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r);
516     verify_reg(hkey, "count/up", REG_SZ, "one/two/three", 14, 0);
517 
518     run_reg_exe("reg add HKCU\\" KEY_BASE " /v \\foo\\bar /f", &r);
519     ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r);
520     verify_reg(hkey, "\\foo\\bar", REG_SZ, "", 1, 0);
521 
522     close_key(hkey);
523     delete_key(HKEY_CURRENT_USER, KEY_BASE, 0);
524 }
525 
test_reg_expand_sz(void)526 static void test_reg_expand_sz(void)
527 {
528     HKEY hkey;
529     DWORD r;
530 
531     add_key(HKEY_CURRENT_USER, KEY_BASE, 0, &hkey);
532 
533     run_reg_exe("reg add HKCU\\" KEY_BASE " /t REG_EXPAND_SZ /f", &r);
534     ok(r == REG_EXIT_SUCCESS, "got exit code %u, expected 0\n", r);
535     verify_reg(hkey, NULL, REG_EXPAND_SZ, "", 1, 0);
536 
537     delete_value(hkey, NULL);
538 
539     run_reg_exe("reg add HKCU\\" KEY_BASE " /ve /t REG_EXPAND_SZ /f", &r);
540     ok(r == REG_EXIT_SUCCESS, "got exit code %u, expected 0\n", r);
541     verify_reg(hkey, NULL, REG_EXPAND_SZ, "", 1, 0);
542 
543     run_reg_exe("reg add HKCU\\" KEY_BASE " /v expand0 /t REG_EXpand_sz /d \"dead%PATH%beef\" /f", &r);
544     ok(r == REG_EXIT_SUCCESS, "got exit code %u, expected 0\n", r);
545     verify_reg(hkey, "expand0", REG_EXPAND_SZ, "dead%PATH%beef", 15, 0);
546 
547     run_reg_exe("reg add HKCU\\" KEY_BASE " /v expand1 /t REG_EXpand_sz /d \"dead^%PATH^%beef\" /f", &r);
548     ok(r == REG_EXIT_SUCCESS, "got exit code %u, expected 0\n", r);
549     verify_reg(hkey, "expand1", REG_EXPAND_SZ, "dead^%PATH^%beef", 17, 0);
550 
551     run_reg_exe("reg add HKCU\\" KEY_BASE " /t REG_EXPAND_SZ /v expand2 /f", &r);
552     ok(r == REG_EXIT_SUCCESS, "got exit code %u, expected 0\n", r);
553     verify_reg(hkey, "expand2", REG_EXPAND_SZ, "", 1, 0);
554 
555     run_reg_exe("reg add HKEY_CURRENT_USER\\" KEY_BASE " /ve /t REG_EXPAND_SZ /d WineTEST /f", &r);
556     ok(r == REG_EXIT_SUCCESS, "got exit code %u, expected 0\n", r);
557     verify_reg(hkey, "", REG_EXPAND_SZ, "WineTEST", 9, 0);
558 
559     run_reg_exe("reg add HKCU\\" KEY_BASE " /t REG_EXPAND_SZ /v expand3 /f /d \"\"", &r);
560     ok(r == REG_EXIT_SUCCESS, "got exit code %u, expected 0\n", r);
561     verify_reg(hkey, "expand3", REG_EXPAND_SZ, "", 1, 0);
562 
563     close_key(hkey);
564     delete_key(HKEY_CURRENT_USER, KEY_BASE, 0);
565 }
566 
test_reg_binary(void)567 static void test_reg_binary(void)
568 {
569     HKEY hkey;
570     DWORD r, dword, type, size;
571     char buffer[22];
572     LONG err;
573 
574     add_key(HKEY_CURRENT_USER, KEY_BASE, 0, &hkey);
575 
576     run_reg_exe("reg add HKCU\\" KEY_BASE " /t REG_BINARY /f", &r);
577     ok(r == REG_EXIT_SUCCESS, "got exit code %u, expected 0\n", r);
578     verify_reg(hkey, NULL, REG_BINARY, buffer, 0, 0);
579 
580     delete_value(hkey, NULL);
581 
582     run_reg_exe("reg add HKCU\\" KEY_BASE " /ve /t REG_BINARY /f", &r);
583     ok(r == REG_EXIT_SUCCESS, "got exit code %u, expected 0\n", r);
584     verify_reg(hkey, NULL, REG_BINARY, buffer, 0, 0);
585 
586     run_reg_exe("reg add HKEY_CURRENT_USER\\" KEY_BASE " /ve /t REG_BINARY /d deadbeef /f", &r);
587     ok(r == REG_EXIT_SUCCESS, "got exit code %u, expected 0\n", r);
588     dword = 0xefbeadde;
589     verify_reg(hkey, "", REG_BINARY, &dword, sizeof(DWORD), 0);
590 
591     run_reg_exe("reg add HKCU\\" KEY_BASE " /t REG_BINARY /v bin0 /f", &r);
592     ok(r == REG_EXIT_SUCCESS, "got exit code %u, expected 0\n", r);
593     verify_reg(hkey, "bin0", REG_BINARY, buffer, 0, 0);
594 
595     run_reg_exe("reg add HKCU\\" KEY_BASE " /t REG_BINARY /v bin1 /f /d 0xDeAdBeEf", &r);
596     ok(r == REG_EXIT_FAILURE, "got exit code %u, expected 1\n", r);
597 
598     run_reg_exe("reg add HKCU\\" KEY_BASE " /t REG_BINARY /v bin2 /f /d x01", &r);
599     ok(r == REG_EXIT_FAILURE, "got exit code %u, expected 1\n", r);
600 
601     run_reg_exe("reg add HKCU\\" KEY_BASE " /t REG_BINARY /v bin3 /f /d 01x", &r);
602     ok(r == REG_EXIT_FAILURE, "got exit code %u, expected 1\n", r);
603 
604     run_reg_exe("reg add HKCU\\" KEY_BASE " /t REG_BINARY /v bin4 /f /d DeAdBeEf0DD", &r);
605     ok(r == REG_EXIT_SUCCESS, "got exit code %u, expected 0\n", r);
606     /* Remaining nibble prefixed */
607     buffer[0] = 0x0d; buffer[1] = 0xea; buffer[2] = 0xdb;
608     buffer[3] = 0xee; buffer[4] = 0xf0; buffer[5] = 0xdd;
609     /* Remaining nibble suffixed on WinXP */
610     buffer[6] = 0xde; buffer[7] = 0xad; buffer[8] = 0xbe;
611     buffer[9] = 0xef; buffer[10] = 0x0d; buffer[11] = 0xd0;
612     size = 6;
613     err = RegQueryValueExA(hkey, "bin4", NULL, &type, (void *) (buffer+12), &size);
614     ok(err == ERROR_SUCCESS, "RegQueryValueEx failed: got %d\n", err);
615     ok(type == REG_BINARY, "got wrong type %u\n", type);
616     ok(size == 6, "got wrong size %u\n", size);
617     ok(memcmp(buffer, buffer+12, 6) == 0 ||
618         broken(memcmp(buffer+6, buffer+12, 6) == 0 /* WinXP */), "got wrong data\n");
619 
620     run_reg_exe("reg add HKCU\\" KEY_BASE " /t REG_BINARY /v bin5 /d \"\" /f", &r);
621     ok(r == REG_EXIT_SUCCESS, "got exit code %u, expected 0\n", r);
622     verify_reg(hkey, "bin5", REG_BINARY, buffer, 0, 0);
623 
624     run_reg_exe("reg add HKCU\\" KEY_BASE " /v bin6 /t REG_BINARY /f /d", &r);
625     ok(r == REG_EXIT_FAILURE, "got exit code %d, expected 1\n", r);
626 
627     close_key(hkey);
628     delete_key(HKEY_CURRENT_USER, KEY_BASE, 0);
629 }
630 
test_reg_dword(void)631 static void test_reg_dword(void)
632 {
633     HKEY hkey;
634     DWORD r, dword, type, size;
635     LONG err;
636 
637     add_key(HKEY_CURRENT_USER, KEY_BASE, 0, &hkey);
638 
639     run_reg_exe("reg add HKCU\\" KEY_BASE " /t REG_DWORD /f /d 12345678", &r);
640     ok(r == REG_EXIT_SUCCESS || broken(r == REG_EXIT_FAILURE /* WinXP */),
641        "got exit code %d, expected 0\n", r);
642     dword = 12345678;
643     if (r == REG_EXIT_SUCCESS)
644         verify_reg(hkey, "", REG_DWORD, &dword, sizeof(dword), 0);
645     else
646         win_skip("broken reg.exe detected\n");
647 
648     run_reg_exe("reg add HKCU\\" KEY_BASE " /ve /t REG_DWORD /f", &r);
649     ok(r == REG_EXIT_FAILURE || broken(r == REG_EXIT_SUCCESS /* WinXP */), "got exit code %u, expected 1\n", r);
650 
651     run_reg_exe("reg add HKCU\\" KEY_BASE " /v dword0 /t REG_DWORD /f /d", &r);
652     ok(r == REG_EXIT_FAILURE, "got exit code %d, expected 1\n", r);
653 
654     run_reg_exe("reg add HKCU\\" KEY_BASE " /v dword1 /t REG_DWORD /f", &r);
655     ok(r == REG_EXIT_FAILURE || broken(r == REG_EXIT_SUCCESS /* WinXP */),
656        "got exit code %d, expected 1\n", r);
657 
658     run_reg_exe("reg add HKCU\\" KEY_BASE " /v dword2 /t REG_DWORD /d zzz /f", &r);
659     ok(r == REG_EXIT_FAILURE, "got exit code %d, expected 1\n", r);
660 
661     run_reg_exe("reg add HKCU\\" KEY_BASE " /v dword3 /t REG_DWORD /d deadbeef /f", &r);
662     ok(r == REG_EXIT_FAILURE, "got exit code %d, expected 1\n", r);
663 
664     run_reg_exe("reg add HKCU\\" KEY_BASE " /v dword4 /t REG_DWORD /d 123xyz /f", &r);
665     ok(r == REG_EXIT_FAILURE, "got exit code %d, expected 1\n", r);
666 
667     run_reg_exe("reg add HKCU\\" KEY_BASE " /v dword5 /t reg_dword /d 12345678 /f", &r);
668     ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r);
669     dword = 12345678;
670     verify_reg(hkey, "dword5", REG_DWORD, &dword, sizeof(dword), 0);
671 
672     run_reg_exe("reg add HKCU\\" KEY_BASE " /v dword6 /t REG_DWORD /D 0123 /f", &r);
673     ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r);
674     size = sizeof(dword);
675     err = RegQueryValueExA(hkey, "dword6", NULL, &type, (LPBYTE)&dword, &size);
676     ok(err == ERROR_SUCCESS, "RegQueryValueEx failed: got %d\n", err);
677     ok(type == REG_DWORD, "got wrong type %d, expected %d\n", type, REG_DWORD);
678     ok(size == sizeof(DWORD), "got wrong size %d, expected %d\n", size, (int)sizeof(DWORD));
679     ok(dword == 123 || broken(dword == 0123 /* WinXP */), "got wrong data %d, expected 123\n", dword);
680 
681     run_reg_exe("reg add HKCU\\" KEY_BASE " /v dword7 /t reg_dword /d 0xabcdefg /f", &r);
682     ok(r == REG_EXIT_FAILURE, "got exit code %d, expected 1\n", r);
683 
684     run_reg_exe("reg add HKCU\\" KEY_BASE " /v dword8 /t REG_dword /d 0xdeadbeef /f", &r);
685     ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r);
686     dword = 0xdeadbeef;
687     verify_reg(hkey, "dword8", REG_DWORD, &dword, sizeof(dword), 0);
688 
689     run_reg_exe("reg add HKCU\\" KEY_BASE " /t REG_DWORD /v dword9 /f /d -1", &r);
690     ok(r == REG_EXIT_FAILURE || broken(r == REG_EXIT_SUCCESS /* WinXP */), "got exit code %u, expected 1\n", r);
691 
692     run_reg_exe("reg add HKCU\\" KEY_BASE " /t REG_DWORD /v dword10 /f /d -0x1", &r);
693     ok(r == REG_EXIT_FAILURE || broken(r == REG_EXIT_SUCCESS /* WinXP */), "got exit code %u, expected 1\n", r);
694 
695     run_reg_exe("reg add HKCU\\" KEY_BASE " /v dword11 /t REG_dword /d 0x01ffffffff /f", &r);
696     ok(r == REG_EXIT_FAILURE || broken(r == REG_EXIT_SUCCESS /* WinXP */), "got exit code %d, expected 1\n", r);
697 
698     run_reg_exe("reg add HKCU\\" KEY_BASE " /v dword12 /t REG_DWORD /d 0xffffffff /f", &r);
699     ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r);
700     dword = ~0u;
701     verify_reg(hkey, "dword12", REG_DWORD, &dword, sizeof(dword), 0);
702 
703     run_reg_exe("reg add HKCU\\" KEY_BASE " /v dword13 /t REG_DWORD /d 00x123 /f", &r);
704     ok(r == REG_EXIT_FAILURE, "got exit code %d, expected 1\n", r);
705 
706     run_reg_exe("reg add HKCU\\" KEY_BASE " /v dword14 /t REG_DWORD /d 0X123 /f", &r);
707     ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r);
708     dword = 0x123;
709     verify_reg(hkey, "dword14", REG_DWORD, &dword, sizeof(dword), 0);
710 
711     run_reg_exe("reg add HKCU\\" KEY_BASE " /v dword15 /t REG_DWORD /d 4294967296 /f", &r);
712     ok(r == REG_EXIT_FAILURE || broken(r == REG_EXIT_SUCCESS /* WinXP */), "got exit code %u, expected 1\n", r);
713 
714     run_reg_exe("reg add HKCU\\" KEY_BASE " /v dword16 /t REG_DWORD /d 456 /f", &r);
715     ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r);
716     dword = 456;
717     verify_reg(hkey, "dword16", REG_DWORD, &dword, sizeof(dword), 0);
718 
719     run_reg_exe("reg add HKCU\\" KEY_BASE " /v dword17 /t REG_DWORD /d 0x456 /f", &r);
720     ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r);
721     dword = 0x456;
722     verify_reg(hkey, "dword17", REG_DWORD, &dword, sizeof(dword), 0);
723 
724     /* REG_DWORD_LITTLE_ENDIAN */
725     run_reg_exe("reg add HKCU\\" KEY_BASE " /v DWORD_LE /t REG_DWORD_LITTLE_ENDIAN /d 456 /f", &r);
726     ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r);
727     dword = 456;
728     verify_reg(hkey, "DWORD_LE", REG_DWORD_LITTLE_ENDIAN, &dword, sizeof(dword), 0);
729 
730     close_key(hkey);
731     delete_key(HKEY_CURRENT_USER, KEY_BASE, 0);
732 }
733 
734 /* REG_DWORD_BIG_ENDIAN is broken in every version of Windows. It behaves
735  * like an ordinary REG_DWORD, which is little endian.
736  */
test_reg_dword_big_endian(void)737 static void test_reg_dword_big_endian(void)
738 {
739     HKEY hkey;
740     DWORD r, dword;
741 
742     run_reg_exe("reg add HKCU\\" KEY_BASE " /ve /t REG_DWORD_BIG_ENDIAN /f", &r);
743     ok(r == REG_EXIT_FAILURE || broken(r == REG_EXIT_SUCCESS /* WinXP */), "got exit code %d, expected 1\n", r);
744 
745     run_reg_exe("reg add HKCU\\" KEY_BASE " /v Test1 /t REG_DWORD_BIG_ENDIAN /f /d", &r);
746     ok(r == REG_EXIT_FAILURE, "got exit code %d, expected 1\n", r);
747 
748     run_reg_exe("reg add HKCU\\" KEY_BASE " /v Test2 /t REG_DWORD_BIG_ENDIAN /f", &r);
749     ok(r == REG_EXIT_FAILURE || broken(r == REG_EXIT_SUCCESS /* WinXP */), "got exit code %d, expected 1\n", r);
750 
751     add_key(HKEY_CURRENT_USER, KEY_BASE, 0, &hkey);
752 
753     run_reg_exe("reg add HKCU\\" KEY_BASE " /v Test3 /t REG_DWORD_BIG_ENDIAN /d 456 /f", &r);
754     ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r);
755     dword = 456;
756     verify_reg(hkey, "Test3", REG_DWORD_BIG_ENDIAN, &dword, sizeof(dword), 0);
757 
758     run_reg_exe("reg add HKCU\\" KEY_BASE " /v Test4 /t REG_DWORD_BIG_ENDIAN /d 0x456 /f", &r);
759     ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r);
760     dword = 0x456;
761     verify_reg(hkey, "Test4", REG_DWORD_BIG_ENDIAN, &dword, sizeof(dword), 0);
762 
763     close_key(hkey);
764     delete_key(HKEY_CURRENT_USER, KEY_BASE, 0);
765 }
766 
test_reg_multi_sz(void)767 static void test_reg_multi_sz(void)
768 {
769     HKEY hkey;
770     DWORD r;
771 
772     add_key(HKEY_CURRENT_USER, KEY_BASE, 0, &hkey);
773 
774     run_reg_exe("reg add HKCU\\" KEY_BASE " /t REG_MULTI_SZ /f", &r);
775     ok(r == REG_EXIT_SUCCESS, "got exit code %u, expected 0\n", r);
776     verify_reg(hkey, NULL, REG_MULTI_SZ, "", 1, 0);
777 
778     delete_value(hkey, NULL);
779 
780     run_reg_exe("reg add HKCU\\" KEY_BASE " /ve /t REG_MULTI_SZ /f", &r);
781     ok(r == REG_EXIT_SUCCESS, "got exit code %u, expected 0\n", r);
782     verify_reg(hkey, NULL, REG_MULTI_SZ, "", 1, 0);
783 
784     run_reg_exe("reg add HKCU\\" KEY_BASE " /v multi0 /t REG_MULTI_SZ /d \"three\\0little\\0strings\" /f", &r);
785     ok(r == REG_EXIT_SUCCESS, "got exit code %u, expected 0\n", r);
786     verify_reg(hkey, "multi0", REG_MULTI_SZ, "three\0little\0strings\0", 22, 0);
787 
788     run_reg_exe("reg add HKCU\\" KEY_BASE " /t REG_MULTI_SZ /v multi1 /s \"#\" /d \"three#little#strings\" /f", &r);
789     ok(r == REG_EXIT_SUCCESS, "got exit code %u, expected 0\n", r);
790     verify_reg(hkey, "multi1", REG_MULTI_SZ, "three\0little\0strings\0", 22, 0);
791 
792     run_reg_exe("reg add HKCU\\" KEY_BASE " /t REG_MULTI_SZ /v multi2 /d \"\" /f", &r);
793     ok(r == REG_EXIT_SUCCESS, "got exit code %u, expected 0\n", r);
794     verify_reg(hkey, "multi2", REG_MULTI_SZ, "", 1, 0);
795 
796     run_reg_exe("reg add HKCU\\" KEY_BASE " /t REG_MULTI_SZ /v multi3 /f", &r);
797     ok(r == REG_EXIT_SUCCESS, "got exit code %u, expected 0\n", r);
798     verify_reg(hkey, "multi3", REG_MULTI_SZ, "", 1, 0);
799 
800     run_reg_exe("reg add HKCU\\" KEY_BASE " /t REG_MULTI_SZ /v multi4 /s \"#\" /d \"threelittlestrings\" /f", &r);
801     ok(r == REG_EXIT_SUCCESS, "got exit code %u, expected 0\n", r);
802     verify_reg(hkey, "multi4", REG_MULTI_SZ, "threelittlestrings\0", 20, 0);
803 
804     run_reg_exe("reg add HKCU\\" KEY_BASE " /t REG_MULTI_SZ /v multi5 /s \"#randomgibberish\" /d \"three#little#strings\" /f", &r);
805     ok(r == REG_EXIT_FAILURE, "got exit code %u, expected 1\n", r);
806 
807     run_reg_exe("reg add HKCU\\" KEY_BASE " /t REG_MULTI_SZ /v multi6 /s \"\\0\" /d \"three\\0little\\0strings\" /f", &r);
808     ok(r == REG_EXIT_FAILURE, "got exit code %u, expected 1\n", r);
809 
810     run_reg_exe("reg add HKCU\\" KEY_BASE " /t REG_MULTI_SZ /v multi7 /s \"\" /d \"three#little#strings\" /f", &r);
811     ok(r == REG_EXIT_FAILURE, "got exit code %u, expected 1\n", r);
812 
813     run_reg_exe("reg add HKCU\\" KEY_BASE " /t REG_MULTI_SZ /v multi8 /s \"#\" /d \"##\" /f", &r);
814     ok(r == REG_EXIT_FAILURE, "got exit code %u, expected 1\n", r);
815 
816     run_reg_exe("reg add HKCU\\" KEY_BASE " /t REG_MULTI_SZ /v multi9 /s \"#\" /d \"two##strings\" /f", &r);
817     ok(r == REG_EXIT_FAILURE, "got exit code %u, expected 1\n", r);
818 
819     run_reg_exe("reg add HKCU\\" KEY_BASE " /t REG_MULTI_SZ /v multi10 /s \"#\" /d \"#a\" /f", &r);
820     ok(r == REG_EXIT_FAILURE, "got exit code %u, expected 1\n", r);
821 
822     run_reg_exe("reg add HKCU\\" KEY_BASE " /t REG_MULTI_SZ /v multi11 /s \"#\" /d \"a#\" /f", &r);
823     ok(r == REG_EXIT_SUCCESS, "got exit code %u, expected 0\n", r);
824     verify_reg(hkey, "multi11", REG_MULTI_SZ, "a\0", 3, 0);
825 
826     run_reg_exe("reg add HKCU\\" KEY_BASE " /v multi12 /t REG_MULTI_SZ /f /d", &r);
827     ok(r == REG_EXIT_FAILURE, "got exit code %d, expected 1\n", r);
828 
829     run_reg_exe("reg add HKCU\\" KEY_BASE " /v multi13 /t REG_MULTI_SZ /f /s", &r);
830     ok(r == REG_EXIT_FAILURE, "got exit code %d, expected 1\n", r);
831 
832     run_reg_exe("reg add HKCU\\" KEY_BASE " /v multi14 /t REG_MULTI_SZ /d \"\\0a\" /f", &r);
833     ok(r == REG_EXIT_FAILURE, "got exit code %u, expected 1\n", r);
834 
835     run_reg_exe("reg add HKCU\\" KEY_BASE " /v multi15 /t REG_MULTI_SZ /d \"a\\0\" /f", &r);
836     ok(r == REG_EXIT_SUCCESS, "got exit code %u, expected 0\n", r);
837     verify_reg(hkey, "multi15", REG_MULTI_SZ, "a\0", 3, 0);
838 
839     run_reg_exe("reg add HKCU\\" KEY_BASE " /t REG_MULTI_SZ /v multi16 /d \"two\\0\\0strings\" /f", &r);
840     ok(r == REG_EXIT_FAILURE, "got exit code %u, expected 1\n", r);
841 
842     run_reg_exe("reg add HKCU\\" KEY_BASE " /v multi17 /t REG_MULTI_SZ /s \"#\" /d \"#\" /f", &r);
843     ok(r == REG_EXIT_SUCCESS, "got exit code %u, expected 0\n", r);
844     verify_reg(hkey, "multi17", REG_MULTI_SZ, "\0", 2, 0);
845 
846     run_reg_exe("reg add HKCU\\" KEY_BASE " /v multi18 /t REG_MULTI_SZ /d \"\\0\" /f", &r);
847     ok(r == REG_EXIT_SUCCESS, "got exit code %u, expected 0\n", r);
848     verify_reg(hkey, "multi18", REG_MULTI_SZ, "\0", 2, 0);
849 
850     run_reg_exe("reg add HKCU\\" KEY_BASE " /v multi19 /t REG_MULTI_SZ /s \"#\" /d \"two\\0#strings\" /f", &r);
851     ok(r == REG_EXIT_SUCCESS, "got exit code %u, expected 0\n", r);
852     verify_reg(hkey, "multi19", REG_MULTI_SZ, "two\\0\0strings\0", 15, 0);
853 
854     run_reg_exe("reg add HKCU\\" KEY_BASE " /v multi20 /t REG_MULTI_SZ /s \"#\" /d \"two#\\0strings\" /f", &r);
855     ok(r == REG_EXIT_SUCCESS, "got exit code %u, expected 0\n", r);
856     verify_reg(hkey, "multi20", REG_MULTI_SZ, "two\0\\0strings\0", 15, 0);
857 
858     run_reg_exe("reg add HKCU\\" KEY_BASE " /v multi21 /t REG_MULTI_SZ /s \"#\" /d \"two\\0\\0strings\" /f", &r);
859     ok(r == REG_EXIT_SUCCESS, "got exit code %u, expected 0\n", r);
860     verify_reg(hkey, "multi21", REG_MULTI_SZ, "two\\0\\0strings\0", 16, 0);
861 
862     close_key(hkey);
863     delete_key(HKEY_CURRENT_USER, KEY_BASE, 0);
864 }
865 
866 #if 0
867 static void test_registry_view_win32(void)
868 {
869     HKEY hkey;
870     DWORD r;
871     BOOL is_wow64, is_win32;
872 
873     IsWow64Process(GetCurrentProcess(), &is_wow64);
874     is_win32 = !is_wow64 && (sizeof(void *) == sizeof(int));
875 
876     if (!is_win32) return;
877 
878     /* Try adding to the 32-bit registry view (32-bit Windows) */
879     run_reg_exe("reg add HKLM\\" KEY_BASE " /v Wine32 /d Test /f /reg:32", &r);
880     ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r);
881 
882     open_key(HKEY_LOCAL_MACHINE, KEY_BASE, KEY_WOW64_32KEY, &hkey);
883     verify_reg(hkey, "Wine32", REG_SZ, "Test", 5, 0);
884     close_key(hkey);
885 
886     open_key(HKEY_LOCAL_MACHINE, KEY_BASE, KEY_WOW64_64KEY, &hkey);
887     verify_reg(hkey, "Wine32", REG_SZ, "Test", 5, 0);
888     close_key(hkey);
889 
890     delete_key(HKEY_LOCAL_MACHINE, KEY_BASE, 0);
891 
892     /* Try adding to the 64-bit registry view, which doesn't exist on 32-bit Windows */
893     run_reg_exe("reg add HKLM\\" KEY_BASE " /v Wine64 /d Test /f /reg:64", &r);
894     ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r);
895 
896     open_key(HKEY_LOCAL_MACHINE, KEY_BASE, KEY_WOW64_64KEY, &hkey);
897     verify_reg(hkey, "Wine64", REG_SZ, "Test", 5, 0);
898     close_key(hkey);
899 
900     open_key(HKEY_LOCAL_MACHINE, KEY_BASE, KEY_WOW64_32KEY, &hkey);
901     verify_reg(hkey, "Wine64", REG_SZ, "Test", 5, 0);
902     close_key(hkey);
903 
904     delete_key(HKEY_LOCAL_MACHINE, KEY_BASE, 0);
905 }
906 
907 static void test_registry_view_win64(void)
908 {
909     HKEY hkey;
910     DWORD r;
911     BOOL is_wow64, is_win64;
912 
913     IsWow64Process(GetCurrentProcess(), &is_wow64);
914     is_win64 = !is_wow64 && (sizeof(void *) > sizeof(int));
915 
916     if (!is_win64) return;
917 
918     /* Try adding to the 32-bit registry view (64-bit Windows) */
919     run_reg_exe("reg add HKLM\\" KEY_BASE " /v Wine32 /d Test /f /reg:32", &r);
920     ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r);
921 
922     open_key(HKEY_LOCAL_MACHINE, KEY_BASE, KEY_WOW64_32KEY, &hkey);
923     verify_reg(hkey, "Wine32", REG_SZ, "Test", 5, 0);
924     close_key(hkey);
925     delete_key(HKEY_LOCAL_MACHINE, KEY_BASE, KEY_WOW64_32KEY);
926 
927     verify_key_nonexist(HKEY_LOCAL_MACHINE, KEY_BASE, KEY_WOW64_64KEY);
928 
929     /* Try adding to the 64-bit registry view (64-bit Windows) */
930     run_reg_exe("reg add HKLM\\" KEY_BASE " /v Wine64 /d Test /f /reg:64", &r);
931     ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r);
932 
933     open_key(HKEY_LOCAL_MACHINE, KEY_BASE, KEY_WOW64_64KEY, &hkey);
934     verify_reg(hkey, "Wine64", REG_SZ, "Test", 5, 0);
935     close_key(hkey);
936     delete_key(HKEY_LOCAL_MACHINE, KEY_BASE, KEY_WOW64_64KEY);
937 
938     verify_key_nonexist(HKEY_LOCAL_MACHINE, KEY_BASE, KEY_WOW64_32KEY);
939 }
940 
941 static void test_registry_view_wow64(void)
942 {
943     HKEY hkey;
944     DWORD r;
945     BOOL is_wow64;
946 
947     IsWow64Process(GetCurrentProcess(), &is_wow64);
948 
949     if (!is_wow64) return;
950 
951     /* Try adding to the 32-bit registry view (WOW64) */
952     run_reg_exe("reg add HKLM\\" KEY_BASE " /v Wine32 /d Test /f /reg:32", &r);
953     ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r);
954 
955     open_key(HKEY_LOCAL_MACHINE, KEY_BASE, KEY_WOW64_32KEY, &hkey);
956     verify_reg(hkey, "Wine32", REG_SZ, "Test", 5, 0);
957     close_key(hkey);
958     delete_key(HKEY_LOCAL_MACHINE, KEY_BASE, KEY_WOW64_32KEY);
959 
960     verify_key_nonexist(HKEY_LOCAL_MACHINE, KEY_BASE, KEY_WOW64_64KEY);
961 
962     /* Try adding to the 64-bit registry view (WOW64) */
963     run_reg_exe("reg add HKLM\\" KEY_BASE " /v Wine64 /d Test /f /reg:64", &r);
964     ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r);
965 
966     open_key(HKEY_LOCAL_MACHINE, KEY_BASE, KEY_WOW64_64KEY, &hkey);
967     verify_reg(hkey, "Wine64", REG_SZ, "Test", 5, 0);
968     close_key(hkey);
969     delete_key(HKEY_LOCAL_MACHINE, KEY_BASE, KEY_WOW64_64KEY);
970 
971     verify_key_nonexist(HKEY_LOCAL_MACHINE, KEY_BASE, KEY_WOW64_32KEY);
972 }
973 #endif
974 
START_TEST(add)975 START_TEST(add)
976 {
977     DWORD r;
978 
979     if (!run_reg_exe("reg.exe /?", &r)) {
980         win_skip("reg.exe not available, skipping 'add' tests\n");
981         return;
982     }
983 
984     test_command_syntax();
985     test_key_formats();
986     test_add();
987     test_reg_none();
988     test_reg_sz();
989     test_reg_expand_sz();
990     test_reg_binary();
991     test_reg_dword();
992     test_reg_dword_big_endian();
993     test_reg_multi_sz();
994 
995     /* Check if reg.exe is running with elevated privileges */
996     if (!is_elevated_process())
997     {
998         win_skip("reg.exe is not running with elevated privileges; "
999                  "skipping registry view tests\n");
1000         return;
1001     }
1002 
1003 #if 0
1004     test_registry_view_win32();
1005     test_registry_view_win64();
1006     test_registry_view_wow64();
1007 #endif
1008 
1009 }
1010