2 * Copyright 2023 Zhiyi Zhang for CodeWeavers
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 MAX_BUFFER 65536
24 static char stdout_buffer
[MAX_BUFFER
], stderr_buffer
[MAX_BUFFER
];
25 static DWORD stdout_size
, stderr_size
;
27 static void read_all_from_handle(HANDLE handle
, char *buffer
, DWORD
*size
)
32 memset(buffer
, 0, MAX_BUFFER
);
36 BOOL success
= ReadFile(handle
, bytes
, sizeof(bytes
), &bytes_read
, NULL
);
37 if (!success
|| !bytes_read
)
39 if (*size
+ bytes_read
> MAX_BUFFER
)
41 ok(FALSE
, "Insufficient buffer.\n");
44 memcpy(buffer
+ *size
, bytes
, bytes_read
);
49 static void write_to_handle(HANDLE handle
, const char *str
, int len
)
53 WriteFile(handle
, str
, len
, &dummy
, NULL
);
56 #define run_find_stdin(a, b, c) _run_find_stdin(__FILE__, __LINE__, a, b, c)
57 static void _run_find_stdin(const char *file
, int line
, const char *commandline
, const char *input
,
58 int exitcode_expected
)
60 HANDLE parent_stdin_write
, parent_stdout_read
, parent_stderr_read
;
61 HANDLE child_stdin_read
, child_stdout_write
, child_stderr_write
;
62 SECURITY_ATTRIBUTES security_attributes
= {0};
63 PROCESS_INFORMATION process_info
= {0};
64 STARTUPINFOA startup_info
= {0};
68 security_attributes
.nLength
= sizeof(SECURITY_ATTRIBUTES
);
69 security_attributes
.bInheritHandle
= TRUE
;
71 CreatePipe(&child_stdin_read
, &parent_stdin_write
, &security_attributes
, 0);
72 CreatePipe(&parent_stdout_read
, &child_stdout_write
, &security_attributes
, 0);
73 CreatePipe(&parent_stderr_read
, &child_stderr_write
, &security_attributes
, 0);
75 SetHandleInformation(parent_stdin_write
, HANDLE_FLAG_INHERIT
, 0);
76 SetHandleInformation(parent_stdout_read
, HANDLE_FLAG_INHERIT
, 0);
77 SetHandleInformation(parent_stderr_read
, HANDLE_FLAG_INHERIT
, 0);
79 startup_info
.cb
= sizeof(STARTUPINFOA
);
80 startup_info
.hStdInput
= child_stdin_read
;
81 startup_info
.hStdOutput
= child_stdout_write
;
82 startup_info
.hStdError
= child_stderr_write
;
83 startup_info
.dwFlags
|= STARTF_USESTDHANDLES
;
85 sprintf(cmd
, "findstr.exe %s", commandline
);
87 CreateProcessA(NULL
, cmd
, NULL
, NULL
, TRUE
, 0, NULL
, NULL
, &startup_info
, &process_info
);
88 CloseHandle(child_stdin_read
);
89 CloseHandle(child_stdout_write
);
90 CloseHandle(child_stderr_write
);
92 write_to_handle(parent_stdin_write
, input
, lstrlenA(input
));
93 CloseHandle(parent_stdin_write
);
95 read_all_from_handle(parent_stdout_read
, stdout_buffer
, &stdout_size
);
96 read_all_from_handle(parent_stderr_read
, stderr_buffer
, &stderr_size
);
97 CloseHandle(parent_stdout_read
);
98 CloseHandle(parent_stderr_read
);
100 WaitForSingleObject(process_info
.hProcess
, INFINITE
);
101 GetExitCodeProcess(process_info
.hProcess
, &exitcode
);
102 CloseHandle(process_info
.hProcess
);
103 CloseHandle(process_info
.hThread
);
104 ok_(file
, line
)(exitcode
== exitcode_expected
, "Expected exitcode %d, got %ld\n",
105 exitcode_expected
, exitcode
);
108 #define run_find_file(a, b, c) _run_find_file(__FILE__, __LINE__, a, b, c)
109 static void _run_find_file(const char *file
, int line
, const char *commandline
, const char *input
,
110 int exitcode_expected
)
112 char path_temp_file
[MAX_PATH
], path_temp_dir
[MAX_PATH
], commandline_new
[MAX_PATH
];
115 GetTempPathA(ARRAY_SIZE(path_temp_dir
), path_temp_dir
);
116 GetTempFileNameA(path_temp_dir
, "", 0, path_temp_file
);
117 handle_file
= CreateFileA(path_temp_file
, GENERIC_WRITE
, 0, NULL
, CREATE_ALWAYS
, 0, NULL
);
118 write_to_handle(handle_file
, input
, lstrlenA(input
));
119 CloseHandle(handle_file
);
121 sprintf(commandline_new
, "%s %s", commandline
, path_temp_file
);
122 _run_find_stdin(file
, line
, commandline_new
, "", exitcode_expected
);
124 DeleteFileA(path_temp_file
);
127 static void test_basic(void)
132 run_find_stdin("", "", 2);
133 ok(stdout_size
== 0, "Unexpected stdout buffer size %ld.\n", stdout_size
);
134 ok(stderr_size
> 0, "Unexpected stderr buffer size %ld.\n", stderr_size
);
135 ret
= strcmp(stderr_buffer
, "FINDSTR: Bad command line\r\n");
136 ok(!ret
, "Got the wrong result.\n");
139 run_find_stdin("/?", "", 0);
140 ok(stdout_size
> 0, "Unexpected stdout buffer size %ld.\n", stdout_size
);
141 ok(stderr_size
== 0, "Unexpected stderr buffer size %ld.\n", stderr_size
);
143 /* find string in stdin */
144 run_find_stdin("abc", "abc", 0);
145 ok(stdout_size
> 0, "Unexpected stdout buffer size %ld.\n", stdout_size
);
146 ok(stderr_size
== 0, "Unexpected stderr buffer size %ld.\n", stderr_size
);
147 ret
= strcmp(stdout_buffer
, "abc\r\n");
148 ok(!ret
, "Got the wrong result.\n");
150 /* find string in stdin fails */
151 run_find_stdin("abc", "cba", 1);
152 ok(stdout_size
== 0, "Unexpected stdout buffer size %ld.\n", stdout_size
);
153 ok(stderr_size
== 0, "Unexpected stderr buffer size %ld.\n", stderr_size
);
155 /* find string in file */
156 run_find_file("abc", "abc", 0);
157 ok(stdout_size
> 0, "Unexpected stdout buffer size %ld.\n", stdout_size
);
158 ok(stderr_size
== 0, "Unexpected stderr buffer size %ld.\n", stderr_size
);
159 ret
= strcmp(stdout_buffer
, "abc");
160 ok(!ret
, "Got the wrong result.\n");
162 /* find string in file fails */
163 run_find_file("abc", "cba", 1);
164 ok(stdout_size
== 0, "Unexpected stdout buffer size %ld.\n", stdout_size
);
165 ok(stderr_size
== 0, "Unexpected stderr buffer size %ld.\n", stderr_size
);
167 /* find string in stdin with space separator */
168 run_find_stdin("\"abc cba\"", "abc", 0);
169 ok(stdout_size
> 0, "Unexpected stdout buffer size %ld.\n", stdout_size
);
170 ok(stderr_size
== 0, "Unexpected stderr buffer size %ld.\n", stderr_size
);
171 ret
= strcmp(stdout_buffer
, "abc\r\n");
172 ok(!ret
, "Got the wrong result.\n");
174 /* find string in stdin with /C: */
175 run_find_stdin("/C:abc", "abc", 0);
176 ok(stdout_size
> 0, "Unexpected stdout buffer size %ld.\n", stdout_size
);
177 ok(stderr_size
== 0, "Unexpected stderr buffer size %ld.\n", stderr_size
);
178 ret
= strcmp(stdout_buffer
, "abc\r\n");
179 ok(!ret
, "Got the wrong result.\n");
181 /* find string in stdin with /C:"abc" */
182 run_find_stdin("/C:\"abc\"", "abc", 0);
183 ok(stdout_size
> 0, "Unexpected stdout buffer size %ld.\n", stdout_size
);
184 ok(stderr_size
== 0, "Unexpected stderr buffer size %ld.\n", stderr_size
);
185 ret
= strcmp(stdout_buffer
, "abc\r\n");
186 ok(!ret
, "Got the wrong result.\n");
188 /* find string in stdin with /C:"abc cba" fails */
189 run_find_stdin("/C:\"abc cba\"", "abc", 1);
190 ok(stdout_size
== 0, "Unexpected stdout buffer size %ld.\n", stdout_size
);
191 ok(stderr_size
== 0, "Unexpected stderr buffer size %ld.\n", stderr_size
);
193 /* find string in stdin with /C: fails */
194 run_find_stdin("/C:abc", "cba", 1);
195 ok(stdout_size
== 0, "Unexpected stdout buffer size %ld.\n", stdout_size
);
196 ok(stderr_size
== 0, "Unexpected stderr buffer size %ld.\n", stderr_size
);
201 if (PRIMARYLANGID(GetUserDefaultUILanguage()) != LANG_ENGLISH
)
203 skip("Tests only work with English locale.\n");