xref: /reactos/modules/rostests/apitests/cmd/fc.c (revision 34593d93)
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 
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
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 
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 
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 
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