2 * Copyright 2014 Akihiro Sagawa
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.
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.
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
20 #include "wine/test.h"
22 #define lok ok_(__FILE__,line)
23 #define KEY_BASE "Software\\Wine\\reg_test"
24 #define REG_EXIT_SUCCESS 0
25 #define REG_EXIT_FAILURE 1
26 #define TODO_REG_TYPE (0x0001u)
27 #define TODO_REG_SIZE (0x0002u)
28 #define TODO_REG_DATA (0x0004u)
30 #define run_reg_exe(c,r) run_reg_exe_(__LINE__,c,r)
31 static BOOL
run_reg_exe_(unsigned line
, const char *cmd
, DWORD
*rc
)
33 STARTUPINFOA si
= {sizeof(STARTUPINFOA
)};
34 PROCESS_INFORMATION pi
;
39 si
.dwFlags
= STARTF_USESTDHANDLES
;
40 si
.hStdInput
= INVALID_HANDLE_VALUE
;
41 si
.hStdOutput
= INVALID_HANDLE_VALUE
;
42 si
.hStdError
= INVALID_HANDLE_VALUE
;
45 if (!CreateProcessA(NULL
, cmdline
, NULL
, NULL
, TRUE
, 0, NULL
, NULL
, &si
, &pi
))
48 ret
= WaitForSingleObject(pi
.hProcess
, 10000);
49 if (ret
== WAIT_TIMEOUT
)
50 TerminateProcess(pi
.hProcess
, 1);
52 bret
= GetExitCodeProcess(pi
.hProcess
, rc
);
53 lok(bret
, "GetExitCodeProcess failed: %d\n", GetLastError());
55 CloseHandle(pi
.hThread
);
56 CloseHandle(pi
.hProcess
);
60 #define verify_reg(k,v,t,d,s,todo) verify_reg_(__LINE__,k,v,t,d,s,todo)
61 static void verify_reg_(unsigned line
, HKEY hkey
, const char* value
,
62 DWORD exp_type
, const void *exp_data
, DWORD exp_size
, DWORD todo
)
69 memset(data
, 0xdd, size
);
70 err
= RegQueryValueExA(hkey
, value
, NULL
, &type
, data
, &size
);
71 lok(err
== ERROR_SUCCESS
, "RegQueryValueEx failed: got %d\n", err
);
72 if (err
!= ERROR_SUCCESS
)
75 if (todo
& TODO_REG_TYPE
)
76 todo_wine
lok(type
== exp_type
, "got wrong type %d, expected %d\n", type
, exp_type
);
78 lok(type
== exp_type
, "got wrong type %d, expected %d\n", type
, exp_type
);
79 if (todo
& TODO_REG_SIZE
)
80 todo_wine
lok(size
== exp_size
, "got wrong size %d, expected %d\n", size
, exp_size
);
82 lok(size
== exp_size
, "got wrong size %d, expected %d\n", size
, exp_size
);
83 if (todo
& TODO_REG_DATA
)
84 todo_wine
lok(memcmp(data
, exp_data
, size
) == 0, "got wrong data\n");
86 lok(memcmp(data
, exp_data
, size
) == 0, "got wrong data\n");
89 static void test_add(void)
93 DWORD r
, dword
, type
, size
;
96 run_reg_exe("reg add", &r
);
97 ok(r
== REG_EXIT_FAILURE
, "got exit code %d, expected 1\n", r
);
99 err
= RegDeleteKeyA(HKEY_CURRENT_USER
, KEY_BASE
);
100 ok(err
== ERROR_SUCCESS
|| err
== ERROR_FILE_NOT_FOUND
, "got %d\n", err
);
102 err
= RegOpenKeyExA(HKEY_CURRENT_USER
, KEY_BASE
, 0, KEY_READ
, &hkey
);
103 ok(err
== ERROR_FILE_NOT_FOUND
, "got %d\n", err
);
105 run_reg_exe("reg add HKCU\\" KEY_BASE
" /f", &r
);
106 ok(r
== REG_EXIT_SUCCESS
, "got exit code %d, expected 0\n", r
);
108 err
= RegOpenKeyExA(HKEY_CURRENT_USER
, KEY_BASE
, 0, KEY_READ
, &hkey
);
109 ok(err
== ERROR_SUCCESS
, "key creation failed, got %d\n", err
);
112 run_reg_exe("reg add HKCU\\" KEY_BASE
" /d WineTest /f", &r
);
113 ok(r
== REG_EXIT_SUCCESS
|| broken(r
== REG_EXIT_FAILURE
/* WinXP */),
114 "got exit code %d, expected 0\n", r
);
115 if (r
== REG_EXIT_SUCCESS
)
116 verify_reg(hkey
, "", REG_SZ
, "WineTest", 9, 0);
118 win_skip("broken reg.exe detected\n");
120 run_reg_exe("reg add HKCU\\" KEY_BASE
" /v test /d deadbeef /f", &r
);
121 ok(r
== REG_EXIT_SUCCESS
, "got exit code %d, expected 0\n", r
);
122 verify_reg(hkey
, "test", REG_SZ
, "deadbeef", 9, 0);
124 run_reg_exe("reg add HKCU\\" KEY_BASE
" /v test /f", &r
);
125 ok(r
== REG_EXIT_SUCCESS
, "got exit code %d, expected 0\n", r
);
126 verify_reg(hkey
, "test", REG_SZ
, "", 1, TODO_REG_SIZE
);
128 run_reg_exe("reg add HKEY_CURRENT_USER\\" KEY_BASE
" /ve /d WineTEST /f", &r
);
129 ok(r
== REG_EXIT_SUCCESS
, "got exit code %d, expected 0\n", r
);
130 verify_reg(hkey
, "", REG_SZ
, "WineTEST", 9, 0);
132 run_reg_exe("reg add HKCU\\" KEY_BASE
" /t REG_SZ /v test2 /f", &r
);
133 ok(r
== REG_EXIT_SUCCESS
, "got exit code %d, expected 0\n", r
);
134 verify_reg(hkey
, "test2", REG_SZ
, "", 1, TODO_REG_SIZE
);
136 run_reg_exe("reg add HKCU\\" KEY_BASE
" /t REG_SZ /v test3 /f /d \"\"", &r
);
137 ok(r
== REG_EXIT_SUCCESS
, "got exit code %d, expected 0\n", r
);
138 verify_reg(hkey
, "test3", REG_SZ
, "", 1, 0);
141 run_reg_exe("reg add HKCU\\" KEY_BASE
" /v expand0 /t REG_EXpand_sz /d \"dead%PATH%beef\" /f", &r
);
142 ok(r
== REG_EXIT_SUCCESS
, "got exit code %u\n", r
);
143 verify_reg(hkey
, "expand0", REG_EXPAND_SZ
, "dead%PATH%beef", 15, TODO_REG_SIZE
);
145 run_reg_exe("reg add HKCU\\" KEY_BASE
" /v expand1 /t REG_EXpand_sz /d \"dead^%PATH^%beef\" /f", &r
);
146 ok(r
== REG_EXIT_SUCCESS
, "got exit code %u\n", r
);
147 verify_reg(hkey
, "expand1", REG_EXPAND_SZ
, "dead^%PATH^%beef", 17, TODO_REG_SIZE
);
149 run_reg_exe("reg add HKCU\\" KEY_BASE
" /t REG_EXPAND_SZ /v expand2 /f", &r
);
150 ok(r
== REG_EXIT_SUCCESS
, "got exit code %u\n", r
);
151 verify_reg(hkey
, "expand2", REG_EXPAND_SZ
, "", 1, TODO_REG_SIZE
);
153 run_reg_exe("reg add HKEY_CURRENT_USER\\" KEY_BASE
" /ve /t REG_EXPAND_SZ /d WineTEST /f", &r
);
154 ok(r
== REG_EXIT_SUCCESS
, "got exit code %u\n", r
);
155 verify_reg(hkey
, "", REG_EXPAND_SZ
, "WineTEST", 9, TODO_REG_SIZE
);
157 run_reg_exe("reg add HKCU\\" KEY_BASE
" /t REG_EXPAND_SZ /v expand3 /f /d \"\"", &r
);
158 ok(r
== REG_EXIT_SUCCESS
, "got exit code %u\n", r
);
159 verify_reg(hkey
, "expand3", REG_EXPAND_SZ
, "", 1, TODO_REG_SIZE
);
162 run_reg_exe("reg add HKCU\\" KEY_BASE
" /t REG_BINARY /v bin0 /f", &r
);
163 ok(r
== REG_EXIT_SUCCESS
, "got exit code %u\n", r
);
164 verify_reg(hkey
, "bin0", REG_BINARY
, buffer
, 0, 0);
166 run_reg_exe("reg add HKEY_CURRENT_USER\\" KEY_BASE
" /ve /t REG_BINARY /d deadbeef /f", &r
);
167 ok(r
== REG_EXIT_SUCCESS
, "got exit code %u\n", r
);
169 verify_reg(hkey
, "", REG_BINARY
, &dword
, sizeof(DWORD
), TODO_REG_SIZE
);
171 run_reg_exe("reg add HKCU\\" KEY_BASE
" /t REG_BINARY /v bin1 /f /d 0xDeAdBeEf", &r
);
172 todo_wine
ok(r
== REG_EXIT_FAILURE
, "got exit code %u\n", r
);
173 run_reg_exe("reg add HKCU\\" KEY_BASE
" /t REG_BINARY /v bin2 /f /d x01", &r
);
174 todo_wine
ok(r
== REG_EXIT_FAILURE
, "got exit code %u\n", r
);
175 run_reg_exe("reg add HKCU\\" KEY_BASE
" /t REG_BINARY /v bin3 /f /d 01x", &r
);
176 todo_wine
ok(r
== REG_EXIT_FAILURE
, "got exit code %u\n", r
);
178 run_reg_exe("reg add HKCU\\" KEY_BASE
" /t REG_BINARY /v bin4 /f /d DeAdBeEf0DD", &r
);
179 ok(r
== REG_EXIT_SUCCESS
, "got exit code %u\n", r
);
180 /* Remaining nibble prefixed */
181 buffer
[0] = 0x0d; buffer
[1] = 0xea; buffer
[2] = 0xdb;
182 buffer
[3] = 0xee; buffer
[4] = 0xf0; buffer
[5] = 0xdd;
183 /* Remaining nibble suffixed on winXP */
184 buffer
[6] = 0xde; buffer
[7] = 0xad; buffer
[8] = 0xbe;
185 buffer
[9] = 0xef; buffer
[10] = 0x0d; buffer
[11] = 0xd0;
187 err
= RegQueryValueExA(hkey
, "bin4", NULL
, &type
, (void *) (buffer
+12), &size
);
188 ok(err
== ERROR_SUCCESS
, "RegQueryValueEx failed: got %d\n", err
);
189 ok(type
== REG_BINARY
, "got wrong type %u\n", type
);
190 todo_wine
ok(size
== 6, "got wrong size %u\n", size
);
191 todo_wine
ok(memcmp(buffer
, buffer
+12, 6) == 0 ||
192 broken(memcmp(buffer
+6, buffer
+12, 6) == 0 /* WinXP */), "got wrong data\n");
195 run_reg_exe("reg add HKCU\\" KEY_BASE
" /t REG_DWORD /f /d 12345678", &r
);
196 ok(r
== REG_EXIT_SUCCESS
|| broken(r
== REG_EXIT_FAILURE
/* WinXP */),
197 "got exit code %d, expected 0\n", r
);
199 if (r
== REG_EXIT_SUCCESS
)
200 verify_reg(hkey
, "", REG_DWORD
, &dword
, sizeof(dword
), 0);
202 win_skip("broken reg.exe detected\n");
204 run_reg_exe("reg add HKCU\\" KEY_BASE
" /v dword1 /t REG_DWORD /f", &r
);
205 todo_wine
ok(r
== REG_EXIT_FAILURE
|| broken(r
== REG_EXIT_SUCCESS
/* WinXP */),
206 "got exit code %d, expected 0\n", r
);
207 run_reg_exe("reg add HKCU\\" KEY_BASE
" /v dword2 /t REG_DWORD /d zzz /f", &r
);
208 todo_wine
ok(r
== REG_EXIT_FAILURE
, "got exit code %d, expected 1\n", r
);
209 run_reg_exe("reg add HKCU\\" KEY_BASE
" /v dword3 /t REG_DWORD /d deadbeef /f", &r
);
210 todo_wine
ok(r
== REG_EXIT_FAILURE
, "got exit code %d, expected 1\n", r
);
211 run_reg_exe("reg add HKCU\\" KEY_BASE
" /v dword4 /t REG_DWORD /d 123xyz /f", &r
);
212 todo_wine
ok(r
== REG_EXIT_FAILURE
, "got exit code %d, expected 1\n", r
);
214 run_reg_exe("reg add HKCU\\" KEY_BASE
" /v dword5 /t reg_dword /d 12345678 /f", &r
);
215 ok(r
== REG_EXIT_SUCCESS
, "got exit code %d, expected 0\n", r
);
217 verify_reg(hkey
, "dword5", REG_DWORD
, &dword
, sizeof(dword
), 0);
219 run_reg_exe("reg add HKCU\\" KEY_BASE
" /v dword6 /t REG_DWORD /D 0123 /f", &r
);
220 ok(r
== REG_EXIT_SUCCESS
, "got exit code %d, expected 0\n", r
);
221 size
= sizeof(dword
);
222 err
= RegQueryValueExA(hkey
, "dword6", NULL
, &type
, (LPBYTE
)&dword
, &size
);
223 ok(err
== ERROR_SUCCESS
, "RegQueryValueEx failed: got %d\n", err
);
224 ok(type
== REG_DWORD
, "got wrong type %d, expected %d\n", type
, REG_DWORD
);
225 ok(size
== sizeof(DWORD
), "got wrong size %d, expected %d\n", size
, (int)sizeof(DWORD
));
226 todo_wine
ok(dword
== 123 || broken(dword
== 0123 /* WinXP */),
227 "got wrong data %d, expected %d\n", dword
, 123);
229 run_reg_exe("reg add HKCU\\" KEY_BASE
" /v dword7 /t reg_dword /d 0xabcdefg /f", &r
);
230 todo_wine
ok(r
== REG_EXIT_FAILURE
, "got exit code %d, expected 1\n", r
);
232 run_reg_exe("reg add HKCU\\" KEY_BASE
" /v dword8 /t REG_dword /d 0xdeadbeef /f", &r
);
233 ok(r
== REG_EXIT_SUCCESS
, "got exit code %d, expected 0\n", r
);
235 verify_reg(hkey
, "dword8", REG_DWORD
, &dword
, sizeof(dword
),
236 (sizeof(long) > sizeof(DWORD
)) ? 0 : TODO_REG_DATA
);
238 run_reg_exe("reg add HKCU\\" KEY_BASE
" /t REG_DWORD /v dword9 /f /d -1", &r
);
239 todo_wine
ok(r
== REG_EXIT_FAILURE
|| broken(r
== REG_EXIT_SUCCESS
/* WinXP */), "got exit code %u\n", r
);
240 run_reg_exe("reg add HKCU\\" KEY_BASE
" /t REG_DWORD /v dword10 /f /d -0x1", &r
);
241 todo_wine
ok(r
== REG_EXIT_FAILURE
|| broken(r
== REG_EXIT_SUCCESS
/* WinXP */), "got exit code %u\n", r
);
243 /* REG_DWORD_LITTLE_ENDIAN */
244 run_reg_exe("reg add HKCU\\" KEY_BASE
" /v DWORD_LE /t REG_DWORD_LITTLE_ENDIAN /d 456 /f", &r
);
245 ok(r
== REG_EXIT_SUCCESS
, "got exit code %d, expected 0\n", r
);
247 verify_reg(hkey
, "DWORD_LE", REG_DWORD_LITTLE_ENDIAN
, &dword
, sizeof(dword
), 0);
250 run_reg_exe("reg add HKCU\\" KEY_BASE
" /v multi0 /t REG_MULTI_SZ /d \"three\\0little\\0strings\" /f", &r
);
251 ok(r
== REG_EXIT_SUCCESS
, "got exit code %u\n", r
);
252 memcpy(buffer
, "three\0little\0strings\0", 22);
253 verify_reg(hkey
, "multi0", REG_MULTI_SZ
, buffer
, 22, TODO_REG_SIZE
);
255 run_reg_exe("reg add HKCU\\" KEY_BASE
" /t REG_MULTI_SZ /v multi1 /s \"#\" /d \"three#little#strings\" /f", &r
);
256 ok(r
== REG_EXIT_SUCCESS
, "got exit code %u\n", r
);
257 verify_reg(hkey
, "multi1", REG_MULTI_SZ
, buffer
, 22, TODO_REG_SIZE
);
259 run_reg_exe("reg add HKCU\\" KEY_BASE
" /t REG_MULTI_SZ /v multi2 /d \"\" /f", &r
);
260 ok(r
== REG_EXIT_SUCCESS
, "got exit code %u\n", r
);
261 verify_reg(hkey
, "multi2", REG_MULTI_SZ
, &buffer
[21], 1, TODO_REG_SIZE
);
263 run_reg_exe("reg add HKCU\\" KEY_BASE
" /t REG_MULTI_SZ /v multi3 /f", &r
);
264 ok(r
== REG_EXIT_SUCCESS
, "got exit code %u\n", r
);
265 verify_reg(hkey
, "multi3", REG_MULTI_SZ
, &buffer
[21], 1, TODO_REG_SIZE
);
267 run_reg_exe("reg add HKCU\\" KEY_BASE
" /t REG_MULTI_SZ /v multi4 /s \"#\" /d \"threelittlestrings\" /f", &r
);
268 ok(r
== REG_EXIT_SUCCESS
, "got exit code %u\n", r
);
269 verify_reg(hkey
, "multi4", REG_MULTI_SZ
, "threelittlestrings\0", 20, TODO_REG_SIZE
);
271 run_reg_exe("reg add HKCU\\" KEY_BASE
" /t REG_MULTI_SZ /v multi5 /s \"#randomgibberish\" /d \"three#little#strings\" /f", &r
);
272 todo_wine
ok(r
== REG_EXIT_FAILURE
, "got exit code %u\n", r
);
273 run_reg_exe("reg add HKCU\\" KEY_BASE
" /t REG_MULTI_SZ /v multi6 /s \"\\0\" /d \"three\\0little\\0strings\" /f", &r
);
274 todo_wine
ok(r
== REG_EXIT_FAILURE
, "got exit code %u\n", r
);
275 run_reg_exe("reg add HKCU\\" KEY_BASE
" /t REG_MULTI_SZ /v multi7 /s \"\" /d \"three#little#strings\" /f", &r
);
276 todo_wine
ok(r
== REG_EXIT_FAILURE
, "got exit code %u\n", r
);
277 run_reg_exe("reg add HKCU\\" KEY_BASE
" /t REG_MULTI_SZ /v multi8 /s \"#\" /d \"##\" /f", &r
);
278 todo_wine
ok(r
== REG_EXIT_FAILURE
, "got exit code %u\n", r
);
279 run_reg_exe("reg add HKCU\\" KEY_BASE
" /t REG_MULTI_SZ /v multi9 /s \"#\" /d \"two##strings\" /f", &r
);
280 todo_wine
ok(r
== REG_EXIT_FAILURE
, "got exit code %u\n", r
);
281 run_reg_exe("reg add HKCU\\" KEY_BASE
" /t REG_MULTI_SZ /v multi10 /s \"#\" /d \"#a\" /f", &r
);
282 todo_wine
ok(r
== REG_EXIT_FAILURE
, "got exit code %u\n", r
);
284 run_reg_exe("reg add HKCU\\" KEY_BASE
" /t REG_MULTI_SZ /v multi11 /s \"#\" /d \"a#\" /f", &r
);
285 ok(r
== REG_EXIT_SUCCESS
, "got exit code %u\n", r
);
286 buffer
[0]='a'; buffer
[1]=0; buffer
[2]=0;
287 verify_reg(hkey
, "multi11", REG_MULTI_SZ
, buffer
, 3, TODO_REG_SIZE
);
291 err
= RegDeleteKeyA(HKEY_CURRENT_USER
, KEY_BASE
);
292 ok(err
== ERROR_SUCCESS
, "got %d\n", err
);
295 static void test_delete(void)
300 const DWORD deadbeef
= 0xdeadbeef;
302 run_reg_exe("reg delete", &r
);
303 ok(r
== REG_EXIT_FAILURE
, "got exit code %d, expected 1\n", r
);
305 err
= RegCreateKeyExA(HKEY_CURRENT_USER
, KEY_BASE
, 0, NULL
, 0, KEY_ALL_ACCESS
, NULL
, &hkey
, NULL
);
306 ok(err
== ERROR_SUCCESS
, "got %d\n", err
);
308 err
= RegSetValueExA(hkey
, "foo", 0, REG_DWORD
, (LPBYTE
)&deadbeef
, sizeof(deadbeef
));
309 ok(err
== ERROR_SUCCESS
, "got %d\n" ,err
);
311 err
= RegSetValueExA(hkey
, "bar", 0, REG_DWORD
, (LPBYTE
)&deadbeef
, sizeof(deadbeef
));
312 ok(err
== ERROR_SUCCESS
, "got %d\n" ,err
);
314 err
= RegSetValueExA(hkey
, "", 0, REG_DWORD
, (LPBYTE
)&deadbeef
, sizeof(deadbeef
));
315 ok(err
== ERROR_SUCCESS
, "got %d\n" ,err
);
317 err
= RegCreateKeyExA(hkey
, "subkey", 0, NULL
, 0, KEY_ALL_ACCESS
, NULL
, &hsubkey
, NULL
);
318 ok(err
== ERROR_SUCCESS
, "got %d\n" ,err
);
319 RegCloseKey(hsubkey
);
321 run_reg_exe("reg delete HKCU\\" KEY_BASE
" /v bar /f", &r
);
322 ok(r
== REG_EXIT_SUCCESS
, "got exit code %d, expected 0\n", r
);
323 err
= RegQueryValueExA(hkey
, "bar", NULL
, NULL
, NULL
, NULL
);
324 ok(err
== ERROR_FILE_NOT_FOUND
, "got %d\n", err
);
326 run_reg_exe("reg delete HKCU\\" KEY_BASE
" /ve /f", &r
);
327 ok(r
== REG_EXIT_SUCCESS
, "got exit code %d, expected 0\n", r
);
328 err
= RegQueryValueExA(hkey
, "", NULL
, NULL
, NULL
, NULL
);
329 todo_wine
ok(err
== ERROR_FILE_NOT_FOUND
, "got %d\n", err
);
331 run_reg_exe("reg delete HKCU\\" KEY_BASE
" /va /f", &r
);
332 ok(r
== REG_EXIT_SUCCESS
, "got exit code %d, expected 0\n", r
);
333 err
= RegQueryValueExA(hkey
, "foo", NULL
, NULL
, NULL
, NULL
);
334 ok(err
== ERROR_FILE_NOT_FOUND
, "got %d\n", err
);
335 err
= RegOpenKeyExA(hkey
, "subkey", 0, KEY_READ
, &hsubkey
);
336 ok(err
== ERROR_SUCCESS
, "got %d\n", err
);
337 RegCloseKey(hsubkey
);
340 run_reg_exe("reg delete HKCU\\" KEY_BASE
" /f", &r
);
341 ok(r
== REG_EXIT_SUCCESS
, "got exit code %d, expected 0\n", r
);
342 err
= RegOpenKeyExA(HKEY_CURRENT_USER
, KEY_BASE
, 0, KEY_READ
, &hkey
);
343 ok(err
== ERROR_FILE_NOT_FOUND
, "got %d\n", err
);
346 static void test_query(void)
349 run_reg_exe("reg Query", &r
);
350 ok(r
== REG_EXIT_FAILURE
, "got exit code %d, expected 1\n", r
);
356 if (!run_reg_exe("reg.exe /?", &r
)) {
357 win_skip("reg.exe not available, skipping reg.exe tests\n");