xref: /reactos/modules/rostests/winetests/reg/query.c (revision a3bf868e)
17fcb8acaSwinesync /*
27fcb8acaSwinesync  * Copyright 2014 Akihiro Sagawa
37fcb8acaSwinesync  * Copyright 2016-2018, 2021 Hugh McMaster
47fcb8acaSwinesync  *
57fcb8acaSwinesync  * This library is free software; you can redistribute it and/or
67fcb8acaSwinesync  * modify it under the terms of the GNU Lesser General Public
77fcb8acaSwinesync  * License as published by the Free Software Foundation; either
87fcb8acaSwinesync  * version 2.1 of the License, or (at your option) any later version.
97fcb8acaSwinesync  *
107fcb8acaSwinesync  * This library is distributed in the hope that it will be useful,
117fcb8acaSwinesync  * but WITHOUT ANY WARRANTY; without even the implied warranty of
127fcb8acaSwinesync  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
137fcb8acaSwinesync  * Lesser General Public License for more details.
147fcb8acaSwinesync  *
157fcb8acaSwinesync  * You should have received a copy of the GNU Lesser General Public
167fcb8acaSwinesync  * License along with this library; if not, write to the Free Software
177fcb8acaSwinesync  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
187fcb8acaSwinesync  */
197fcb8acaSwinesync 
207fcb8acaSwinesync #include "reg_test.h"
217fcb8acaSwinesync 
225132d26cSwinesync static void read_from_pipe(HANDLE child_proc_stdout, BYTE *buf, DWORD buf_size)
235132d26cSwinesync {
245132d26cSwinesync     DWORD read, len = 0;
255132d26cSwinesync     BOOL ret;
265132d26cSwinesync 
275132d26cSwinesync     while (1)
285132d26cSwinesync     {
295132d26cSwinesync         ret = ReadFile(child_proc_stdout, buf + len, buf_size - len, &read, NULL);
305132d26cSwinesync         if (!ret || !read) break;
315132d26cSwinesync 
325132d26cSwinesync         len += read;
335132d26cSwinesync     }
345132d26cSwinesync 
355132d26cSwinesync     buf[len] = 0;
365132d26cSwinesync }
375132d26cSwinesync 
385132d26cSwinesync #define read_reg_output(c,b,s,r) read_reg_output_(__FILE__,__LINE__,c,b,s,r)
395132d26cSwinesync static BOOL read_reg_output_(const char *file, unsigned line, const char *cmd,
405132d26cSwinesync                              BYTE *buf, DWORD buf_size, DWORD *rc)
415132d26cSwinesync {
425132d26cSwinesync     SECURITY_ATTRIBUTES sa;
435132d26cSwinesync     HANDLE pipe_stdout_rd, pipe_stdout_wr;
445132d26cSwinesync     STARTUPINFOA si = {0};
455132d26cSwinesync     PROCESS_INFORMATION pi;
465132d26cSwinesync     char cmdline[256];
475132d26cSwinesync     BOOL bret;
485132d26cSwinesync     DWORD ret;
495132d26cSwinesync 
505132d26cSwinesync     sa.nLength = sizeof(SECURITY_ATTRIBUTES);
515132d26cSwinesync     sa.bInheritHandle = TRUE;
525132d26cSwinesync     sa.lpSecurityDescriptor = NULL;
535132d26cSwinesync 
545132d26cSwinesync     if (!CreatePipe(&pipe_stdout_rd, &pipe_stdout_wr, &sa, 0))
555132d26cSwinesync         return FALSE;
565132d26cSwinesync 
575132d26cSwinesync     if (!SetHandleInformation(pipe_stdout_rd, HANDLE_FLAG_INHERIT, 0))
585132d26cSwinesync         return FALSE;
595132d26cSwinesync 
605132d26cSwinesync     si.cb = sizeof(si);
615132d26cSwinesync     si.dwFlags = STARTF_USESTDHANDLES;
625132d26cSwinesync     si.hStdInput = INVALID_HANDLE_VALUE;
635132d26cSwinesync     si.hStdOutput = pipe_stdout_wr;
645132d26cSwinesync     si.hStdError = INVALID_HANDLE_VALUE;
655132d26cSwinesync 
665132d26cSwinesync     strcpy(cmdline, cmd);
675132d26cSwinesync     if (!CreateProcessA(NULL, cmdline, NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi))
685132d26cSwinesync         return FALSE;
695132d26cSwinesync 
705132d26cSwinesync     CloseHandle(pipe_stdout_wr);
715132d26cSwinesync 
725132d26cSwinesync     read_from_pipe(pipe_stdout_rd, buf, buf_size);
735132d26cSwinesync 
745132d26cSwinesync     ret = WaitForSingleObject(pi.hProcess, 10000);
755132d26cSwinesync     if (ret == WAIT_TIMEOUT)
765132d26cSwinesync         TerminateProcess(pi.hProcess, 1);
775132d26cSwinesync 
785132d26cSwinesync     bret = GetExitCodeProcess(pi.hProcess, rc);
795132d26cSwinesync     lok(bret, "GetExitCodeProcess failed: %d\n", GetLastError());
805132d26cSwinesync 
815132d26cSwinesync     CloseHandle(pipe_stdout_rd);
825132d26cSwinesync     CloseHandle(pi.hThread);
835132d26cSwinesync     CloseHandle(pi.hProcess);
845132d26cSwinesync     return bret;
855132d26cSwinesync }
865132d26cSwinesync 
87e77afe91Swinesync #define compare_query(b,e,c,todo) compare_query_(__FILE__,__LINE__,b,e,c,todo)
885132d26cSwinesync static void compare_query_(const char *file, unsigned line, const BYTE *buf,
89e77afe91Swinesync                            const char *expected, BOOL cmp_len, DWORD todo)
90e77afe91Swinesync {
91e77afe91Swinesync     const char *str = (const char *)buf;
92e77afe91Swinesync     const char *err = "query output does not match expected output";
93e77afe91Swinesync 
94e77afe91Swinesync     if (!cmp_len)
955132d26cSwinesync     {
965132d26cSwinesync         todo_wine_if (todo & TODO_REG_COMPARE)
97e77afe91Swinesync             lok(!strcmp(str, expected), "%s\n", err);
98e77afe91Swinesync     }
99e77afe91Swinesync     else
100e77afe91Swinesync     {
101e77afe91Swinesync         todo_wine_if (todo & TODO_REG_COMPARE)
102e77afe91Swinesync             lok(!strncmp(str, expected, strlen(expected)), "%s\n", err);
103e77afe91Swinesync     }
1045132d26cSwinesync }
1055132d26cSwinesync 
1065132d26cSwinesync /* Unit tests */
1075132d26cSwinesync 
1087fcb8acaSwinesync static void test_query(void)
1097fcb8acaSwinesync {
1105132d26cSwinesync     const char *test1 = "\r\n"
1115132d26cSwinesync         "HKEY_CURRENT_USER\\" KEY_BASE "\r\n"
1125132d26cSwinesync         "    Test1    REG_SZ    Hello, World\r\n"
1135132d26cSwinesync         "    Test2    REG_DWORD    0x123\r\n\r\n";
1145132d26cSwinesync 
1155132d26cSwinesync     const char *test2 = "\r\n"
1165132d26cSwinesync         "HKEY_CURRENT_USER\\" KEY_BASE "\r\n"
1175132d26cSwinesync         "    Test1    REG_SZ    Hello, World\r\n\r\n";
1185132d26cSwinesync 
1195132d26cSwinesync     const char *test3 = "\r\n"
1205132d26cSwinesync         "HKEY_CURRENT_USER\\" KEY_BASE "\r\n"
1215132d26cSwinesync         "    Test1    REG_SZ    Hello, World\r\n"
1225132d26cSwinesync         "    Test2    REG_DWORD    0x123\r\n"
1235132d26cSwinesync         "    Wine    REG_SZ    First instance\r\n\r\n"
1245132d26cSwinesync         "HKEY_CURRENT_USER\\" KEY_BASE "\\subkey\r\n";
1255132d26cSwinesync 
1265132d26cSwinesync     const char *test4 = "\r\n"
1275132d26cSwinesync         "HKEY_CURRENT_USER\\" KEY_BASE "\\subkey\r\n"
1285132d26cSwinesync         "    Test3    REG_SZ    Some string data\r\n"
1295132d26cSwinesync         "    Test4    REG_DWORD    0xabc\r\n\r\n";
1305132d26cSwinesync 
1315132d26cSwinesync     const char *test5 = "\r\n"
1325132d26cSwinesync         "HKEY_CURRENT_USER\\" KEY_BASE "\\subkey\r\n"
1335132d26cSwinesync         "    Test4    REG_DWORD    0xabc\r\n\r\n";
1345132d26cSwinesync 
135e77afe91Swinesync     const char *test6 = "\r\n"
136e77afe91Swinesync         "HKEY_CURRENT_USER\\" KEY_BASE "\r\n"
137e77afe91Swinesync         "    Test1    REG_SZ    Hello, World\r\n"
138e77afe91Swinesync         "    Test2    REG_DWORD    0x123\r\n"
139e77afe91Swinesync         "    Wine    REG_SZ    First instance\r\n\r\n"
140e77afe91Swinesync         "HKEY_CURRENT_USER\\" KEY_BASE "\\subkey\r\n"
141e77afe91Swinesync         "    Test3    REG_SZ    Some string data\r\n"
142e77afe91Swinesync         "    Test4    REG_DWORD    0xabc\r\n"
143e77afe91Swinesync         "    Wine    REG_SZ    Second instance\r\n\r\n";
144e77afe91Swinesync 
145e77afe91Swinesync     const char *test7 = "\r\n"
146e77afe91Swinesync         "HKEY_CURRENT_USER\\" KEY_BASE "\r\n"
147e77afe91Swinesync         "    Wine    REG_SZ    First instance\r\n\r\n"
148e77afe91Swinesync         "HKEY_CURRENT_USER\\" KEY_BASE "\\subkey\r\n"
149e77afe91Swinesync         "    Wine    REG_SZ    Second instance\r\n\r\n";
150e77afe91Swinesync 
1514771673cSwinesync     const char *test8a = "\r\n"
1524771673cSwinesync         "HKEY_CURRENT_USER\\" KEY_BASE "\\subkey1\r\n"
1534771673cSwinesync         "HKEY_CURRENT_USER\\" KEY_BASE "\\subkey2\r\n"
1544771673cSwinesync         "HKEY_CURRENT_USER\\" KEY_BASE "\\subkey3\r\n"
1554771673cSwinesync         "HKEY_CURRENT_USER\\" KEY_BASE "\\subkey4\r\n";
1564771673cSwinesync 
1574771673cSwinesync     const char *test8b = "\r\n"
1584771673cSwinesync         "HKEY_CURRENT_USER\\" KEY_BASE "\\subkey1\r\n\r\n"
1594771673cSwinesync         "HKEY_CURRENT_USER\\" KEY_BASE "\\subkey2\r\n\r\n"
1604771673cSwinesync         "HKEY_CURRENT_USER\\" KEY_BASE "\\subkey3\r\n\r\n"
1614771673cSwinesync         "HKEY_CURRENT_USER\\" KEY_BASE "\\subkey4\r\n\r\n";
1624771673cSwinesync 
163a12c8448Swinesync     DWORD r, dword = 0x123;
164d552b44fSwinesync     HKEY hkey, subkey;
1655132d26cSwinesync     BYTE buf[512];
1667fcb8acaSwinesync 
1677fcb8acaSwinesync     delete_tree(HKEY_CURRENT_USER, KEY_BASE);
1687fcb8acaSwinesync     verify_key_nonexist(HKEY_CURRENT_USER, KEY_BASE);
1697fcb8acaSwinesync 
1707fcb8acaSwinesync     run_reg_exe("reg query", &r);
1717fcb8acaSwinesync     ok(r == REG_EXIT_FAILURE, "got exit code %d, expected 1\n", r);
1727fcb8acaSwinesync 
1737fcb8acaSwinesync     run_reg_exe("reg query /?", &r);
1747fcb8acaSwinesync     ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r);
1757fcb8acaSwinesync 
1767fcb8acaSwinesync     run_reg_exe("reg query /h", &r);
1777fcb8acaSwinesync     ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r);
1787fcb8acaSwinesync 
1797fcb8acaSwinesync     run_reg_exe("reg query -H", &r);
1807fcb8acaSwinesync     ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r);
1817fcb8acaSwinesync 
1822535ff3fSwinesync     /* Key not present */
1832535ff3fSwinesync     run_reg_exe("reg query HKCU\\" KEY_BASE, &r);
1842535ff3fSwinesync     ok(r == REG_EXIT_FAILURE, "got exit code %d, expected 1\n", r);
1852535ff3fSwinesync 
1867fcb8acaSwinesync     /* Create a test key */
187d552b44fSwinesync     add_key(HKEY_CURRENT_USER, KEY_BASE, &hkey);
188d552b44fSwinesync     add_value(hkey, "Test1", REG_SZ, "Hello, World", 13);
189d552b44fSwinesync     add_value(hkey, "Test2", REG_DWORD, &dword, sizeof(dword));
1907fcb8acaSwinesync 
1917fcb8acaSwinesync     run_reg_exe("reg query HKCU\\" KEY_BASE " /v", &r);
1927fcb8acaSwinesync     ok(r == REG_EXIT_FAILURE, "got exit code %d, expected 1\n", r);
1937fcb8acaSwinesync 
1947fcb8acaSwinesync     run_reg_exe("reg query HKCU\\" KEY_BASE " /v Missing", &r);
1957fcb8acaSwinesync     ok(r == REG_EXIT_FAILURE, "got exit code %d, expected 1\n", r);
1967fcb8acaSwinesync 
197a12c8448Swinesync     run_reg_exe("reg query HKCU\\" KEY_BASE " /v Test1 /v Test2", &r);
198b12d7980Swinesync     ok(r == REG_EXIT_FAILURE, "got exit code %d, expected 1\n", r);
199b12d7980Swinesync 
200a12c8448Swinesync     run_reg_exe("reg query HKCU\\" KEY_BASE " /v Test1 /ve", &r);
201b12d7980Swinesync     ok(r == REG_EXIT_FAILURE, "got exit code %d, expected 1\n", r);
202b12d7980Swinesync 
203b12d7980Swinesync     run_reg_exe("reg query HKCU\\" KEY_BASE " /s /s", &r);
204b12d7980Swinesync     ok(r == REG_EXIT_FAILURE, "got exit code %d, expected 1\n", r);
205b12d7980Swinesync 
2065132d26cSwinesync     read_reg_output("reg query HKCU\\" KEY_BASE, buf, sizeof(buf), &r);
207a12c8448Swinesync     ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r);
208e77afe91Swinesync     compare_query(buf, test1, FALSE, 0);
209a12c8448Swinesync 
210b12d7980Swinesync     run_reg_exe("reg query HKCU\\" KEY_BASE " /ve", &r);
211b12d7980Swinesync     ok(r == REG_EXIT_SUCCESS || broken(r == REG_EXIT_FAILURE /* WinXP */),
212b12d7980Swinesync        "got exit code %d, expected 0\n", r);
213b12d7980Swinesync 
2145132d26cSwinesync     read_reg_output("reg query HKCU\\" KEY_BASE " /v Test1", buf, sizeof(buf), &r);
215b12d7980Swinesync     ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r);
216e77afe91Swinesync     compare_query(buf, test2, FALSE, 0);
217b12d7980Swinesync 
218a12c8448Swinesync     run_reg_exe("reg query HKCU\\" KEY_BASE " /v Test2", &r);
2197fcb8acaSwinesync     ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r);
2207fcb8acaSwinesync 
221d552b44fSwinesync     add_value(hkey, "Wine", REG_SZ, "First instance", 15);
2227fcb8acaSwinesync 
2237fcb8acaSwinesync     /* Create a test subkey */
224d552b44fSwinesync     add_key(hkey, "subkey", &subkey);
2255132d26cSwinesync 
2265132d26cSwinesync     read_reg_output("reg query HKCU\\" KEY_BASE, buf, sizeof(buf), &r);
2275132d26cSwinesync     ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r);
228*a3bf868eSwinesync     compare_query(buf, test3, FALSE, 0);
2295132d26cSwinesync 
230a12c8448Swinesync     add_value(subkey, "Test3", REG_SZ, "Some string data", 16);
231a12c8448Swinesync     dword = 0xabc;
232a12c8448Swinesync     add_value(subkey, "Test4", REG_DWORD, &dword, sizeof(dword));
2337fcb8acaSwinesync 
2345132d26cSwinesync     read_reg_output("reg query HKCU\\" KEY_BASE "\\subkey", buf, sizeof(buf), &r);
2357fcb8acaSwinesync     ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r);
236e77afe91Swinesync     compare_query(buf, test4, FALSE, 0);
2377fcb8acaSwinesync 
238a12c8448Swinesync     run_reg_exe("reg query HKCU\\" KEY_BASE "\\subkey /v Test3", &r);
2397fcb8acaSwinesync     ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r);
2407fcb8acaSwinesync 
2415132d26cSwinesync     read_reg_output("reg query HKCU\\" KEY_BASE "\\subkey /v Test4", buf, sizeof(buf), &r);
2427fcb8acaSwinesync     ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r);
243e77afe91Swinesync     compare_query(buf, test5, FALSE, 0);
2447fcb8acaSwinesync 
245a12c8448Swinesync     add_value(subkey, "Wine", REG_SZ, "Second instance", 16);
2467fcb8acaSwinesync 
2477fcb8acaSwinesync     /* Test recursion */
248e77afe91Swinesync     read_reg_output("reg query HKCU\\" KEY_BASE " /s", buf, sizeof(buf), &r);
2497fcb8acaSwinesync     ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r);
250e77afe91Swinesync     compare_query(buf, test6, FALSE, 0);
2517fcb8acaSwinesync 
25216cc1ad7Swinesync     read_reg_output("reg query HKCU\\" KEY_BASE "\\ /s", buf, sizeof(buf), &r);
25316cc1ad7Swinesync     ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r);
254a0060cdcSwinesync     compare_query(buf, test6, FALSE, 0);
25516cc1ad7Swinesync 
256e77afe91Swinesync     read_reg_output("reg query HKCU\\" KEY_BASE " /v Wine /s", buf, sizeof(buf), &r);
2577fcb8acaSwinesync     ok(r == REG_EXIT_SUCCESS || r == REG_EXIT_FAILURE /* WinXP */,
2587fcb8acaSwinesync        "got exit code %d, expected 0\n", r);
259e77afe91Swinesync     compare_query(buf, test7, TRUE, 0);
2607fcb8acaSwinesync 
261d552b44fSwinesync     add_value(hkey, NULL, REG_SZ, "Empty", 6);
262a12c8448Swinesync     add_value(subkey, NULL, REG_SZ, "Empty", 6);
263a12c8448Swinesync     close_key(subkey);
264d552b44fSwinesync     close_key(hkey);
265a12c8448Swinesync 
266a12c8448Swinesync     run_reg_exe("reg query HKCU\\" KEY_BASE "\\subkey /ve", &r);
267a12c8448Swinesync     ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r);
268a12c8448Swinesync 
2697fcb8acaSwinesync     run_reg_exe("reg query HKCU\\" KEY_BASE " /ve /s", &r);
2707fcb8acaSwinesync     ok(r == REG_EXIT_SUCCESS || r == REG_EXIT_FAILURE /* WinXP */,
2717fcb8acaSwinesync        "got exit code %d, expected 0\n", r);
2727fcb8acaSwinesync 
2732535ff3fSwinesync     delete_tree(HKEY_CURRENT_USER, KEY_BASE);
2744771673cSwinesync 
2754771673cSwinesync     /* Subkeys only */
2764771673cSwinesync     add_key(HKEY_CURRENT_USER, KEY_BASE, &hkey);
2774771673cSwinesync     add_key(hkey, "subkey1", NULL);
2784771673cSwinesync     add_key(hkey, "subkey2", NULL);
2794771673cSwinesync     add_key(hkey, "subkey3", NULL);
2804771673cSwinesync     add_key(hkey, "subkey4", NULL);
2814771673cSwinesync     close_key(hkey);
2824771673cSwinesync 
2834771673cSwinesync     read_reg_output("reg query HKCU\\" KEY_BASE, buf, sizeof(buf), &r);
2844771673cSwinesync     ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r);
2854771673cSwinesync     compare_query(buf, test8a, FALSE, TODO_REG_COMPARE);
2864771673cSwinesync 
2874771673cSwinesync     read_reg_output("reg query HKCU\\" KEY_BASE " /s", buf, sizeof(buf), &r);
2884771673cSwinesync     ok(r == REG_EXIT_SUCCESS, "got exit code %d, expected 0\n", r);
2894771673cSwinesync     compare_query(buf, test8b, FALSE, TODO_REG_COMPARE);
2904771673cSwinesync 
2914771673cSwinesync     delete_tree(HKEY_CURRENT_USER, KEY_BASE);
2927fcb8acaSwinesync }
2937fcb8acaSwinesync 
2947fcb8acaSwinesync START_TEST(query)
2957fcb8acaSwinesync {
2967fcb8acaSwinesync     DWORD r;
2977fcb8acaSwinesync 
2987fcb8acaSwinesync     if (!run_reg_exe("reg.exe /?", &r)) {
2997fcb8acaSwinesync         win_skip("reg.exe not available, skipping 'query' tests\n");
3007fcb8acaSwinesync         return;
3017fcb8acaSwinesync     }
3027fcb8acaSwinesync 
3037fcb8acaSwinesync     test_query();
3047fcb8acaSwinesync }
305