1 /*
2 * PROJECT: ReactOS API tests
3 * LICENSE: LGPL-2.1+ (https://spdx.org/licenses/LGPL-2.1+)
4 * PURPOSE: Test for fc.exe
5 * COPYRIGHT: Copyright 2021 Katayama Hirofumi MZ <katayama.hirofumi.mz@gmail.com>
6 */
7
8 #include "precomp.h"
9 #include <stdlib.h>
10 #include <stdio.h>
11 #include <string.h>
12 #include <shlwapi.h>
13
14 typedef struct TEST_ENTRY
15 {
16 INT lineno;
17 INT ret;
18 LPCSTR cmdline;
19 LPCSTR file1_data;
20 LPCSTR file2_data;
21 INT file1_size; // -1 for zero-terminated
22 INT file2_size; // -1 for zero-terminated
23 LPCSTR output;
24 } TEST_ENTRY;
25
26 #define FILE1 "fc-test1.txt"
27 #define FILE2 "fc-test2.txt"
28 #define FILES " " FILE1 " " FILE2
29 #define COMPARING "Comparing files fc-test1.txt and FC-TEST2.TXT\n"
30 #define NO_DIFF "FC: no differences encountered\n"
31 #define RESYNC_FAILED "Resync Failed. Files are too different.\n"
32
33 static const TEST_ENTRY s_entries[] =
34 {
35 /* binary comparison */
36 {
37 __LINE__, 0, "fc /B" FILES, "", "", -1, -1, COMPARING
38 NO_DIFF
39 },
40 {
41 __LINE__, 1, "fc /B" FILES, "A", "B", -1, -1, COMPARING
42 "00000000: 41 42\n"
43 },
44 {
45 __LINE__, 1, "fc /B" FILES, "B", "A", -1, -1, COMPARING
46 "00000000: 42 41\n"
47 },
48 {
49 __LINE__, 0, "fc /B" FILES, "AB", "AB", -1, -1, COMPARING
50 NO_DIFF
51 },
52 {
53 __LINE__, 1, "fc /B" FILES, "AB", "BA", -1, -1, COMPARING
54 "00000000: 41 42\n"
55 "00000001: 42 41\n"
56 },
57 {
58 __LINE__, 0, "fc /B" FILES, "ABC", "ABC", -1, -1, COMPARING
59 NO_DIFF
60 },
61 {
62 __LINE__, 1, "fc /B" FILES, "ABC", "ABCD", -1, -1, COMPARING
63 "FC: FC-TEST2.TXT longer than fc-test1.txt\n\n"
64 },
65 {
66 __LINE__, 1, "fc /B" FILES, "ABC", "ABDD", -1, -1, COMPARING
67 "00000002: 43 44\n"
68 "FC: FC-TEST2.TXT longer than fc-test1.txt\n"
69 },
70 {
71 __LINE__, 1, "fc /B /C" FILES, "ABC", "abc", -1, -1, COMPARING
72 "00000000: 41 61\n"
73 "00000001: 42 62\n"
74 "00000002: 43 63\n"
75 },
76 /* text comparison */
77 {
78 __LINE__, 0, "fc" FILES, "", "", -1, -1, COMPARING
79 NO_DIFF
80 },
81 {
82 __LINE__, 1, "fc" FILES, "A", "B", -1, -1, COMPARING
83 "***** fc-test1.txt\nA\n"
84 "***** FC-TEST2.TXT\nB\n"
85 "*****\n\n"
86 },
87 {
88 __LINE__, 1, "fc" FILES, "B", "A", -1, -1, COMPARING
89 "***** fc-test1.txt\nB\n"
90 "***** FC-TEST2.TXT\nA\n"
91 "*****\n\n"
92 },
93 {
94 __LINE__, 0, "fc" FILES, "AB", "AB", -1, -1, COMPARING
95 NO_DIFF
96 },
97 {
98 __LINE__, 1, "fc" FILES, "AB", "BA", -1, -1, COMPARING
99 "***** fc-test1.txt\nAB\n"
100 "***** FC-TEST2.TXT\nBA\n"
101 "*****\n\n"
102 },
103 {
104 __LINE__, 0, "fc" FILES, "ABC", "ABC", -1, -1, COMPARING
105 NO_DIFF
106 },
107 {
108 __LINE__, 0, "fc /C" FILES, "ABC", "abc", -1, -1, COMPARING
109 NO_DIFF
110 },
111 {
112 __LINE__, 1, "fc" FILES, "A\nB\nC\nD\nE\n", "A\nB\nB\nD\nE\n", -1, -1, COMPARING
113 "***** fc-test1.txt\nB\nC\nD\n"
114 "***** FC-TEST2.TXT\nB\nB\nD\n"
115 "*****\n\n"
116 },
117 /* Test /A */
118 {
119 __LINE__, 1, "fc /A" FILES, "A\nB\nC\nD\nE\n", "B\nB\nC\nD\nE\n", -1, -1, COMPARING
120 "***** fc-test1.txt\nA\nB\n"
121 "***** FC-TEST2.TXT\nB\nB\n"
122 "*****\n\n"
123 },
124 {
125 __LINE__, 1, "fc /A" FILES, "A\nB\nC\nD\nE\n", "C\nC\nC\nD\nE\n", -1, -1, COMPARING
126 "***** fc-test1.txt\nA\nB\nC\n"
127 "***** FC-TEST2.TXT\nC\nC\nC\n"
128 "*****\n\n"
129 },
130 {
131 __LINE__, 1, "fc /A" FILES, "A\nB\nC\nD\nE\n", "A\nC\nC\nD\nE\n", -1, -1, COMPARING
132 "***** fc-test1.txt\nA\nB\nC\n"
133 "***** FC-TEST2.TXT\nA\nC\nC\n"
134 "*****\n\n"
135 },
136 {
137 __LINE__, 1, "fc /A" FILES, "A\nB\nC\nD\nE\n", "A\nC\nC\nC\nE\n", -1, -1, COMPARING
138 "***** fc-test1.txt\nA\n...\nE\n"
139 "***** FC-TEST2.TXT\nA\n...\nE\n"
140 "*****\n\n"
141 },
142 {
143 __LINE__, 1, "fc /A" FILES, "A\nB\nC\nD\nE\n", "A\nB\nC\nD\nF\n", -1, -1, COMPARING
144 "***** fc-test1.txt\nD\nE\n"
145 "***** FC-TEST2.TXT\nD\nF\n"
146 "*****\n\n"
147 },
148 {
149 __LINE__, 1, "fc /A" FILES, "A\nB\nC\nD\nE\n", "A\nB\nC\nF\nF\n", -1, -1, COMPARING
150 "***** fc-test1.txt\nC\nD\nE\n"
151 "***** FC-TEST2.TXT\nC\nF\nF\n"
152 "*****\n\n"
153 },
154 {
155 __LINE__, 1, "fc /A" FILES, "A\nB\nC\nD\nE\n", "A\nB\nF\nF\nF\n", -1, -1, COMPARING
156 "***** fc-test1.txt\nB\n...\nE\n"
157 "***** FC-TEST2.TXT\nB\n...\nF\n"
158 "*****\n\n"
159 },
160 {
161 __LINE__, 1, "fc /A" FILES, "A\nC\nE\nF\nE\n", "A\nB\nC\nD\nE\n", -1, -1, COMPARING
162 "***** fc-test1.txt\nA\nC\nE\n"
163 "***** FC-TEST2.TXT\nA\n...\nE\n"
164 "*****\n\n"
165 "***** fc-test1.txt\nF\nE\n"
166 "***** FC-TEST2.TXT\n"
167 "*****\n\n"
168 },
169 /* Test /N /A */
170 {
171 __LINE__, 1, "fc /N /A" FILES, "A\nB\nC\nD\nE\n", "A\nB\nB\nD\nE\n", -1, -1, COMPARING
172 "***** fc-test1.txt\n 2: B\n 3: C\n 4: D\n"
173 "***** FC-TEST2.TXT\n 2: B\n 3: B\n 4: D\n"
174 "*****\n\n"
175 },
176 {
177 __LINE__, 1, "fc /N /A" FILES, "A\nC\nC\nD\nE\n", "A\nB\nC\nD\nE\n", -1, -1, COMPARING
178 "***** fc-test1.txt\n 1: A\n 2: C\n 3: C\n"
179 "***** FC-TEST2.TXT\n 1: A\n 2: B\n 3: C\n"
180 "*****\n\n"
181 },
182 {
183 __LINE__, 1, "fc /N /A" FILES, "A\nC\nC\nC\nE\n", "A\nB\nC\nD\nE\n", -1, -1, COMPARING
184 "***** fc-test1.txt\n 1: A\n...\n 5: E\n"
185 "***** FC-TEST2.TXT\n 1: A\n...\n 5: E\n"
186 "*****\n\n"
187 },
188 {
189 __LINE__, 1, "fc /N /A" FILES, "A\nC\nE\nF\nC\n", "A\nB\nC\nD\nE\n", -1, -1, COMPARING
190 "***** fc-test1.txt\n 1: A\n...\n 5: C\n"
191 "***** FC-TEST2.TXT\n 1: A\n 2: B\n 3: C\n"
192 "*****\n\n"
193 "***** fc-test1.txt\n"
194 "***** FC-TEST2.TXT\n 4: D\n 5: E\n"
195 "*****\n\n"
196 },
197 {
198 __LINE__, 1, "fc /N /A" FILES, "A\nC\nE\nF\nE\n", "A\nB\nC\nD\nE\n", -1, -1, COMPARING
199 "***** fc-test1.txt\n 1: A\n 2: C\n 3: E\n"
200 "***** FC-TEST2.TXT\n 1: A\n...\n 5: E\n"
201 "*****\n\n"
202 "***** fc-test1.txt\n 4: F\n 5: E\n"
203 "***** FC-TEST2.TXT\n"
204 "*****\n\n"
205 },
206 /* Test tab expansion */
207 {
208 __LINE__, 0, "fc" FILES, "A\n\tB\nC", "A\n B\nC", -1, -1, COMPARING
209 NO_DIFF
210 },
211 {
212 __LINE__, 0, "fc" FILES, "A\n \tB\nC", "A\n B\nC", -1, -1, COMPARING
213 NO_DIFF
214 },
215 /* Test /T */
216 {
217 __LINE__, 1, "fc /T" FILES, "A\n\tB\nC", "A\n B\nC", -1, -1, COMPARING
218 "***** fc-test1.txt\nA\n\tB\nC\n"
219 "***** FC-TEST2.TXT\nA\n B\nC\n"
220 "*****\n\n"
221 },
222 {
223 __LINE__, 1, "fc /T" FILES, "A\n \tB\nC", "A\n B\nC", -1, -1, COMPARING
224 "***** fc-test1.txt\nA\n \tB\nC\n"
225 "***** FC-TEST2.TXT\nA\n B\nC\n"
226 "*****\n\n"
227 },
228 /* Test /W */
229 {
230 __LINE__, 0, "fc /W" FILES, "A\n \tB\nC", "A\n B\nC", -1, -1, COMPARING
231 NO_DIFF
232 },
233 {
234 __LINE__, 0, "fc /W" FILES, "\tA \nB\n", "A\nB\n", -1, -1, COMPARING
235 NO_DIFF
236 },
237 {
238 __LINE__, 1, "fc /W" FILES, " A \nB\n", "AB\nB\n", -1, -1, COMPARING
239 "***** fc-test1.txt\n A \nB\n"
240 "***** FC-TEST2.TXT\nAB\nB\n"
241 "*****\n\n"
242 },
243 /* TEST /W /T */
244 {
245 __LINE__, 0, "fc /W /T" FILES, "A\n \tB\nC", "A\n B\nC", -1, -1, COMPARING
246 NO_DIFF
247 },
248 {
249 __LINE__, 0, "fc /W /T" FILES, "A\n \tB\nC", "A\n B\nC", -1, -1, COMPARING
250 NO_DIFF
251 },
252 {
253 __LINE__, 1, "fc /W /T" FILES, "\tA \nB\n", "AB\nB\n", -1, -1, COMPARING
254 "***** fc-test1.txt\n\tA \nB\n"
255 "***** FC-TEST2.TXT\nAB\nB\n"
256 "*****\n\n"
257 },
258 /* Test /N */
259 {
260 __LINE__, 1, "fc /N" FILES, "A\nB\nC\nD\nE\n", "A\nB\nC\nE\nE\n", -1, -1, COMPARING
261 "***** fc-test1.txt\n 3: C\n 4: D\n 5: E\n"
262 "***** FC-TEST2.TXT\n 3: C\n 4: E\n"
263 "*****\n\n"
264 "***** fc-test1.txt\n"
265 "***** FC-TEST2.TXT\n 5: E\n"
266 "*****\n\n"
267 },
268 /* Test NUL */
269 {
270 __LINE__, 1, "fc" FILES, "ABC\000DE", "ABC\000\000\000", 6, 6, COMPARING
271 "***** fc-test1.txt\nABC\nDE\n"
272 "***** FC-TEST2.TXT\nABC\n\n\n"
273 "*****\n\n"
274 },
275 {
276 __LINE__, 1, "fc" FILES, "ABC\000DE", "ABC\n\000\000", 6, 6, COMPARING
277 "***** fc-test1.txt\nABC\nDE\n"
278 "***** FC-TEST2.TXT\nABC\n\n\n"
279 "*****\n\n"
280 },
281 {
282 __LINE__, 0, "fc" FILES, "ABC\000DE", "ABC\nDE", 6, 6, COMPARING
283 NO_DIFF
284 },
285 /* Test CR ('\r') */
286 {
287 __LINE__, 0, "fc" FILES, "ABC\nABC", "ABC\r\nABC", -1, -1, COMPARING
288 NO_DIFF
289 },
290 {
291 __LINE__, 1, "fc" FILES, "ABC\nABC", "ABC\r\r\nABC", -1, -1, COMPARING
292 "***** fc-test1.txt\nABC\nABC\n"
293 "***** FC-TEST2.TXT\nABC\nABC\n"
294 "*****\n\n"
295 },
296 /* Test '\n' at EOF */
297 {
298 __LINE__, 0, "fc" FILES, "ABC", "ABC\n", -1, -1, COMPARING
299 NO_DIFF
300 },
301 /* Test /U */
302 {
303 /* L"AB" */
304 __LINE__, 0, "fc /U" FILES, "A\000B\000", "A\000B\000", 4, 4, COMPARING
305 NO_DIFF
306 },
307 {
308 __LINE__, 1, "fc /U" FILES, "A\000B\000", "A\000C\000", 4, 4, COMPARING
309 "***** fc-test1.txt\nAB\n"
310 "***** FC-TEST2.TXT\nAC\n"
311 "*****\n\n"
312 },
313 /* Test /LB2 */
314 {
315 __LINE__, 1, "fc /LB2" FILES, "A\nB\nC\nD\nE\n", "B\nB\nC\nD\nE\n", -1, -1, COMPARING
316 "***** fc-test1.txt\nA\nB\n"
317 "***** FC-TEST2.TXT\nB\nB\n"
318 "*****\n\n"
319 },
320 {
321 __LINE__, 1, "fc /LB2" FILES, "A\nB\nC\nD\nE\n", "C\nC\nC\nD\nE\n", -1, -1, COMPARING
322 RESYNC_FAILED
323 "***** fc-test1.txt\nA\nB\n"
324 "***** FC-TEST2.TXT\nC\nC\n"
325 "*****\n\n"
326 },
327 {
328 __LINE__, 1, "fc /LB2" FILES, "A\nB\nC\nD\nE\n", "D\nD\nD\nD\nE\n", -1, -1, COMPARING
329 RESYNC_FAILED
330 "***** fc-test1.txt\nA\nB\n"
331 "***** FC-TEST2.TXT\nD\nD\n"
332 "*****\n\n"
333 },
334 {
335 __LINE__, 1, "fc /LB2" FILES, "A\nB\nC\nD\nE\n", "A\nC\nC\nD\nE\n", -1, -1, COMPARING
336 RESYNC_FAILED
337 "***** fc-test1.txt\nA\nB\n"
338 "***** FC-TEST2.TXT\nA\nC\n"
339 "*****\n\n"
340 },
341 /* Test /LB3 */
342 {
343 __LINE__, 1, "fc /LB3" FILES, "A\nB\nC\nD\nE\n", "C\nC\nC\nD\nE\n", -1, -1, COMPARING
344 "***** fc-test1.txt\nA\nB\nC\n"
345 "***** FC-TEST2.TXT\nC\nC\n"
346 "*****\n\n"
347 "***** fc-test1.txt\nC\nD\n"
348 "***** FC-TEST2.TXT\nC\nC\nD\n"
349 "*****\n\n"
350 },
351 {
352 __LINE__, 1, "fc /LB3" FILES, "A\nB\nC\nD\nE\n", "D\nD\nD\nD\nE\n", -1, -1, COMPARING
353 RESYNC_FAILED
354 "***** fc-test1.txt\nA\nB\nC\n"
355 "***** FC-TEST2.TXT\nD\nD\nD\n"
356 "*****\n\n"
357 },
358 /* Test /N /LB2 */
359 {
360 __LINE__, 1, "fc /N /LB2" FILES, "A\nB\nC\nD\nE\n", "A\nB\nC\nE\nE\n", -1, -1, COMPARING
361 RESYNC_FAILED
362 "***** fc-test1.txt\n 3: C\n 4: D\n"
363 "***** FC-TEST2.TXT\n 3: C\n 4: E\n"
364 "*****\n\n"
365 },
366 /* Test /1 */
367 {
368 __LINE__, 1, "fc /1" FILES, "A\nB\nC\nD\nE\n", "A\nB\nC\nE\nE\n", -1, -1, COMPARING
369 "***** fc-test1.txt\nC\nD\nE\n"
370 "***** FC-TEST2.TXT\nC\nE\n"
371 "*****\n\n"
372 },
373 {
374 __LINE__, 1, "fc /1" FILES, "A\nB\nC\nD\nE\n", "A\nB\nX\nX\nE\n", -1, -1, COMPARING
375 "***** fc-test1.txt\nB\nC\nD\nE\n"
376 "***** FC-TEST2.TXT\nB\nX\nX\nE\n"
377 "*****\n\n"
378 },
379 {
380 __LINE__, 1, "fc /1" FILES, "A\nB\nC\nD\nE\nF\n", "A\nB\nX\nD\nX\nF", -1, -1, COMPARING
381 "***** fc-test1.txt\nB\nC\nD\n"
382 "***** FC-TEST2.TXT\nB\nX\nD\n"
383 "*****\n\n"
384 "***** fc-test1.txt\nD\nE\nF\n"
385 "***** FC-TEST2.TXT\nD\nX\nF\n"
386 "*****\n\n"
387 },
388 /* Test /3 */
389 {
390 __LINE__, 1, "fc /3" FILES, "A\nB\nC\nD\nE\n", "A\nB\nC\nE\nE\n", -1, -1, COMPARING
391 "***** fc-test1.txt\nC\nD\nE\n"
392 "***** FC-TEST2.TXT\nC\nE\n"
393 "*****\n\n"
394 },
395 {
396 __LINE__, 1, "fc /3" FILES, "A\nB\nC\nD\nE\n", "A\nB\nX\nX\nE\n", -1, -1, COMPARING
397 "***** fc-test1.txt\nB\nC\nD\nE\n"
398 "***** FC-TEST2.TXT\nB\nX\nX\nE\n"
399 "*****\n\n"
400 },
401 {
402 __LINE__, 1, "fc /3" FILES, "A\nB\nC\nD\nE\nF\n", "A\nB\nX\nD\nX\nF", -1, -1, COMPARING
403 "***** fc-test1.txt\nB\nC\nD\nE\nF\n"
404 "***** FC-TEST2.TXT\nB\nX\nD\nX\nF\n"
405 "*****\n\n"
406 },
407 };
408
DoDuplicateHandle(HANDLE hFile,PHANDLE phFile,BOOL bInherit)409 BOOL DoDuplicateHandle(HANDLE hFile, PHANDLE phFile, BOOL bInherit)
410 {
411 HANDLE hProcess = GetCurrentProcess();
412 return DuplicateHandle(hProcess, hFile, hProcess, phFile, 0,
413 bInherit, DUPLICATE_SAME_ACCESS);
414 }
415
416 static BOOL
PrepareForRedirect(STARTUPINFOA * psi,PHANDLE phInputWrite,PHANDLE phOutputRead,PHANDLE phErrorRead)417 PrepareForRedirect(STARTUPINFOA *psi, PHANDLE phInputWrite, PHANDLE phOutputRead,
418 PHANDLE phErrorRead)
419 {
420 SECURITY_ATTRIBUTES sa;
421 HANDLE hInputRead = NULL, hInputWriteTmp = NULL;
422 HANDLE hOutputReadTmp = NULL, hOutputWrite = NULL;
423 HANDLE hErrorReadTmp = NULL, hErrorWrite = NULL;
424
425 sa.nLength = sizeof(sa);
426 sa.lpSecurityDescriptor = NULL;
427 sa.bInheritHandle = TRUE;
428
429 if (phInputWrite)
430 {
431 if (CreatePipe(&hInputRead, &hInputWriteTmp, &sa, 0))
432 {
433 if (!DoDuplicateHandle(hInputWriteTmp, phInputWrite, FALSE))
434 return FALSE;
435 CloseHandle(hInputWriteTmp);
436 }
437 else
438 goto failure;
439 }
440
441 if (phOutputRead)
442 {
443 if (CreatePipe(&hOutputReadTmp, &hOutputWrite, &sa, 0))
444 {
445 if (!DoDuplicateHandle(hOutputReadTmp, phOutputRead, FALSE))
446 return FALSE;
447 CloseHandle(hOutputReadTmp);
448 }
449 else
450 goto failure;
451 }
452
453 if (phOutputRead && phOutputRead == phErrorRead)
454 {
455 if (!DoDuplicateHandle(hOutputWrite, &hErrorWrite, TRUE))
456 return FALSE;
457 }
458 else if (phErrorRead)
459 {
460 if (CreatePipe(&hErrorReadTmp, &hErrorWrite, &sa, 0))
461 {
462 if (!DoDuplicateHandle(hErrorReadTmp, phErrorRead, FALSE))
463 return FALSE;
464 CloseHandle(hErrorReadTmp);
465 }
466 else
467 goto failure;
468 }
469
470 if (phInputWrite)
471 {
472 psi->hStdInput = hInputRead;
473 psi->dwFlags |= STARTF_USESTDHANDLES;
474 }
475 if (phOutputRead)
476 {
477 psi->hStdOutput = hOutputWrite;
478 psi->dwFlags |= STARTF_USESTDHANDLES;
479 }
480 if (phErrorRead)
481 {
482 psi->hStdOutput = hErrorWrite;
483 psi->dwFlags |= STARTF_USESTDHANDLES;
484 }
485 return TRUE;
486
487 failure:
488 CloseHandle(hInputRead);
489 CloseHandle(hInputWriteTmp);
490 CloseHandle(hOutputReadTmp);
491 CloseHandle(hOutputWrite);
492 CloseHandle(hErrorReadTmp);
493 CloseHandle(hErrorWrite);
494 return FALSE;
495 }
496
ConvertOutput(LPSTR psz)497 static void ConvertOutput(LPSTR psz)
498 {
499 LPSTR pch1, pch2;
500 pch1 = pch2 = psz;
501 while (*pch1)
502 {
503 if (*pch1 != '\r')
504 {
505 *pch2++ = *pch1;
506 }
507 ++pch1;
508 }
509 *pch2 = 0;
510 }
511
DoTestEntry(const TEST_ENTRY * pEntry)512 static void DoTestEntry(const TEST_ENTRY* pEntry)
513 {
514 FILE *fp;
515 STARTUPINFOA si = { sizeof(si) };
516 PROCESS_INFORMATION pi;
517 INT file1_size, file2_size;
518 HANDLE hOutputRead;
519 DWORD cbAvail, cbRead;
520 CHAR szOutput[1024];
521 BOOL ret;
522 DWORD dwExitCode;
523 LPSTR psz;
524
525 file1_size = pEntry->file1_size;
526 file2_size = pEntry->file2_size;
527 if (file1_size == -1)
528 file1_size = strlen(pEntry->file1_data);
529 if (file2_size == -1)
530 file2_size = strlen(pEntry->file2_data);
531
532 fp = fopen(FILE1, "wb");
533 fwrite(pEntry->file1_data, file1_size, 1, fp);
534 fclose(fp);
535
536 fp = fopen(FILE2, "wb");
537 fwrite(pEntry->file2_data, file2_size, 1, fp);
538 fclose(fp);
539
540 ok(PathFileExistsA(FILE1), "Line %d: PathFileExistsA(FILE1) failed\n", pEntry->lineno);
541 ok(PathFileExistsA(FILE2), "Line %d: PathFileExistsA(FILE2) failed\n", pEntry->lineno);
542
543 si.hStdInput = GetStdHandle(STD_INPUT_HANDLE);
544 si.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE);
545 si.hStdError = GetStdHandle(STD_ERROR_HANDLE);
546
547 PrepareForRedirect(&si, NULL, &hOutputRead, &hOutputRead);
548
549 psz = _strdup(pEntry->cmdline);
550 ret = CreateProcessA(NULL, psz, NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi);
551 free(psz);
552
553 ok(ret, "Line %d: CreateProcessA failed\n", pEntry->lineno);
554
555 #define TIMEOUT (10 * 1000)
556 WaitForSingleObject(pi.hProcess, TIMEOUT);
557
558 ZeroMemory(szOutput, sizeof(szOutput));
559 if (PeekNamedPipe(hOutputRead, NULL, 0, NULL, &cbAvail, NULL))
560 {
561 if (cbAvail > 0)
562 {
563 if (cbAvail > sizeof(szOutput))
564 cbAvail = sizeof(szOutput) - 1;
565
566 ReadFile(hOutputRead, szOutput, cbAvail, &cbRead, NULL);
567 }
568 }
569 ConvertOutput(szOutput);
570
571 GetExitCodeProcess(pi.hProcess, &dwExitCode);
572 ok(dwExitCode == pEntry->ret, "Line %d: dwExitCode was 0x%lx\n", pEntry->lineno, dwExitCode);
573
574 if (StrCmpNIA(pEntry->output, szOutput, strlen(pEntry->output)) != 0)
575 {
576 ok(FALSE, "Line %d: Output was wrong\n", pEntry->lineno);
577 printf("---FROM HERE\n");
578 printf("%s\n", szOutput);
579 printf("---UP TO HERE\n");
580 }
581 else
582 {
583 ok_int(TRUE, TRUE);
584 }
585
586 CloseHandle(pi.hProcess);
587 CloseHandle(pi.hThread);
588
589 CloseHandle(hOutputRead);
590 if (si.hStdInput != GetStdHandle(STD_INPUT_HANDLE))
591 CloseHandle(si.hStdInput);
592 if (si.hStdOutput != GetStdHandle(STD_OUTPUT_HANDLE))
593 CloseHandle(si.hStdOutput);
594 if (si.hStdError != GetStdHandle(STD_ERROR_HANDLE))
595 CloseHandle(si.hStdError);
596
597 DeleteFileA(FILE1);
598 DeleteFileA(FILE2);
599 }
600
601 #define ENGLISH_CP 437 /* English codepage */
602
START_TEST(fc)603 START_TEST(fc)
604 {
605 UINT i;
606 UINT uOldCP = GetConsoleCP(), uOldOutputCP = GetConsoleOutputCP();
607 SetConsoleCP(ENGLISH_CP);
608 SetConsoleOutputCP(ENGLISH_CP);
609
610 for (i = 0; i < _countof(s_entries); ++i)
611 {
612 DoTestEntry(&s_entries[i]);
613 }
614
615 SetConsoleCP(uOldCP);
616 SetConsoleOutputCP(uOldOutputCP);
617 }
618