2 * Copyright 2014 Akihiro Sagawa
3 * Copyright 2016-2018, 2021 Hugh McMaster
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
22 static void read_from_pipe(HANDLE child_proc_stdout
, BYTE
*buf
, DWORD buf_size
)
29 ret
= ReadFile(child_proc_stdout
, buf
+ len
, buf_size
- len
, &read
, NULL
);
30 if (!ret
|| !read
) break;
38 #define read_reg_output(c,b,s,r) read_reg_output_(__FILE__,__LINE__,c,b,s,r)
39 static BOOL
read_reg_output_(const char *file
, unsigned line
, const char *cmd
,
40 BYTE
*buf
, DWORD buf_size
, DWORD
*rc
)
42 SECURITY_ATTRIBUTES sa
;
43 HANDLE pipe_stdout_rd
, pipe_stdout_wr
;
44 STARTUPINFOA si
= {0};
45 PROCESS_INFORMATION pi
;
50 sa
.nLength
= sizeof(SECURITY_ATTRIBUTES
);
51 sa
.bInheritHandle
= TRUE
;
52 sa
.lpSecurityDescriptor
= NULL
;
54 if (!CreatePipe(&pipe_stdout_rd
, &pipe_stdout_wr
, &sa
, 0))
57 if (!SetHandleInformation(pipe_stdout_rd
, HANDLE_FLAG_INHERIT
, 0))
61 si
.dwFlags
= STARTF_USESTDHANDLES
;
62 si
.hStdInput
= INVALID_HANDLE_VALUE
;
63 si
.hStdOutput
= pipe_stdout_wr
;
64 si
.hStdError
= INVALID_HANDLE_VALUE
;
67 if (!CreateProcessA(NULL
, cmdline
, NULL
, NULL
, TRUE
, 0, NULL
, NULL
, &si
, &pi
))
70 CloseHandle(pipe_stdout_wr
);
72 read_from_pipe(pipe_stdout_rd
, buf
, buf_size
);
74 ret
= WaitForSingleObject(pi
.hProcess
, 10000);
75 if (ret
== WAIT_TIMEOUT
)
76 TerminateProcess(pi
.hProcess
, 1);
78 bret
= GetExitCodeProcess(pi
.hProcess
, rc
);
79 lok(bret
, "GetExitCodeProcess failed: %d\n", GetLastError());
81 CloseHandle(pipe_stdout_rd
);
82 CloseHandle(pi
.hThread
);
83 CloseHandle(pi
.hProcess
);
87 #define compare_query(b,e,c,todo) compare_query_(__FILE__,__LINE__,b,e,c,todo)
88 static void compare_query_(const char *file
, unsigned line
, const BYTE
*buf
,
89 const char *expected
, BOOL cmp_len
, DWORD todo
)
91 const char *str
= (const char *)buf
;
92 const char *err
= "query output does not match expected output";
96 todo_wine_if (todo
& TODO_REG_COMPARE
)
97 lok(!strcmp(str
, expected
), "%s\n", err
);
101 todo_wine_if (todo
& TODO_REG_COMPARE
)
102 lok(!strncmp(str
, expected
, strlen(expected
)), "%s\n", err
);
108 static void test_query(void)
110 const char *test1
= "\r\n"
111 "HKEY_CURRENT_USER\\" KEY_BASE
"\r\n"
112 " Test1 REG_SZ Hello, World\r\n"
113 " Test2 REG_DWORD 0x123\r\n\r\n";
115 const char *test2
= "\r\n"
116 "HKEY_CURRENT_USER\\" KEY_BASE
"\r\n"
117 " Test1 REG_SZ Hello, World\r\n\r\n";
119 const char *test3
= "\r\n"
120 "HKEY_CURRENT_USER\\" KEY_BASE
"\r\n"
121 " Test1 REG_SZ Hello, World\r\n"
122 " Test2 REG_DWORD 0x123\r\n"
123 " Wine REG_SZ First instance\r\n\r\n"
124 "HKEY_CURRENT_USER\\" KEY_BASE
"\\subkey\r\n";
126 const char *test4
= "\r\n"
127 "HKEY_CURRENT_USER\\" KEY_BASE
"\\subkey\r\n"
128 " Test3 REG_SZ Some string data\r\n"
129 " Test4 REG_DWORD 0xabc\r\n\r\n";
131 const char *test5
= "\r\n"
132 "HKEY_CURRENT_USER\\" KEY_BASE
"\\subkey\r\n"
133 " Test4 REG_DWORD 0xabc\r\n\r\n";
135 const char *test6
= "\r\n"
136 "HKEY_CURRENT_USER\\" KEY_BASE
"\r\n"
137 " Test1 REG_SZ Hello, World\r\n"
138 " Test2 REG_DWORD 0x123\r\n"
139 " Wine REG_SZ First instance\r\n\r\n"
140 "HKEY_CURRENT_USER\\" KEY_BASE
"\\subkey\r\n"
141 " Test3 REG_SZ Some string data\r\n"
142 " Test4 REG_DWORD 0xabc\r\n"
143 " Wine REG_SZ Second instance\r\n\r\n";
145 const char *test7
= "\r\n"
146 "HKEY_CURRENT_USER\\" KEY_BASE
"\r\n"
147 " Wine REG_SZ First instance\r\n\r\n"
148 "HKEY_CURRENT_USER\\" KEY_BASE
"\\subkey\r\n"
149 " Wine REG_SZ Second instance\r\n\r\n";
151 DWORD r
, dword
= 0x123;
155 delete_tree(HKEY_CURRENT_USER
, KEY_BASE
);
156 verify_key_nonexist(HKEY_CURRENT_USER
, KEY_BASE
);
158 run_reg_exe("reg query", &r
);
159 ok(r
== REG_EXIT_FAILURE
, "got exit code %d, expected 1\n", r
);
161 run_reg_exe("reg query /?", &r
);
162 ok(r
== REG_EXIT_SUCCESS
, "got exit code %d, expected 0\n", r
);
164 run_reg_exe("reg query /h", &r
);
165 ok(r
== REG_EXIT_SUCCESS
, "got exit code %d, expected 0\n", r
);
167 run_reg_exe("reg query -H", &r
);
168 ok(r
== REG_EXIT_SUCCESS
, "got exit code %d, expected 0\n", r
);
170 /* Create a test key */
171 add_key(HKEY_CURRENT_USER
, KEY_BASE
, &key
);
172 add_value(key
, "Test1", REG_SZ
, "Hello, World", 13);
173 add_value(key
, "Test2", REG_DWORD
, &dword
, sizeof(dword
));
175 run_reg_exe("reg query HKCU\\" KEY_BASE
" /v", &r
);
176 ok(r
== REG_EXIT_FAILURE
, "got exit code %d, expected 1\n", r
);
178 run_reg_exe("reg query HKCU\\" KEY_BASE
" /v Missing", &r
);
179 ok(r
== REG_EXIT_FAILURE
, "got exit code %d, expected 1\n", r
);
181 run_reg_exe("reg query HKCU\\" KEY_BASE
" /v Test1 /v Test2", &r
);
182 ok(r
== REG_EXIT_FAILURE
, "got exit code %d, expected 1\n", r
);
184 run_reg_exe("reg query HKCU\\" KEY_BASE
" /v Test1 /ve", &r
);
185 ok(r
== REG_EXIT_FAILURE
, "got exit code %d, expected 1\n", r
);
187 run_reg_exe("reg query HKCU\\" KEY_BASE
" /s /s", &r
);
188 ok(r
== REG_EXIT_FAILURE
, "got exit code %d, expected 1\n", r
);
190 read_reg_output("reg query HKCU\\" KEY_BASE
, buf
, sizeof(buf
), &r
);
191 ok(r
== REG_EXIT_SUCCESS
, "got exit code %d, expected 0\n", r
);
192 compare_query(buf
, test1
, FALSE
, 0);
194 run_reg_exe("reg query HKCU\\" KEY_BASE
" /ve", &r
);
195 ok(r
== REG_EXIT_SUCCESS
|| broken(r
== REG_EXIT_FAILURE
/* WinXP */),
196 "got exit code %d, expected 0\n", r
);
198 read_reg_output("reg query HKCU\\" KEY_BASE
" /v Test1", buf
, sizeof(buf
), &r
);
199 ok(r
== REG_EXIT_SUCCESS
, "got exit code %d, expected 0\n", r
);
200 compare_query(buf
, test2
, FALSE
, 0);
202 run_reg_exe("reg query HKCU\\" KEY_BASE
" /v Test2", &r
);
203 ok(r
== REG_EXIT_SUCCESS
, "got exit code %d, expected 0\n", r
);
205 add_value(key
, "Wine", REG_SZ
, "First instance", 15);
207 /* Create a test subkey */
208 add_key(key
, "subkey", &subkey
);
210 read_reg_output("reg query HKCU\\" KEY_BASE
, buf
, sizeof(buf
), &r
);
211 ok(r
== REG_EXIT_SUCCESS
, "got exit code %d, expected 0\n", r
);
212 compare_query(buf
, test3
, FALSE
, TODO_REG_COMPARE
);
214 add_value(subkey
, "Test3", REG_SZ
, "Some string data", 16);
216 add_value(subkey
, "Test4", REG_DWORD
, &dword
, sizeof(dword
));
218 read_reg_output("reg query HKCU\\" KEY_BASE
"\\subkey", buf
, sizeof(buf
), &r
);
219 ok(r
== REG_EXIT_SUCCESS
, "got exit code %d, expected 0\n", r
);
220 compare_query(buf
, test4
, FALSE
, 0);
222 run_reg_exe("reg query HKCU\\" KEY_BASE
"\\subkey /v Test3", &r
);
223 ok(r
== REG_EXIT_SUCCESS
, "got exit code %d, expected 0\n", r
);
225 read_reg_output("reg query HKCU\\" KEY_BASE
"\\subkey /v Test4", buf
, sizeof(buf
), &r
);
226 ok(r
== REG_EXIT_SUCCESS
, "got exit code %d, expected 0\n", r
);
227 compare_query(buf
, test5
, FALSE
, 0);
229 add_value(subkey
, "Wine", REG_SZ
, "Second instance", 16);
232 read_reg_output("reg query HKCU\\" KEY_BASE
" /s", buf
, sizeof(buf
), &r
);
233 ok(r
== REG_EXIT_SUCCESS
, "got exit code %d, expected 0\n", r
);
234 compare_query(buf
, test6
, FALSE
, 0);
236 read_reg_output("reg query HKCU\\" KEY_BASE
" /v Wine /s", buf
, sizeof(buf
), &r
);
237 ok(r
== REG_EXIT_SUCCESS
|| r
== REG_EXIT_FAILURE
/* WinXP */,
238 "got exit code %d, expected 0\n", r
);
239 compare_query(buf
, test7
, TRUE
, 0);
241 add_value(key
, NULL
, REG_SZ
, "Empty", 6);
242 add_value(subkey
, NULL
, REG_SZ
, "Empty", 6);
245 run_reg_exe("reg query HKCU\\" KEY_BASE
"\\subkey /ve", &r
);
246 ok(r
== REG_EXIT_SUCCESS
, "got exit code %d, expected 0\n", r
);
248 run_reg_exe("reg query HKCU\\" KEY_BASE
" /ve /s", &r
);
249 ok(r
== REG_EXIT_SUCCESS
|| r
== REG_EXIT_FAILURE
/* WinXP */,
250 "got exit code %d, expected 0\n", r
);
252 /* Clean-up, then query */
253 delete_key(key
, "subkey");
256 run_reg_exe("reg query HKCU\\" KEY_BASE
"\\subkey", &r
);
257 ok(r
== REG_EXIT_FAILURE
, "got exit code %d, expected 1\n", r
);
259 delete_key(HKEY_CURRENT_USER
, KEY_BASE
);
261 run_reg_exe("reg query HKCU\\" KEY_BASE
, &r
);
262 ok(r
== REG_EXIT_FAILURE
, "got exit code %d, expected 1\n", r
);
269 if (!run_reg_exe("reg.exe /?", &r
)) {
270 win_skip("reg.exe not available, skipping 'query' tests\n");