Release 1.5.29.
[wine] / dlls / msvcrt / tests / file.c
1 /*
2  * Unit test suite for file functions
3  *
4  * Copyright 2002 Bill Currie
5  * Copyright 2005 Paul Rupe
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20  */
21
22 #include "wine/test.h"
23 #include <stdarg.h>
24 #include <stdlib.h>
25 #include <stdio.h>
26 #include <fcntl.h>
27 #include <share.h>
28 #include <sys/stat.h>
29 #include <io.h>
30 #include <direct.h>
31 #include <windef.h>
32 #include <winbase.h>
33 #include <winnls.h>
34 #include <process.h>
35 #include <errno.h>
36 #include <locale.h>
37
38 static HANDLE proc_handles[2];
39
40 static int (__cdecl *p_fopen_s)(FILE**, const char*, const char*);
41 static int (__cdecl *p__wfopen_s)(FILE**, const wchar_t*, const wchar_t*);
42
43 static void init(void)
44 {
45     HMODULE hmod = GetModuleHandleA("msvcrt.dll");
46
47     setlocale(LC_CTYPE, "C");
48
49     p_fopen_s = (void*)GetProcAddress(hmod, "fopen_s");
50     p__wfopen_s = (void*)GetProcAddress(hmod, "_wfopen_s");
51 }
52
53 static void test_filbuf( void )
54 {
55     FILE *fp;
56     int c;
57     fpos_t pos;
58
59     fp = fopen("filbuf.tst", "wb");
60     fwrite("\n\n\n\n", 1, 4, fp);
61     fclose(fp);
62
63     fp = fopen("filbuf.tst", "rt");
64     c = _filbuf(fp);
65     ok(c == '\n', "read wrong byte\n");
66     /* See bug 16970 for why we care about _filbuf.
67      * ftell returns screwy values on files with lots
68      * of bare LFs in ascii mode because it assumes
69      * that ascii files contain only CRLFs, removes
70      * the CR's early in _filbuf, and adjusts the return
71      * value of ftell to compensate.
72      * native _filbuf will read the whole file, then consume and return
73      * the first one.  That leaves fp->_fd at offset 4, and fp->_ptr
74      * pointing to a buffer of three bare LFs, so
75      * ftell will return 4 - 3 - 3 = -2.
76      */
77     ok(ftell(fp) == -2, "ascii crlf removal does not match native\n");
78     ok(fgetpos(fp, &pos) == 0, "fgetpos fail\n");
79     ok(pos == -2, "ftell does not match fgetpos\n");
80     fclose(fp);
81     unlink("filbuf.tst");
82 }
83
84 static void test_fdopen( void )
85 {
86     static const char buffer[] = {0,1,2,3,4,5,6,7,8,9};
87     char ibuf[10];
88     int fd;
89     FILE *file;
90
91     fd = open ("fdopen.tst", O_WRONLY | O_CREAT | O_BINARY, _S_IREAD |_S_IWRITE);
92     write (fd, buffer, sizeof (buffer));
93     close (fd);
94
95     fd = open ("fdopen.tst", O_RDONLY | O_BINARY);
96     lseek (fd, 5, SEEK_SET);
97     file = fdopen (fd, "rb");
98     ok (fread (ibuf, 1, sizeof (buffer), file) == 5, "read wrong byte count\n");
99     ok (memcmp (ibuf, buffer + 5, 5) == 0, "read wrong bytes\n");
100     fclose (file);
101     unlink ("fdopen.tst");
102 }
103
104 static void test_fileops( void )
105 {
106     static const char outbuffer[] = "0,1,2,3,4,5,6,7,8,9";
107     char buffer[256];
108     WCHAR wbuffer[256];
109     int fd;
110     FILE *file;
111     fpos_t pos;
112     int i, c, bufmode;
113     static const int bufmodes[] = {_IOFBF,_IONBF};
114
115     fd = open ("fdopen.tst", O_WRONLY | O_CREAT | O_BINARY, _S_IREAD |_S_IWRITE);
116     write (fd, outbuffer, sizeof (outbuffer));
117     close (fd);
118
119     for (bufmode=0; bufmode < sizeof(bufmodes)/sizeof(bufmodes[0]); bufmode++)
120     {
121         fd = open ("fdopen.tst", O_RDONLY | O_BINARY);
122         file = fdopen (fd, "rb");
123         setvbuf(file,NULL,bufmodes[bufmode],2048);
124         ok(strlen(outbuffer) == (sizeof(outbuffer)-1),"strlen/sizeof error for bufmode=%x\n", bufmodes[bufmode]);
125         ok(fgets(buffer,sizeof(buffer),file) !=0,"fgets failed unexpected for bufmode=%x\n", bufmodes[bufmode]);
126         ok(fgets(buffer,sizeof(buffer),file) ==0,"fgets didn't signal EOF for bufmode=%x\n", bufmodes[bufmode]);
127         ok(feof(file) !=0,"feof doesn't signal EOF for bufmode=%x\n", bufmodes[bufmode]);
128         rewind(file);
129         ok(fgets(buffer,strlen(outbuffer),file) !=0,"fgets failed unexpected for bufmode=%x\n", bufmodes[bufmode]);
130         ok(lstrlenA(buffer) == lstrlenA(outbuffer) -1,"fgets didn't read right size for bufmode=%x\n", bufmodes[bufmode]);
131         ok(fgets(buffer,sizeof(outbuffer),file) !=0,"fgets failed unexpected for bufmode=%x\n", bufmodes[bufmode]);
132         ok(strlen(buffer) == 1,"fgets dropped chars for bufmode=%x\n", bufmodes[bufmode]);
133         ok(buffer[0] == outbuffer[strlen(outbuffer)-1],"fgets exchanged chars for bufmode=%x\n", bufmodes[bufmode]);
134
135         rewind(file);
136         for (i = 0; i < sizeof(outbuffer); i++)
137         {
138             ok(fgetc(file) == outbuffer[i], "fgetc returned wrong data for bufmode=%x\n", bufmodes[bufmode]);
139         }
140         ok((c = fgetc(file)) == EOF, "getc did not return EOF for bufmode=%x\n", bufmodes[bufmode]);
141         ok(feof(file), "feof did not return EOF for bufmode=%x\n", bufmodes[bufmode]);
142         ok(ungetc(c, file) == EOF, "ungetc(EOF) did not return EOF for bufmode=%x\n", bufmodes[bufmode]);
143         ok(feof(file), "feof after ungetc(EOF) did not return EOF for bufmode=%x\n", bufmodes[bufmode]);
144         ok(fgetc(file) == EOF, "getc did not return EOF for bufmode=%x\n", bufmodes[bufmode]);
145         c = outbuffer[sizeof(outbuffer) - 1];
146         ok(ungetc(c, file) == c, "ungetc did not return its input for bufmode=%x\n", bufmodes[bufmode]);
147         ok(!feof(file), "feof after ungetc returned EOF for bufmode=%x\n", bufmodes[bufmode]);
148         ok((c = fgetc(file)) != EOF, "getc after ungetc returned EOF for bufmode=%x\n", bufmodes[bufmode]);
149         ok(c == outbuffer[sizeof(outbuffer) - 1],
150            "getc did not return ungetc'd data for bufmode=%x\n", bufmodes[bufmode]);
151         ok(!feof(file), "feof after getc returned EOF prematurely for bufmode=%x\n", bufmodes[bufmode]);
152         ok(fgetc(file) == EOF, "getc did not return EOF for bufmode=%x\n", bufmodes[bufmode]);
153         ok(feof(file), "feof after getc did not return EOF for bufmode=%x\n", bufmodes[bufmode]);
154
155         rewind(file);
156         ok(fgetpos(file,&pos) == 0, "fgetpos failed unexpected for bufmode=%x\n", bufmodes[bufmode]);
157         ok(pos == 0, "Unexpected result of fgetpos %x%08x for bufmode=%x\n", (DWORD)(pos >> 32), (DWORD)pos, bufmodes[bufmode]);
158         pos = sizeof (outbuffer);
159         ok(fsetpos(file, &pos) == 0, "fsetpos failed unexpected for bufmode=%x\n", bufmodes[bufmode]);
160         ok(fgetpos(file,&pos) == 0, "fgetpos failed unexpected for bufmode=%x\n", bufmodes[bufmode]);
161         ok(pos == sizeof (outbuffer), "Unexpected result of fgetpos %x%08x for bufmode=%x\n", (DWORD)(pos >> 32), (DWORD)pos, bufmodes[bufmode]);
162
163         fclose (file);
164     }
165     fd = open ("fdopen.tst", O_RDONLY | O_TEXT);
166     file = fdopen (fd, "rt"); /* open in TEXT mode */
167     ok(fgetws(wbuffer,sizeof(wbuffer)/sizeof(wbuffer[0]),file) !=0,"fgetws failed unexpected\n");
168     ok(fgetws(wbuffer,sizeof(wbuffer)/sizeof(wbuffer[0]),file) ==0,"fgetws didn't signal EOF\n");
169     ok(feof(file) !=0,"feof doesn't signal EOF\n");
170     rewind(file);
171     ok(fgetws(wbuffer,strlen(outbuffer),file) !=0,"fgetws failed unexpected\n");
172     ok(lstrlenW(wbuffer) == (lstrlenA(outbuffer) -1),"fgetws didn't read right size\n");
173     ok(fgetws(wbuffer,sizeof(outbuffer)/sizeof(outbuffer[0]),file) !=0,"fgets failed unexpected\n");
174     ok(lstrlenW(wbuffer) == 1,"fgets dropped chars\n");
175     fclose (file);
176
177     file = fopen("fdopen.tst", "rb");
178     ok( file != NULL, "fopen failed\n");
179     /* sizeof(buffer) > content of file */
180     ok(fread(buffer, sizeof(buffer), 1, file) == 0, "fread test failed\n");
181     /* feof should be set now */
182     ok(feof(file), "feof after fread failed\n");
183     fclose (file);
184
185     unlink ("fdopen.tst");
186 }
187
188 #define IOMODE (ao?"ascii mode":"binary mode")
189 static void test_readmode( BOOL ascii_mode )
190 {
191     static const char outbuffer[] = "0,1,2,3,4,5,6,7,8,9\r\n\r\nA,B,C,D,E\r\nX,Y,Z";
192     static const char padbuffer[] = "ghjghjghjghj";
193     static const char nlbuffer[] = "\r\n";
194     char buffer[2*BUFSIZ+256];
195     const char *optr;
196     int fd;
197     FILE *file;
198     const int *ip;
199     int i, j, m, ao, pl;
200     unsigned int fp;
201     LONG l;
202
203     fd = open ("fdopen.tst", O_WRONLY | O_CREAT | O_BINARY, _S_IREAD |_S_IWRITE);
204     /* an internal buffer of BUFSIZ is maintained, so make a file big
205      * enough to test operations that cross the buffer boundary 
206      */
207     j = (2*BUFSIZ-4)/strlen(padbuffer);
208     for (i=0; i<j; i++)
209         write (fd, padbuffer, strlen(padbuffer));
210     j = (2*BUFSIZ-4)%strlen(padbuffer);
211     for (i=0; i<j; i++)
212         write (fd, &padbuffer[i], 1);
213     write (fd, nlbuffer, strlen(nlbuffer));
214     write (fd, outbuffer, sizeof (outbuffer));
215     close (fd);
216     
217     if (ascii_mode) {
218         /* Open file in ascii mode */
219         fd = open ("fdopen.tst", O_RDONLY);
220         file = fdopen (fd, "r");
221         ao = -1; /* on offset to account for carriage returns */
222     }
223     else {
224         fd = open ("fdopen.tst", O_RDONLY | O_BINARY);
225         file = fdopen (fd, "rb");
226         ao = 0;
227     }
228     
229     /* first is a test of fgets, ftell, fseek */
230     ok(ftell(file) == 0,"Did not start at beginning of file in %s\n", IOMODE);
231     ok(fgets(buffer,2*BUFSIZ+256,file) !=0,"padding line fgets failed unexpected in %s\n", IOMODE);
232     l = ftell(file);
233     pl = 2*BUFSIZ-2;
234     ok(l == pl,"padding line ftell got %d should be %d in %s\n", l, pl, IOMODE);
235     ok(lstrlenA(buffer) == pl+ao,"padding line fgets got size %d should be %d in %s\n",
236      lstrlenA(buffer), pl+ao, IOMODE);
237     for (fp=0; fp<strlen(outbuffer); fp++)
238         if (outbuffer[fp] == '\n') break;
239     fp++;
240     ok(fgets(buffer,256,file) !=0,"line 1 fgets failed unexpected in %s\n", IOMODE);
241     l = ftell(file);
242     ok(l == pl+fp,"line 1 ftell got %d should be %d in %s\n", l, pl+fp, IOMODE);
243     ok(lstrlenA(buffer) == fp+ao,"line 1 fgets got size %d should be %d in %s\n",
244      lstrlenA(buffer), fp+ao, IOMODE);
245     /* test a seek back across the buffer boundary */
246     l = pl;
247     ok(fseek(file,l,SEEK_SET)==0,"seek failure in %s\n", IOMODE);
248     l = ftell(file);
249     ok(l == pl,"ftell after seek got %d should be %d in %s\n", l, pl, IOMODE);
250     ok(fgets(buffer,256,file) !=0,"second read of line 1 fgets failed unexpected in %s\n", IOMODE);
251     l = ftell(file);
252     ok(l == pl+fp,"second read of line 1 ftell got %d should be %d in %s\n", l, pl+fp, IOMODE);
253     ok(lstrlenA(buffer) == fp+ao,"second read of line 1 fgets got size %d should be %d in %s\n",
254      lstrlenA(buffer), fp+ao, IOMODE);
255     ok(fgets(buffer,256,file) !=0,"line 2 fgets failed unexpected in %s\n", IOMODE);
256     fp += 2;
257     l = ftell(file);
258     ok(l == pl+fp,"line 2 ftell got %d should be %d in %s\n", l, pl+fp, IOMODE);
259     ok(lstrlenA(buffer) == 2+ao,"line 2 fgets got size %d should be %d in %s\n",
260      lstrlenA(buffer), 2+ao, IOMODE);
261     
262     /* test fread across buffer boundary */
263     rewind(file);
264     ok(ftell(file) == 0,"Did not start at beginning of file in %s\n", IOMODE);
265     ok(fgets(buffer,BUFSIZ-6,file) !=0,"padding line fgets failed unexpected in %s\n", IOMODE);
266     j=strlen(outbuffer);
267     i=fread(buffer,1,BUFSIZ+strlen(outbuffer),file);
268     ok(i==BUFSIZ+j,"fread failed, expected %d got %d in %s\n", BUFSIZ+j, i, IOMODE);
269     l = ftell(file);
270     ok(l == pl+j-(ao*4)-5,"ftell after fread got %d should be %d in %s\n", l, pl+j-(ao*4)-5, IOMODE);
271     for (m=0; m<3; m++)
272         ok(buffer[m]==padbuffer[m+(BUFSIZ-4)%strlen(padbuffer)],"expected %c got %c\n", padbuffer[m], buffer[m]);
273     m+=BUFSIZ+2+ao;
274     optr = outbuffer;
275     for (; m<i; m++) {
276         ok(buffer[m]==*optr,"char %d expected %c got %c in %s\n", m, *optr, buffer[m], IOMODE);
277         optr++;
278         if (ao && (*optr == '\r'))
279             optr++;
280     }
281     /* fread should return the requested number of bytes if available */
282     rewind(file);
283     ok(ftell(file) == 0,"Did not start at beginning of file in %s\n", IOMODE);
284     ok(fgets(buffer,BUFSIZ-6,file) !=0,"padding line fgets failed unexpected in %s\n", IOMODE);
285     j = fp+10;
286     i=fread(buffer,1,j,file);
287     ok(i==j,"fread failed, expected %d got %d in %s\n", j, i, IOMODE);
288     /* test fread eof */
289     ok(fseek(file,0,SEEK_END)==0,"seek failure in %s\n", IOMODE);
290     ok(feof(file)==0,"feof failure in %s\n", IOMODE);
291     ok(fread(buffer,1,1,file)==0,"fread failure in %s\n", IOMODE);
292     ok(feof(file)!=0,"feof failure in %s\n", IOMODE);
293     ok(fseek(file,-3,SEEK_CUR)==0,"seek failure in %s\n", IOMODE);
294     ok(feof(file)==0,"feof failure in %s\n", IOMODE);
295     ok(fread(buffer,2,1,file)==1,"fread failed in %s\n", IOMODE);
296     ok(feof(file)==0,"feof failure in %s\n", IOMODE);
297     ok(fread(buffer,2,1,file)==0,"fread failure in %s\n",IOMODE);
298     ok(feof(file)!=0,"feof failure in %s\n", IOMODE);
299     
300     /* test some additional functions */
301     rewind(file);
302     ok(ftell(file) == 0,"Did not start at beginning of file in %s\n", IOMODE);
303     ok(fgets(buffer,2*BUFSIZ+256,file) !=0,"padding line fgets failed unexpected in %s\n", IOMODE);
304     i = _getw(file);
305     ip = (const int *)outbuffer;
306     ok(i == *ip,"_getw failed, expected %08x got %08x in %s\n", *ip, i, IOMODE);
307     for (fp=0; fp<strlen(outbuffer); fp++)
308         if (outbuffer[fp] == '\n') break;
309     fp++;
310     /* this will cause the next _getw to cross carriage return characters */
311     ok(fgets(buffer,fp-6,file) !=0,"line 1 fgets failed unexpected in %s\n", IOMODE);
312     for (i=0, j=0; i<6; i++) {
313         if (ao==0 || outbuffer[fp-3+i] != '\r')
314             buffer[j++] = outbuffer[fp-3+i];
315     }
316     i = _getw(file);
317     ip = (int *)buffer;
318     ok(i == *ip,"_getw failed, expected %08x got %08x in %s\n", *ip, i, IOMODE);
319
320     fclose (file);
321     unlink ("fdopen.tst");
322 }
323
324 static void test_asciimode(void)
325 {
326     FILE *fp;
327     char buf[64];
328     int c, i, j;
329
330     /* Simple test of CR CR LF handling.  Test both fgets and fread code paths, they're different! */
331     fp = fopen("ascii.tst", "wb");
332     fputs("\r\r\n", fp);
333     fclose(fp);
334     fp = fopen("ascii.tst", "rt");
335     ok(fgets(buf, sizeof(buf), fp) != NULL, "fgets\n");
336     ok(0 == strcmp(buf, "\r\n"), "CR CR LF not read as CR LF\n");
337     rewind(fp);
338     ok((fread(buf, 1, sizeof(buf), fp) == 2) && (0 == strcmp(buf, "\r\n")), "CR CR LF not read as CR LF\n");
339     fclose(fp);
340     unlink("ascii.tst");
341
342     /* Simple test of foo ^Z [more than one block] bar handling */
343     fp = fopen("ascii.tst", "wb");
344     fputs("foo\032", fp);  /* foo, logical EOF, ... */
345     fseek(fp, 65536L, SEEK_SET); /* ... more than MSVCRT_BUFSIZ, ... */
346     fputs("bar", fp); /* ... bar */
347     fclose(fp);
348     fp = fopen("ascii.tst", "rt");
349     ok(fgets(buf, sizeof(buf), fp) != NULL, "fgets foo\n");
350     ok(0 == strcmp(buf, "foo"), "foo ^Z not read as foo by fgets\n");
351     ok(fgets(buf, sizeof(buf), fp) == NULL, "fgets after logical EOF\n");
352     rewind(fp);
353     ok((fread(buf, 1, sizeof(buf), fp) == 3) && (0 == strcmp(buf, "foo")), "foo ^Z not read as foo by fread\n");
354     ok((fread(buf, 1, sizeof(buf), fp) == 0), "fread after logical EOF\n");
355     fclose(fp);
356
357     /* Show ASCII mode handling*/
358     fp= fopen("ascii.tst","wb");
359     fputs("0\r\n1\r\n2\r\n3\r\n4\r\n5\r\n6\r\n7\r\n8\r\n9\r\n", fp);
360     fclose(fp);
361
362     fp = fopen("ascii.tst", "r");
363     c= fgetc(fp);
364     ok(c == '0', "fgetc failed, expected '0', got '%c'\n", c);
365     c= fgetc(fp);
366     ok(c == '\n', "fgetc failed, expected '\\n', got '%c'\n", c);
367     fseek(fp,0,SEEK_CUR);
368     for(i=1; i<10; i++) {
369         ok((j = ftell(fp)) == i*3, "ftell fails in TEXT mode\n");
370         fseek(fp,0,SEEK_CUR);
371         ok((c = fgetc(fp)) == '0'+ i, "fgetc after fseek failed in line %d\n", i);
372         c= fgetc(fp);
373         ok(c == '\n', "fgetc failed, expected '\\n', got '%c'\n", c);
374     }
375     /* Show that fseek doesn't skip \\r !*/
376     rewind(fp);
377     c= fgetc(fp);
378     ok(c == '0', "fgetc failed, expected '0', got '%c'\n", c);
379     fseek(fp, 2 ,SEEK_CUR);
380     for(i=1; i<10; i++) {
381         ok((c = fgetc(fp)) == '0'+ i, "fgetc after fseek with pos Offset failed in line %d\n", i);
382         fseek(fp, 2 ,SEEK_CUR);
383     }
384     fseek(fp, 9*3 ,SEEK_SET);
385     c = fgetc(fp);
386     ok(c == '9', "fgetc failed, expected '9', got '%c'\n", c);
387     fseek(fp, -4 ,SEEK_CUR);
388     for(i= 8; i>=0; i--) {
389         ok((c = fgetc(fp)) == '0'+ i, "fgetc after fseek with neg Offset failed in line %d\n", i);
390         fseek(fp, -4 ,SEEK_CUR);
391     }
392     /* Show what happens if fseek positions filepointer on \\r */
393     fclose(fp);
394     fp = fopen("ascii.tst", "r");
395     fseek(fp, 3 ,SEEK_SET);
396     ok((c = fgetc(fp)) == '1', "fgetc fails to read next char when positioned on \\r\n");
397     fclose(fp);
398
399     unlink("ascii.tst");
400 }
401
402 static void test_asciimode2(void)
403 {
404     /* Error sequence from one app was getchar followed by small fread
405      * with one \r removed had last byte of buffer filled with
406      * next byte of *unbuffered* data rather than next byte from buffer
407      * Test case is a short string of one byte followed by a newline
408      * followed by filler to fill out the sector, then a sector of
409      * some different byte.
410      */
411
412     FILE *fp;
413     char ibuf[4];
414     int i;
415     static const char obuf[] =
416 "00\n"
417 "000000000000000000000000000000000000000000000000000000000000000000000000000000\n"
418 "000000000000000000000000000000000000000000000000000000000000000000000000000000\n"
419 "000000000000000000000000000000000000000000000000000000000000000000000000000000\n"
420 "000000000000000000000000000000000000000000000000000000000000000000000000000000\n"
421 "000000000000000000000000000000000000000000000000000000000000000000000000000000\n"
422 "000000000000000000000000000000000000000000000000000000000000000000000000000000\n"
423 "000000000000000000\n"
424 "1111111111111111111";
425
426     fp = fopen("ascii2.tst", "wt");
427     fwrite(obuf, 1, sizeof(obuf), fp);
428     fclose(fp);
429
430     fp = fopen("ascii2.tst", "rt");
431     ok(getc(fp) == '0', "first char not 0\n");
432     memset(ibuf, 0, sizeof(ibuf));
433     i = fread(ibuf, 1, sizeof(ibuf), fp);
434     ok(i == sizeof(ibuf), "fread i %d != sizeof(ibuf)\n", i);
435     ok(0 == strncmp(ibuf, obuf+1, sizeof(ibuf)), "ibuf != obuf\n");
436     fclose(fp);
437     unlink("ascii2.tst");
438 }
439
440 static void test_filemodeT(void)
441 {
442     char DATA  [] = {26, 't', 'e', 's' ,'t'};
443     char DATA2 [100];
444     char temppath[MAX_PATH];
445     char tempfile[MAX_PATH];
446     FILE* f;
447     size_t bytesWritten;
448     size_t bytesRead;
449     WIN32_FIND_DATA findData;
450     HANDLE h;
451
452     GetTempPath (MAX_PATH, temppath);
453     GetTempFileName (temppath, "", 0, tempfile);
454
455     f = fopen(tempfile, "w+bDT");
456     bytesWritten = fwrite(DATA, 1, sizeof(DATA), f);
457     rewind(f);
458     bytesRead = fread(DATA2, 1, sizeof(DATA2), f);
459     fclose(f);
460
461     ok (bytesRead == bytesWritten && bytesRead == sizeof(DATA),
462         "fopen file mode 'T' wrongly interpreted as 't'\n" );
463
464     h = FindFirstFile(tempfile, &findData);
465
466     ok (h == INVALID_HANDLE_VALUE, "file wasn't deleted when closed.\n" );
467
468     if (h != INVALID_HANDLE_VALUE) FindClose(h);
469 }
470
471 static WCHAR* AtoW( const char* p )
472 {
473     WCHAR* buffer;
474     DWORD len = MultiByteToWideChar( CP_ACP, 0, p, -1, NULL, 0 );
475     buffer = malloc( len * sizeof(WCHAR) );
476     MultiByteToWideChar( CP_ACP, 0, p, -1, buffer, len );
477     return buffer;
478 }
479
480 /* Test reading in text mode when the 512'th character read is \r*/
481 static void test_readboundary(void)
482 {
483   FILE *fp;
484   char buf[513], rbuf[513];
485   int i, j;
486   for (i = 0; i < 511; i++)
487     {
488       j = (i%('~' - ' ')+ ' ');
489       buf[i] = j;
490     }
491   buf[511] = '\n';
492   buf[512] =0;
493   fp = fopen("boundary.tst", "wt");
494   fwrite(buf, 512,1,fp);
495   fclose(fp);
496   fp = fopen("boundary.tst", "rt");
497   for(i=0; i<512; i++)
498     {
499       fseek(fp,0 , SEEK_CUR);
500       rbuf[i] = fgetc(fp);
501     }
502   rbuf[512] =0;
503   fclose(fp);
504   unlink("boundary.tst");
505
506   ok(strcmp(buf, rbuf) == 0,"CRLF on buffer boundary failure\n");
507   }
508
509 static void test_fgetc( void )
510 {
511   char* tempf;
512   FILE *tempfh;
513   int  ich=0xe0, ret;
514
515   tempf=_tempnam(".","wne");
516   tempfh = fopen(tempf,"w+");
517   fputc(ich, tempfh);
518   fputc(ich, tempfh);
519   rewind(tempfh);
520   ret = fgetc(tempfh);
521   ok(ich == ret, "First fgetc expected %x got %x\n", ich, ret);
522   ret = fgetc(tempfh);
523   ok(ich == ret, "Second fgetc expected %x got %x\n", ich, ret);
524   fclose(tempfh);
525   tempfh = fopen(tempf,"wt");
526   fputc('\n', tempfh);
527   fclose(tempfh);
528   tempfh = fopen(tempf,"wt");
529   setbuf(tempfh, NULL);
530   ret = fgetc(tempfh);
531   ok(ret == -1, "Unbuffered fgetc in text mode must failed on \\r\\n\n");
532   fclose(tempfh);
533   unlink(tempf);
534   free(tempf);
535 }
536
537 static void test_fputc( void )
538 {
539   char* tempf;
540   FILE *tempfh;
541   int  ret;
542
543   tempf=_tempnam(".","wne");
544   tempfh = fopen(tempf,"wb");
545   ret = fputc(0,tempfh);
546   ok(0 == ret, "fputc(0,tempfh) expected %x got %x\n", 0, ret);
547   ret = fputc(0xff,tempfh);
548   ok(0xff == ret, "fputc(0xff,tempfh) expected %x got %x\n", 0xff, ret);
549   ret = fputc(0xffffffff,tempfh);
550   ok(0xff == ret, "fputc(0xffffffff,tempfh) expected %x got %x\n", 0xff, ret);
551   fclose(tempfh);
552
553   tempfh = fopen(tempf,"rb");
554   ret = fputc(0,tempfh);
555   ok(EOF == ret, "fputc(0,tempfh) on r/o file expected %x got %x\n", EOF, ret);
556   fclose(tempfh);
557
558   unlink(tempf);
559   free(tempf);
560 }
561
562 static void test_flsbuf( void )
563 {
564   char* tempf;
565   FILE *tempfh;
566   int  c;
567   int  ret;
568   int  bufmode;
569   static const int bufmodes[] = {_IOFBF,_IONBF};
570
571   tempf=_tempnam(".","wne");
572   for (bufmode=0; bufmode < sizeof(bufmodes)/sizeof(bufmodes[0]); bufmode++)
573   {
574     tempfh = fopen(tempf,"wb");
575     setvbuf(tempfh,NULL,bufmodes[bufmode],2048);
576     ret = _flsbuf(0,tempfh);
577     ok(0 == ret, "_flsbuf(0,tempfh) with bufmode %x expected %x got %x\n",
578                          bufmodes[bufmode], 0, ret);
579     ret = _flsbuf(0xff,tempfh);
580     ok(0xff == ret, "_flsbuf(0xff,tempfh) with bufmode %x expected %x got %x\n",
581                          bufmodes[bufmode], 0xff, ret);
582     ret = _flsbuf(0xffffffff,tempfh);
583     ok(0xff == ret, "_flsbuf(0xffffffff,tempfh) with bufmode %x expected %x got %x\n",
584                          bufmodes[bufmode], 0xff, ret);
585     if(tempfh->_base) {
586         fputc('x', tempfh);
587         tempfh->_cnt = -1;
588         tempfh->_base[1] = 'a';
589         ret = _flsbuf(0xab,tempfh);
590         ok(ret == 0xab, "_flsbuf(0xab,tempfh) with bufmode %x expected 0xab got %x\n",
591                 bufmodes[bufmode], ret);
592         ok(tempfh->_base[1] == 'a', "tempfh->_base[1] should not be changed (%d)\n",
593                 tempfh->_base[1]);
594     }
595
596     fclose(tempfh);
597   }
598
599   tempfh = fopen(tempf,"rb");
600   ret = _flsbuf(0,tempfh);
601   ok(EOF == ret, "_flsbuf(0,tempfh) on r/o file expected %x got %x\n", EOF, ret);
602   fclose(tempfh);
603
604   /* See bug 17123, exposed by WinAVR's make */
605   tempfh = fopen(tempf,"w");
606   ok(tempfh->_cnt == 0, "_cnt on freshly opened file was %d\n", tempfh->_cnt);
607   setbuf(tempfh, NULL);
608   ok(tempfh->_cnt == 0, "_cnt on unbuffered file was %d\n", tempfh->_cnt);
609   /* Inlined putchar sets _cnt to -1.  Native seems to ignore the value... */
610   tempfh->_cnt = 1234;
611   ret = _flsbuf('Q',tempfh);
612   ok('Q' == ret, "_flsbuf('Q',tempfh) expected %x got %x\n", 'Q', ret);
613   /* ... and reset it to zero */
614   ok(tempfh->_cnt == 0, "after unbuf _flsbuf, _cnt was %d\n", tempfh->_cnt);
615   fclose(tempfh);
616   /* And just for grins, make sure the file is correct */
617   tempfh = fopen(tempf,"r");
618   c = fgetc(tempfh);
619   ok(c == 'Q', "first byte should be 'Q'\n");
620   c = fgetc(tempfh);
621   ok(c == EOF, "there should only be one byte\n");
622   fclose(tempfh);
623
624   unlink(tempf);
625   free(tempf);
626 }
627
628 static void test_fflush( void )
629 {
630   static const char obuf[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
631   char buf1[16], buf2[24];
632   char *tempf;
633   FILE *tempfh;
634   int ret;
635
636   tempf=_tempnam(".","wne");
637
638   /* Prepare the file. */
639   tempfh = fopen(tempf,"wb");
640   ok(tempfh != NULL, "Can't open test file.\n");
641   fwrite(obuf, 1, sizeof(obuf), tempfh);
642   fclose(tempfh);
643
644   /* Open the file for input. */
645   tempfh = fopen(tempf,"rb");
646   ok(tempfh != NULL, "Can't open test file.\n");
647   fread(buf1, 1, sizeof(buf1), tempfh);
648
649   /* Using fflush() on input stream is undefined in ANSI.
650    * But MSDN says that it clears input buffer. */
651   _lseek(_fileno(tempfh), 0, SEEK_SET);
652   ret = fflush(tempfh);
653   ok(ret == 0, "expected 0, got %d\n", ret);
654   memset(buf2, '?', sizeof(buf2));
655   fread(buf2, 1, sizeof(buf2), tempfh);
656   ok(memcmp(buf1, buf2, sizeof(buf1)) == 0, "Got unexpected data (%c)\n", buf2[0]);
657
658   /* fflush(NULL) doesn't clear input buffer. */
659   _lseek(_fileno(tempfh), 0, SEEK_SET);
660   ret = fflush(NULL);
661   ok(ret == 0, "expected 0, got %d\n", ret);
662   memset(buf2, '?', sizeof(buf2));
663   fread(buf2, 1, sizeof(buf2), tempfh);
664   ok(memcmp(buf1, buf2, sizeof(buf1)) != 0, "Got unexpected data (%c)\n", buf2[0]);
665
666   /* _flushall() clears input buffer. */
667   _lseek(_fileno(tempfh), 0, SEEK_SET);
668   ret = _flushall();
669   ok(ret >= 0, "unexpected ret %d\n", ret);
670   memset(buf2, '?', sizeof(buf2));
671   fread(buf2, 1, sizeof(buf2), tempfh);
672   ok(memcmp(buf1, buf2, sizeof(buf1)) == 0, "Got unexpected data (%c)\n", buf2[0]);
673
674   fclose(tempfh);
675
676   unlink(tempf);
677   free(tempf);
678 }
679
680 static void test_fgetwc( void )
681 {
682 #define LLEN 512
683
684   char* tempf;
685   FILE *tempfh;
686   static const char mytext[]= "This is test_fgetwc\r\n";
687   WCHAR wtextW[BUFSIZ+LLEN+1];
688   WCHAR *mytextW = NULL, *aptr, *wptr;
689   BOOL diff_found = FALSE;
690   int j;
691   unsigned int i;
692   LONG l;
693
694   tempf=_tempnam(".","wne");
695   tempfh = fopen(tempf,"wb");
696   j = 'a';
697   /* pad to almost the length of the internal buffer */
698   for (i=0; i<BUFSIZ-4; i++)
699     fputc(j,tempfh);
700   j = '\r';
701   fputc(j,tempfh);
702   j = '\n';
703   fputc(j,tempfh);
704   fputs(mytext,tempfh);
705   fclose(tempfh);
706   /* in text mode, getws/c expects multibyte characters */
707   /*currently Wine only supports plain ascii, and that is all that is tested here */
708   tempfh = fopen(tempf,"rt"); /* open in TEXT mode */
709   fgetws(wtextW,LLEN,tempfh);
710   l=ftell(tempfh);
711   ok(l==BUFSIZ-2, "ftell expected %d got %d\n", BUFSIZ-2, l);
712   fgetws(wtextW,LLEN,tempfh);
713   l=ftell(tempfh);
714   ok(l==BUFSIZ-2+strlen(mytext), "ftell expected %d got %d\n", BUFSIZ-2+lstrlen(mytext), l);
715   mytextW = AtoW (mytext);
716   aptr = mytextW;
717   wptr = wtextW;
718   for (i=0; i<strlen(mytext)-2; i++, aptr++, wptr++)
719     {
720       diff_found |= (*aptr != *wptr);
721     }
722   ok(!(diff_found), "fgetwc difference found in TEXT mode\n");
723   ok(*wptr == '\n', "Carriage return was not skipped\n");
724   fclose(tempfh);
725   unlink(tempf);
726   
727   tempfh = fopen(tempf,"wb");
728   j = 'a';
729   /* pad to almost the length of the internal buffer. Use an odd number of bytes
730      to test that we can read wchars that are split across the internal buffer
731      boundary */
732   for (i=0; i<BUFSIZ-3-strlen(mytext)*sizeof(WCHAR); i++)
733     fputc(j,tempfh);
734   j = '\r';
735   fputwc(j,tempfh);
736   j = '\n';
737   fputwc(j,tempfh);
738   fputws(wtextW,tempfh);
739   fputws(wtextW,tempfh);
740   fclose(tempfh);
741   /* in binary mode, getws/c expects wide characters */
742   tempfh = fopen(tempf,"rb"); /* open in BINARY mode */
743   j=(BUFSIZ-2)/sizeof(WCHAR)-strlen(mytext);
744   fgetws(wtextW,j,tempfh);
745   l=ftell(tempfh);
746   j=(j-1)*sizeof(WCHAR);
747   ok(l==j, "ftell expected %d got %d\n", j, l);
748   i=fgetc(tempfh);
749   ok(i=='a', "fgetc expected %d got %d\n", 0x61, i);
750   l=ftell(tempfh);
751   j++;
752   ok(l==j, "ftell expected %d got %d\n", j, l);
753   fgetws(wtextW,3,tempfh);
754   ok(wtextW[0]=='\r',"expected carriage return got %04hx\n", wtextW[0]);
755   ok(wtextW[1]=='\n',"expected newline got %04hx\n", wtextW[1]);
756   l=ftell(tempfh);
757   j += 4;
758   ok(l==j, "ftell expected %d got %d\n", j, l);
759   for(i=0; i<strlen(mytext); i++)
760     wtextW[i] = 0;
761   /* the first time we get the string, it should be entirely within the local buffer */
762   fgetws(wtextW,LLEN,tempfh);
763   l=ftell(tempfh);
764   j += (strlen(mytext)-1)*sizeof(WCHAR);
765   ok(l==j, "ftell expected %d got %d\n", j, l);
766   diff_found = FALSE;
767   aptr = mytextW;
768   wptr = wtextW;
769   for (i=0; i<strlen(mytext)-2; i++, aptr++, wptr++)
770     {
771       ok(*aptr == *wptr, "Char %d expected %04hx got %04hx\n", i, *aptr, *wptr);
772       diff_found |= (*aptr != *wptr);
773     }
774   ok(!(diff_found), "fgetwc difference found in BINARY mode\n");
775   ok(*wptr == '\n', "Should get newline\n");
776   for(i=0; i<strlen(mytext); i++)
777     wtextW[i] = 0;
778   /* the second time we get the string, it should cross the local buffer boundary.
779      One of the wchars should be split across the boundary */
780   fgetws(wtextW,LLEN,tempfh);
781   diff_found = FALSE;
782   aptr = mytextW;
783   wptr = wtextW;
784   for (i=0; i<strlen(mytext)-2; i++, aptr++, wptr++)
785     {
786       ok(*aptr == *wptr, "Char %d expected %04hx got %04hx\n", i, *aptr, *wptr);
787       diff_found |= (*aptr != *wptr);
788     }
789   ok(!(diff_found), "fgetwc difference found in BINARY mode\n");
790   ok(*wptr == '\n', "Should get newline\n");
791
792   free(mytextW);
793   fclose(tempfh);
794   unlink(tempf);
795   free(tempf);
796 }
797
798 static void test_fgetwc_locale(const char* text, const char* locale, int codepage)
799 {
800     char temppath[MAX_PATH], tempfile[MAX_PATH];
801     FILE *tempfh;
802     static const WCHAR wchar_text[] = { 0xfeff, 0xff1f, '!' };
803     WCHAR wtextW[BUFSIZ];
804     int ret = 0, i;
805     wint_t ch;
806
807     if (!setlocale(LC_CTYPE, locale))
808     {
809         win_skip("%s locale not available\n", locale);
810         return;
811     }
812
813     GetTempPath(MAX_PATH, temppath);
814     GetTempFileName(temppath, "", 0, tempfile);
815
816     tempfh = fopen(tempfile, "wb");
817     ok(tempfh != NULL, "can't open tempfile\n");
818     fwrite(text, 1, strlen(text), tempfh);
819     fclose(tempfh);
820
821     if (codepage != 0)
822     {
823         /* mbstowcs rejects invalid multibyte sequence,
824            so we use MultiByteToWideChar here. */
825         ret = MultiByteToWideChar(codepage, 0, text, -1,
826                                   wtextW, sizeof(wtextW)/sizeof(wtextW[0]));
827         ok(ret > 0, "MultiByteToWideChar failed\n");
828     }
829     else
830     {
831         /* C locale */
832         const char *p;
833         for (p = text; *p != '\0'; p++)
834             wtextW[ret++] = (unsigned char)*p;
835         wtextW[ret++] = 0;
836     }
837
838     tempfh = fopen(tempfile, "rt");
839     ok(tempfh != NULL, "can't open tempfile\n");
840
841     for (i = 0; i < ret-1; i++)
842     {
843         ch = fgetwc(tempfh);
844         ok(ch == wtextW[i], "got %04hx, expected %04hx (cp%d[%d])\n", ch, wtextW[i], codepage, i);
845     }
846     ch = fgetwc(tempfh);
847     ok(ch == WEOF, "got %04hx, expected WEOF (cp%d)\n", ch, codepage);
848     fclose(tempfh);
849
850     tempfh = fopen(tempfile, "wb");
851     ok(tempfh != NULL, "can't open tempfile\n");
852     fwrite(wchar_text, 1, sizeof(wchar_text), tempfh);
853     fclose(tempfh);
854
855     tempfh = fopen(tempfile, "rb");
856     ok(tempfh != NULL, "can't open tempfile\n");
857     for (i = 0; i < sizeof(wchar_text)/sizeof(wchar_text[0]); i++)
858     {
859         ch = fgetwc(tempfh);
860         ok(ch == wchar_text[i], "got %04hx, expected %04x (cp%d[%d])\n", ch, wchar_text[i], codepage, i);
861     }
862     ch = fgetwc(tempfh);
863     ok(ch == WEOF, "got %04hx, expected WEOF (cp%d)\n", ch, codepage);
864     fclose(tempfh);
865     unlink(tempfile);
866 }
867
868 static void test_fgetwc_unicode(void)
869 {
870     char temppath[MAX_PATH], tempfile[MAX_PATH];
871     FILE *tempfh;
872     static const WCHAR wchar_text[] = { 0xfeff, 0xff1f, '!' };
873     char utf8_text[BUFSIZ];
874     int ret, i;
875     wint_t ch;
876
877     GetTempPath(MAX_PATH, temppath);
878     GetTempFileName(temppath, "", 0, tempfile);
879
880     if (!p_fopen_s)
881     {
882         win_skip("fopen_s not available\n");
883         return;
884     }
885
886     tempfh = fopen(tempfile, "wb");
887     ok(tempfh != NULL, "can't open tempfile\n");
888     fwrite(wchar_text, 1, sizeof(wchar_text), tempfh);
889     fclose(tempfh);
890
891     tempfh = fopen(tempfile, "rt,ccs=unicode");
892     ok(tempfh != NULL, "can't open tempfile\n");
893     for (i = 1; i < sizeof(wchar_text)/sizeof(wchar_text[0]); i++)
894     {
895         ch = fgetwc(tempfh);
896         ok(ch == wchar_text[i],
897            "got %04hx, expected %04x (unicode[%d])\n", ch, wchar_text[i], i-1);
898     }
899     ch = fgetwc(tempfh);
900     ok(ch == WEOF, "got %04hx, expected WEOF (unicode)\n", ch);
901     fclose(tempfh);
902
903     tempfh = fopen(tempfile, "wb");
904     ok(tempfh != NULL, "can't open tempfile\n");
905     ret = WideCharToMultiByte(CP_UTF8, 0, wchar_text, sizeof(wchar_text)/sizeof(wchar_text[0]),
906                               utf8_text, sizeof(utf8_text), NULL, NULL);
907     ok(ret > 0, "utf-8 conversion failed\n");
908     fwrite(utf8_text, sizeof(char), ret, tempfh);
909     fclose(tempfh);
910
911     tempfh = fopen(tempfile, "rt, ccs=UTF-8");
912     ok(tempfh != NULL, "can't open tempfile\n");
913     for (i = 1; i < sizeof(wchar_text)/sizeof(wchar_text[0]); i++)
914     {
915         ch = fgetwc(tempfh);
916         ok(ch == wchar_text[i],
917            "got %04hx, expected %04x (utf8[%d])\n", ch, wchar_text[i], i-1);
918     }
919     ch = fgetwc(tempfh);
920     ok(ch == WEOF, "got %04hx, expected WEOF (utf8)\n", ch);
921     fclose(tempfh);
922     unlink(temppath);
923 }
924
925 static void test_fputwc(void)
926 {
927     char temppath[MAX_PATH];
928     char tempfile[MAX_PATH];
929     FILE *f;
930     char buf[1024];
931     int ret;
932
933     GetTempPath (MAX_PATH, temppath);
934     GetTempFileName (temppath, "", 0, tempfile);
935
936     f = fopen(tempfile, "w");
937     ret = fputwc('a', f);
938     ok(ret == 'a', "fputwc returned %x, expected 'a'\n", ret);
939     ret = fputwc('\n', f);
940     ok(ret == '\n', "fputwc returned %x, expected '\\n'\n", ret);
941     fclose(f);
942
943     f = fopen(tempfile, "rb");
944     ret = fread(buf, 1, sizeof(buf), f);
945     ok(ret == 3, "fread returned %d, expected 3\n", ret);
946     ok(!memcmp(buf, "a\r\n", 3), "incorrect file data\n");
947     fclose(f);
948
949     if(p_fopen_s) {
950         f = fopen(tempfile, "w,ccs=unicode");
951         ret = fputwc('a', f);
952         ok(ret == 'a', "fputwc returned %x, expected 'a'\n", ret);
953         ret = fputwc('\n', f);
954         ok(ret == '\n', "fputwc returned %x, expected '\\n'\n", ret);
955         fclose(f);
956
957         f = fopen(tempfile, "rb");
958         ret = fread(buf, 1, sizeof(buf), f);
959         ok(ret == 8, "fread returned %d, expected 8\n", ret);
960         ok(!memcmp(buf, "\xff\xfe\x61\x00\r\x00\n\x00", 8), "incorrect file data\n");
961         fclose(f);
962
963         f = fopen(tempfile, "w,ccs=utf-8");
964         ret = fputwc('a', f);
965         ok(ret == 'a', "fputwc returned %x, expected 'a'\n", ret);
966         ret = fputwc('\n', f);
967         ok(ret == '\n', "fputwc returned %x, expected '\\n'\n", ret);
968         fclose(f);
969
970         f = fopen(tempfile, "rb");
971         ret = fread(buf, 1, sizeof(buf), f);
972         ok(ret == 6, "fread returned %d, expected 6\n", ret);
973         ok(!memcmp(buf, "\xef\xbb\xbf\x61\r\n", 6), "incorrect file data\n");
974         fclose(f);
975     }else {
976         win_skip("fputwc tests on unicode files\n");
977     }
978
979     _unlink(tempfile);
980 }
981
982 static void test_ctrlz( void )
983 {
984   char* tempf;
985   FILE *tempfh;
986   static const char mytext[]= "This is test_ctrlz";
987   char buffer[256];
988   int i, j;
989   LONG l;
990
991   tempf=_tempnam(".","wne");
992   tempfh = fopen(tempf,"wb");
993   fputs(mytext,tempfh);
994   j = 0x1a; /* a ctrl-z character signals EOF in text mode */
995   fputc(j,tempfh);
996   j = '\r';
997   fputc(j,tempfh);
998   j = '\n';
999   fputc(j,tempfh);
1000   j = 'a';
1001   fputc(j,tempfh);
1002   fclose(tempfh);
1003   tempfh = fopen(tempf,"rt"); /* open in TEXT mode */
1004   ok(fgets(buffer,256,tempfh) != 0,"fgets failed unexpected\n");
1005   i=strlen(buffer);
1006   j=strlen(mytext);
1007   ok(i==j, "returned string length expected %d got %d\n", j, i);
1008   j+=4; /* ftell should indicate the true end of file */
1009   l=ftell(tempfh);
1010   ok(l==j, "ftell expected %d got %d\n", j, l);
1011   ok(feof(tempfh), "did not get EOF\n");
1012   fclose(tempfh);
1013   
1014   tempfh = fopen(tempf,"rb"); /* open in BINARY mode */
1015   ok(fgets(buffer,256,tempfh) != 0,"fgets failed unexpected\n");
1016   i=strlen(buffer);
1017   j=strlen(mytext)+3; /* should get through newline */
1018   ok(i==j, "returned string length expected %d got %d\n", j, i);
1019   l=ftell(tempfh);
1020   ok(l==j, "ftell expected %d got %d\n", j, l);
1021   ok(fgets(buffer,256,tempfh) != 0,"fgets failed unexpected\n");
1022   i=strlen(buffer);
1023   ok(i==1, "returned string length expected %d got %d\n", 1, i);
1024   ok(feof(tempfh), "did not get EOF\n");
1025   fclose(tempfh);
1026   unlink(tempf);
1027   free(tempf);
1028 }
1029
1030 static void test_file_put_get( void )
1031 {
1032   char* tempf;
1033   FILE *tempfh;
1034   static const char mytext[]=  "This is a test_file_put_get\n";
1035   static const char dostext[]= "This is a test_file_put_get\r\n";
1036   char btext[LLEN];
1037   WCHAR wtextW[LLEN+1];
1038   WCHAR *mytextW = NULL, *aptr, *wptr;
1039   BOOL diff_found = FALSE;
1040   unsigned int i;
1041
1042   tempf=_tempnam(".","wne");
1043   tempfh = fopen(tempf,"wt"); /* open in TEXT mode */
1044   fputs(mytext,tempfh);
1045   fclose(tempfh);
1046   tempfh = fopen(tempf,"rb"); /* open in TEXT mode */
1047   fgets(btext,LLEN,tempfh);
1048   ok( strlen(mytext) + 1 == strlen(btext),"TEXT/BINARY mode not handled for write\n");
1049   ok( btext[strlen(mytext)-1] == '\r', "CR not written\n");
1050   fclose(tempfh);
1051   tempfh = fopen(tempf,"wb"); /* open in BINARY mode */
1052   fputs(dostext,tempfh);
1053   fclose(tempfh);
1054   tempfh = fopen(tempf,"rt"); /* open in TEXT mode */
1055   fgets(btext,LLEN,tempfh);
1056   ok(strcmp(btext, mytext) == 0,"_O_TEXT read doesn't strip CR\n");
1057   fclose(tempfh);
1058   tempfh = fopen(tempf,"rb"); /* open in TEXT mode */
1059   fgets(btext,LLEN,tempfh);
1060   ok(strcmp(btext, dostext) == 0,"_O_BINARY read doesn't preserve CR\n");
1061
1062   fclose(tempfh);
1063   tempfh = fopen(tempf,"rt"); /* open in TEXT mode */
1064   fgetws(wtextW,LLEN,tempfh);
1065   mytextW = AtoW (mytext);
1066   aptr = mytextW;
1067   wptr = wtextW;
1068
1069   for (i=0; i<strlen(mytext); i++, aptr++, wptr++)
1070     {
1071       diff_found |= (*aptr != *wptr);
1072     }
1073   ok(!(diff_found), "fgetwc doesn't strip CR in TEXT mode\n");
1074   free(mytextW);
1075   fclose(tempfh);
1076   unlink(tempf);
1077   free(tempf);
1078 }
1079
1080 static void test_file_write_read( void )
1081 {
1082   char* tempf;
1083   int tempfd;
1084   static const char mytext[]=  "This is test_file_write_read\nsecond line\n";
1085   static const char dostext[]= "This is test_file_write_read\r\nsecond line\r\n";
1086   char btext[LLEN];
1087   int ret, i;
1088
1089   tempf=_tempnam(".","wne");
1090   tempfd = _open(tempf,_O_CREAT|_O_TRUNC|_O_BINARY|_O_RDWR,
1091                      _S_IREAD | _S_IWRITE);
1092   ok( tempfd != -1,
1093      "Can't open '%s': %d\n", tempf, errno); /* open in BINARY mode */
1094   ok(_write(tempfd,dostext,strlen(dostext)) == lstrlenA(dostext),
1095      "_write _O_BINARY bad return value\n");
1096   _close(tempfd);
1097   i = lstrlenA(mytext);
1098   tempfd = _open(tempf,_O_RDONLY|_O_BINARY,0); /* open in BINARY mode */
1099   ok(_read(tempfd,btext,i) == i,
1100      "_read _O_BINARY got bad length\n");
1101   ok( memcmp(dostext,btext,i) == 0,
1102       "problems with _O_BINARY  _write / _read\n");
1103   _close(tempfd);
1104   tempfd = _open(tempf,_O_RDONLY|_O_TEXT); /* open in TEXT mode */
1105   ok(_read(tempfd,btext,i) == i-1,
1106      "_read _O_TEXT got bad length\n");
1107   ok( memcmp(mytext,btext,i-1) == 0,
1108       "problems with _O_BINARY _write / _O_TEXT _read\n");
1109   _close(tempfd);
1110   tempfd = _open(tempf,_O_CREAT|_O_TRUNC|_O_TEXT|_O_RDWR,
1111                      _S_IREAD | _S_IWRITE);
1112   ok( tempfd != -1,
1113      "Can't open '%s': %d\n", tempf, errno); /* open in TEXT mode */
1114   ok(_write(tempfd,mytext,strlen(mytext)) == lstrlenA(mytext),
1115      "_write _O_TEXT bad return value\n");
1116   _close(tempfd);
1117   tempfd = _open(tempf,_O_RDONLY|_O_BINARY,0); /* open in BINARY mode */
1118   ok(_read(tempfd,btext,LLEN) == lstrlenA(dostext),
1119      "_read _O_BINARY got bad length\n");
1120   ok( memcmp(dostext,btext,strlen(dostext)) == 0,
1121       "problems with _O_TEXT _write / _O_BINARY _read\n");
1122   ok( btext[strlen(dostext)-2] == '\r', "CR not written or read\n");
1123   _close(tempfd);
1124   tempfd = _open(tempf,_O_RDONLY|_O_TEXT); /* open in TEXT mode */
1125   ok(_read(tempfd,btext,LLEN) == lstrlenA(mytext),
1126      "_read _O_TEXT got bad length\n");
1127   ok( memcmp(mytext,btext,strlen(mytext)) == 0,
1128       "problems with _O_TEXT _write / _read\n");
1129   _close(tempfd);
1130
1131   memset(btext, 0, LLEN);
1132   tempfd = _open(tempf,_O_APPEND|_O_RDWR); /* open for APPEND in default mode */
1133   ok(tell(tempfd) == 0, "bad position %u expecting 0\n", tell(tempfd));
1134   ok(_read(tempfd,btext,LLEN) == lstrlenA(mytext), "_read _O_APPEND got bad length\n");
1135   ok( memcmp(mytext,btext,strlen(mytext)) == 0, "problems with _O_APPEND _read\n");
1136   _close(tempfd);
1137
1138   /* Test reading only \n or \r */
1139   tempfd = _open(tempf,_O_RDONLY|_O_TEXT); /* open in TEXT mode */
1140   _lseek(tempfd, -1, FILE_END);
1141   ret = _read(tempfd,btext,LLEN);
1142   ok(ret == 1 && *btext == '\n', "_read expected 1 got bad length: %d\n", ret);
1143   _lseek(tempfd, -2, FILE_END);
1144   ret = _read(tempfd,btext,LLEN);
1145   ok(ret == 1 && *btext == '\n', "_read expected '\\n' got bad length: %d\n", ret);
1146   _lseek(tempfd, -2, FILE_END);
1147   ret = _read(tempfd,btext,1);
1148   ok(ret == 1 && *btext == '\n', "_read returned %d, buf: %d\n", ret, *btext);
1149   ret = read(tempfd,btext,1);
1150   ok(ret == 0, "_read returned %d, expected 0\n", ret);
1151   _lseek(tempfd, -3, FILE_END);
1152   ret = _read(tempfd,btext,1);
1153   ok(ret == 1 && *btext == 'e', "_read expected 'e' got \"%.*s\" bad length: %d\n", ret, btext, ret);
1154   ok(tell(tempfd) == 41, "bad position %u expecting 41\n", tell(tempfd));
1155   _lseek(tempfd, -3, FILE_END);
1156   ret = _read(tempfd,btext,2);
1157   ok(ret == 1 && *btext == 'e', "_read expected 'e' got \"%.*s\" bad length: %d\n", ret, btext, ret);
1158   ok(tell(tempfd) == 42, "bad position %u expecting 42\n", tell(tempfd));
1159   _lseek(tempfd, -3, FILE_END);
1160   ret = _read(tempfd,btext,3);
1161   ok(ret == 2 && *btext == 'e', "_read expected 'e' got \"%.*s\" bad length: %d\n", ret, btext, ret);
1162   ok(tell(tempfd) == 43, "bad position %u expecting 43\n", tell(tempfd));
1163    _close(tempfd);
1164
1165   ret = unlink(tempf);
1166   ok( ret == 0 ,"Can't unlink '%s': %d\n", tempf, errno);
1167   free(tempf);
1168
1169   tempf=_tempnam(".","wne");
1170   tempfd = _open(tempf, _O_CREAT|_O_TRUNC|_O_BINARY|_O_RDWR, _S_IWRITE);
1171   ok( tempfd != -1,
1172      "Can't open '%s': %d\n", tempf, errno); /* open in BINARY mode */
1173   ok(_write(tempfd,dostext,strlen(dostext)) == lstrlenA(dostext),
1174      "_write _O_BINARY bad return value\n");
1175   _close(tempfd);
1176   tempfd = _open(tempf,_O_RDONLY|_O_BINARY,0); /* open in BINARY mode */
1177   ok(_read(tempfd,btext,LLEN) == lstrlenA(dostext),
1178      "_read _O_BINARY got bad length\n");
1179   ok( memcmp(dostext,btext,strlen(dostext)) == 0,
1180       "problems with _O_BINARY _write / _read\n");
1181   ok( btext[strlen(dostext)-2] == '\r', "CR not written or read\n");
1182   _close(tempfd);
1183   tempfd = _open(tempf,_O_RDONLY|_O_TEXT); /* open in TEXT mode */
1184   ok(_read(tempfd,btext,LLEN) == lstrlenA(mytext),
1185      "_read _O_TEXT got bad length\n");
1186   ok( memcmp(mytext,btext,strlen(mytext)) == 0,
1187       "problems with _O_BINARY _write / _O_TEXT _read\n");
1188   _close(tempfd);
1189
1190   /* test _read with single bytes. CR should be skipped and LF pulled in */
1191   tempfd = _open(tempf,_O_RDONLY|_O_TEXT); /* open in TEXT mode */
1192   for (i=0; i<strlen(mytext); i++)  /* */
1193     {
1194       _read(tempfd,btext, 1);
1195       ok(btext[0] ==  mytext[i],"_read failed at pos %d 0x%02x vs 0x%02x\n", i, btext[0], mytext[i]);
1196     }
1197   while (_read(tempfd,btext, 1));
1198   _close(tempfd);
1199
1200   /* test _read in buffered mode. Last CR should be skipped but  LF not pulled in */
1201   tempfd = _open(tempf,_O_RDONLY|_O_TEXT); /* open in TEXT mode */
1202   i = _read(tempfd,btext, strlen(mytext));
1203   ok(i == strlen(mytext)-1, "_read_i %d\n", i);
1204   _close(tempfd);
1205
1206   /* test read/write in unicode mode */
1207   if(p_fopen_s)
1208   {
1209       tempfd = _open(tempf, _O_CREAT|_O_TRUNC|_O_WRONLY|_O_WTEXT, _S_IWRITE);
1210       ok(tempfd != -1, "_open failed with error: %d\n", errno);
1211       ret = _write(tempfd, "a", 1);
1212       ok(ret == -1, "_write returned %d, expected -1\n", ret);
1213       ret = _write(tempfd, "a\x00\n\x00\xff\xff", 6);
1214       ok(ret == 6, "_write returned %d, expected 6\n", ret);
1215       _close(tempfd);
1216
1217       tempfd = _open(tempf, _O_RDONLY|_O_BINARY, 0);
1218       ok(tempfd != -1, "_open failed with error: %d\n", errno);
1219       ret = _read(tempfd, btext, sizeof(btext));
1220       ok(ret == 10, "_read returned %d, expected 10\n", ret);
1221       ok(!memcmp(btext, "\xff\xfe\x61\x00\r\x00\n\x00\xff\xff", 10), "btext is incorrect\n");
1222       _close(tempfd);
1223
1224       tempfd = _open(tempf, _O_RDONLY|_O_WTEXT, 0);
1225       ok(tempfd != -1, "_open failed with error: %d\n", errno);
1226       errno = 0xdeadbeef;
1227       ret = _read(tempfd, btext, 3);
1228       ok(ret == -1, "_read returned %d, expected -1\n", ret);
1229       ok(errno == 22, "errno = %d\n", errno);
1230       ret = _read(tempfd, btext, sizeof(btext));
1231       ok(ret == 6, "_read returned %d, expected 6\n", ret);
1232       ok(!memcmp(btext, "\x61\x00\n\x00\xff\xff", 6), "btext is incorrect\n");
1233       _close(tempfd);
1234
1235       tempfd = _open(tempf, _O_CREAT|_O_TRUNC|_O_WRONLY|_O_U8TEXT, _S_IWRITE);
1236       ok(tempfd != -1, "_open failed with error: %d\n", errno);
1237       errno = 0xdeadbeef;
1238       ret = _write(tempfd, "a", 1);
1239       ok(ret == -1, "_write returned %d, expected -1\n", ret);
1240       ok(errno == 22, "errno = %d\n", errno);
1241       ret = _write(tempfd, "a\x00\n\x00\x62\x00", 6);
1242       ok(ret == 6, "_write returned %d, expected 6\n", ret);
1243       _close(tempfd);
1244
1245       tempfd = _open(tempf, _O_RDONLY|_O_BINARY, 0);
1246       ok(tempfd != -1, "_open failed with error: %d\n", errno);
1247       ret = _read(tempfd, btext, sizeof(btext));
1248       ok(ret == 7, "_read returned %d, expected 7\n", ret);
1249       ok(!memcmp(btext, "\xef\xbb\xbf\x61\r\n\x62", 7), "btext is incorrect\n");
1250       _close(tempfd);
1251
1252       tempfd = _open(tempf, _O_RDONLY|_O_WTEXT, 0);
1253       ok(tempfd != -1, "_open failed with error: %d\n", errno);
1254       ret = _read(tempfd, btext, sizeof(btext));
1255       ok(ret == 6, "_read returned %d, expected 6\n", ret);
1256       ok(!memcmp(btext, "\x61\x00\n\x00\x62\x00", 6), "btext is incorrect\n");
1257
1258       /* when buffer is small read sometimes fails in native implementation */
1259       lseek(tempfd, 3 /* skip bom */, SEEK_SET);
1260       ret = _read(tempfd, btext, 4);
1261       todo_wine ok(ret == -1, "_read returned %d, expected -1\n", ret);
1262
1263       lseek(tempfd, 6, SEEK_SET);
1264       ret = _read(tempfd, btext, 2);
1265       ok(ret == 2, "_read returned %d, expected 2\n", ret);
1266       ok(!memcmp(btext, "\x62\x00", 2), "btext is incorrect\n");
1267       _close(tempfd);
1268
1269       tempfd = _open(tempf, _O_CREAT|_O_TRUNC|_O_WRONLY|_O_BINARY, _S_IWRITE);
1270       ok(tempfd != -1, "_open failed with error: %d\n", errno);
1271       ret = _write(tempfd, "\xef\xbb\xbf\x61\xc4\x85\x62\xc5\xbc\r\r\n", 12);
1272       ok(ret == 12, "_write returned %d, expected 9\n", ret);
1273       _close(tempfd);
1274
1275       tempfd = _open(tempf, _O_RDONLY|_O_WTEXT, 0);
1276       ok(tempfd != -1, "_open failed with error: %d\n", errno);
1277       ret = _read(tempfd, btext, sizeof(btext));
1278       ok(ret == 12, "_read returned %d, expected 12\n", ret);
1279       ok(!memcmp(btext, "\x61\x00\x05\x01\x62\x00\x7c\x01\x0d\x00\x0a\x00", 12), "btext is incorrect\n");
1280
1281       /* test invalid utf8 sequence */
1282       lseek(tempfd, 5, SEEK_SET);
1283       ret = _read(tempfd, btext, sizeof(btext));
1284       todo_wine ok(ret == 10, "_read returned %d, expected 10\n", ret);
1285       /* invalid char should be replaced by U+FFFD in MultiByteToWideChar */
1286       todo_wine ok(!memcmp(btext, "\xfd\xff", 2), "invalid UTF8 character was not replaced by U+FFFD\n");
1287       ok(!memcmp(btext+ret-8, "\x62\x00\x7c\x01\x0d\x00\x0a\x00", 8), "btext is incorrect\n");
1288       _close(tempfd);
1289   }
1290   else
1291   {
1292       win_skip("unicode mode tests on file\n");
1293   }
1294
1295   ret =_chmod (tempf, _S_IREAD | _S_IWRITE);
1296   ok( ret == 0,
1297      "Can't chmod '%s' to read-write: %d\n", tempf, errno);
1298   ret = unlink(tempf);
1299   ok( ret == 0 ,"Can't unlink '%s': %d\n", tempf, errno);
1300   free(tempf);
1301 }
1302
1303 static void test_file_inherit_child(const char* fd_s)
1304 {
1305     int fd = atoi(fd_s);
1306     char buffer[32];
1307     int ret;
1308
1309     ret =write(fd, "Success", 8);
1310     ok( ret == 8, "Couldn't write in child process on %d (%s)\n", fd, strerror(errno));
1311     lseek(fd, 0, SEEK_SET);
1312     ok(read(fd, buffer, sizeof (buffer)) == 8, "Couldn't read back the data\n");
1313     ok(memcmp(buffer, "Success", 8) == 0, "Couldn't read back the data\n");
1314 }
1315
1316 static void test_file_inherit_child_no(const char* fd_s)
1317 {
1318     int fd = atoi(fd_s);
1319     int ret;
1320
1321     ret = write(fd, "Success", 8);
1322     ok( ret == -1 && errno == EBADF, 
1323        "Wrong write result in child process on %d (%s)\n", fd, strerror(errno));
1324 }
1325
1326 static void create_io_inherit_block( STARTUPINFO *startup, unsigned int count, const HANDLE *handles )
1327 {
1328     static BYTE block[1024];
1329     BYTE *wxflag_ptr;
1330     HANDLE *handle_ptr;
1331     unsigned int i;
1332
1333     startup->lpReserved2 = block;
1334     startup->cbReserved2 = sizeof(unsigned) + (sizeof(char) + sizeof(HANDLE)) * count;
1335     wxflag_ptr = block + sizeof(unsigned);
1336     handle_ptr = (HANDLE *)(wxflag_ptr + count);
1337
1338     *(unsigned*)block = count;
1339     for (i = 0; i < count; i++)
1340     {
1341         wxflag_ptr[i] = 0x81;
1342         handle_ptr[i] = handles[i];
1343     }
1344 }
1345
1346 static const char *read_file( HANDLE file )
1347 {
1348     static char buffer[128];
1349     DWORD ret;
1350     SetFilePointer( file, 0, NULL, FILE_BEGIN );
1351     if (!ReadFile( file, buffer, sizeof(buffer) - 1, &ret, NULL)) ret = 0;
1352     buffer[ret] = 0;
1353     return buffer;
1354 }
1355
1356 static void test_stdout_handle( STARTUPINFO *startup, char *cmdline, HANDLE hstdout, BOOL expect_stdout,
1357                                 const char *descr )
1358 {
1359     const char *data;
1360     HANDLE hErrorFile;
1361     SECURITY_ATTRIBUTES sa;
1362     PROCESS_INFORMATION proc;
1363
1364     /* make file handle inheritable */
1365     sa.nLength = sizeof(sa);
1366     sa.lpSecurityDescriptor = NULL;
1367     sa.bInheritHandle = TRUE;
1368
1369     hErrorFile = CreateFileA( "fdopen.err", GENERIC_READ|GENERIC_WRITE,
1370                               FILE_SHARE_READ | FILE_SHARE_WRITE, &sa, CREATE_ALWAYS, 0, NULL );
1371     startup->dwFlags    = STARTF_USESTDHANDLES;
1372     startup->hStdInput  = GetStdHandle( STD_INPUT_HANDLE );
1373     startup->hStdOutput = hErrorFile;
1374     startup->hStdError  = GetStdHandle( STD_ERROR_HANDLE );
1375
1376     CreateProcessA( NULL, cmdline, NULL, NULL, TRUE,
1377                     CREATE_DEFAULT_ERROR_MODE | NORMAL_PRIORITY_CLASS, NULL, NULL, startup, &proc );
1378     winetest_wait_child_process( proc.hProcess );
1379
1380     data = read_file( hErrorFile );
1381     if (expect_stdout)
1382         ok( strcmp( data, "Success" ), "%s: Error file shouldn't contain data\n", descr );
1383     else
1384         ok( !strcmp( data, "Success" ), "%s: Wrong error data (%s)\n", descr, data );
1385
1386     if (hstdout)
1387     {
1388         data = read_file( hstdout );
1389         if (expect_stdout)
1390             ok( !strcmp( data, "Success" ), "%s: Wrong stdout data (%s)\n", descr, data );
1391         else
1392             ok( strcmp( data, "Success" ), "%s: Stdout file shouldn't contain data\n", descr );
1393     }
1394
1395     CloseHandle( hErrorFile );
1396     DeleteFile( "fdopen.err" );
1397 }
1398
1399 static void test_file_inherit( const char* selfname )
1400 {
1401     int                 fd;
1402     const char*         arg_v[5];
1403     char                buffer[16];
1404     char cmdline[MAX_PATH];
1405     STARTUPINFO startup;
1406     SECURITY_ATTRIBUTES sa;
1407     HANDLE handles[3];
1408
1409     fd = open ("fdopen.tst", O_CREAT | O_RDWR | O_BINARY, _S_IREAD |_S_IWRITE);
1410     ok(fd != -1, "Couldn't create test file\n");
1411     arg_v[0] = selfname;
1412     arg_v[1] = "tests/file.c";
1413     arg_v[2] = "inherit";
1414     arg_v[3] = buffer; sprintf(buffer, "%d", fd);
1415     arg_v[4] = 0;
1416     _spawnvp(_P_WAIT, selfname, arg_v);
1417     ok(tell(fd) == 8, "bad position %u expecting 8\n", tell(fd));
1418     lseek(fd, 0, SEEK_SET);
1419     ok(read(fd, buffer, sizeof (buffer)) == 8 && memcmp(buffer, "Success", 8) == 0, "Couldn't read back the data\n");
1420     close (fd);
1421     ok(unlink("fdopen.tst") == 0, "Couldn't unlink\n");
1422     
1423     fd = open ("fdopen.tst", O_CREAT | O_RDWR | O_BINARY | O_NOINHERIT, _S_IREAD |_S_IWRITE);
1424     ok(fd != -1, "Couldn't create test file\n");
1425     arg_v[0] = selfname;
1426     arg_v[1] = "tests/file.c";
1427     arg_v[2] = "inherit_no";
1428     arg_v[3] = buffer; sprintf(buffer, "%d", fd);
1429     arg_v[4] = 0;
1430     _spawnvp(_P_WAIT, selfname, arg_v);
1431     ok(tell(fd) == 0, "bad position %u expecting 0\n", tell(fd));
1432     ok(read(fd, buffer, sizeof (buffer)) == 0, "Found unexpected data (%s)\n", buffer);
1433     close (fd);
1434     ok(unlink("fdopen.tst") == 0, "Couldn't unlink\n");
1435
1436     /* make file handle inheritable */
1437     sa.nLength = sizeof(sa);
1438     sa.lpSecurityDescriptor = NULL;
1439     sa.bInheritHandle = TRUE;
1440     sprintf(cmdline, "%s file inherit 1", selfname);
1441
1442     /* init an empty Reserved2, which should not be recognized as inherit-block */
1443     ZeroMemory(&startup, sizeof(STARTUPINFO));
1444     startup.cb = sizeof(startup);
1445     create_io_inherit_block( &startup, 0, NULL );
1446     test_stdout_handle( &startup, cmdline, 0, FALSE, "empty block" );
1447
1448     /* test with valid inheritblock */
1449     handles[0] = GetStdHandle( STD_INPUT_HANDLE );
1450     handles[1] = CreateFileA( "fdopen.tst", GENERIC_READ|GENERIC_WRITE,
1451                               FILE_SHARE_READ | FILE_SHARE_WRITE, &sa, CREATE_ALWAYS, 0, NULL );
1452     handles[2] = GetStdHandle( STD_ERROR_HANDLE );
1453     create_io_inherit_block( &startup, 3, handles );
1454     test_stdout_handle( &startup, cmdline, handles[1], TRUE, "valid block" );
1455     CloseHandle( handles[1] );
1456     DeleteFile("fdopen.tst");
1457
1458     /* test inherit block starting with unsigned zero */
1459     handles[1] = CreateFileA( "fdopen.tst", GENERIC_READ|GENERIC_WRITE,
1460                               FILE_SHARE_READ | FILE_SHARE_WRITE, &sa, CREATE_ALWAYS, 0, NULL );
1461     create_io_inherit_block( &startup, 3, handles );
1462     *(unsigned int *)startup.lpReserved2 = 0;
1463     test_stdout_handle( &startup, cmdline, handles[1], FALSE, "zero count block" );
1464     CloseHandle( handles[1] );
1465     DeleteFile("fdopen.tst");
1466
1467     /* test inherit block with smaller size */
1468     handles[1] = CreateFileA( "fdopen.tst", GENERIC_READ|GENERIC_WRITE,
1469                               FILE_SHARE_READ | FILE_SHARE_WRITE, &sa, CREATE_ALWAYS, 0, NULL );
1470     create_io_inherit_block( &startup, 3, handles );
1471     startup.cbReserved2 -= 3;
1472     test_stdout_handle( &startup, cmdline, handles[1], TRUE, "small size block" );
1473     CloseHandle( handles[1] );
1474     DeleteFile("fdopen.tst");
1475
1476     /* test inherit block with even smaller size */
1477     handles[1] = CreateFileA( "fdopen.tst", GENERIC_READ|GENERIC_WRITE,
1478                               FILE_SHARE_READ | FILE_SHARE_WRITE, &sa, CREATE_ALWAYS, 0, NULL );
1479     create_io_inherit_block( &startup, 3, handles );
1480     startup.cbReserved2 = sizeof(unsigned int) + sizeof(HANDLE) + sizeof(char);
1481     test_stdout_handle( &startup, cmdline, handles[1], FALSE, "smaller size block" );
1482     CloseHandle( handles[1] );
1483     DeleteFile("fdopen.tst");
1484
1485     /* test inherit block with larger size */
1486     handles[1] = CreateFileA( "fdopen.tst", GENERIC_READ|GENERIC_WRITE,
1487                               FILE_SHARE_READ | FILE_SHARE_WRITE, &sa, CREATE_ALWAYS, 0, NULL );
1488     create_io_inherit_block( &startup, 3, handles );
1489     startup.cbReserved2 += 7;
1490     test_stdout_handle( &startup, cmdline, handles[1], TRUE, "large size block" );
1491     CloseHandle( handles[1] );
1492     DeleteFile("fdopen.tst");
1493 }
1494
1495 static void test_tmpnam( void )
1496 {
1497   char name[MAX_PATH] = "abc";
1498   char *res;
1499
1500   res = tmpnam(NULL);
1501   ok(res != NULL, "tmpnam returned NULL\n");
1502   ok(res[0] == '\\', "first character is not a backslash\n");
1503   ok(strchr(res+1, '\\') == 0, "file not in the root directory\n");
1504   ok(res[strlen(res)-1] == '.', "first call - last character is not a dot\n");
1505
1506   res = tmpnam(name);
1507   ok(res != NULL, "tmpnam returned NULL\n");
1508   ok(res == name, "supplied buffer was not used\n");
1509   ok(res[0] == '\\', "first character is not a backslash\n");
1510   ok(strchr(res+1, '\\') == 0, "file not in the root directory\n");
1511   ok(res[strlen(res)-1] != '.', "second call - last character is a dot\n");
1512 }
1513
1514 static void test_chsize( void )
1515 {
1516     int fd;
1517     LONG cur, pos, count;
1518     char temptext[] = "012345678";
1519     char *tempfile = _tempnam( ".", "tst" );
1520     
1521     ok( tempfile != NULL, "Couldn't create test file: %s\n", tempfile );
1522
1523     fd = _open( tempfile, _O_CREAT|_O_TRUNC|_O_RDWR, _S_IREAD|_S_IWRITE );
1524     ok( fd > 0, "Couldn't open test file\n" );
1525
1526     count = _write( fd, temptext, sizeof(temptext) );
1527     ok( count > 0, "Couldn't write to test file\n" );
1528
1529     /* get current file pointer */
1530     cur = _lseek( fd, 0, SEEK_CUR );
1531
1532     /* make the file smaller */
1533     ok( _chsize( fd, sizeof(temptext) / 2 ) == 0, "_chsize() failed\n" );
1534
1535     pos = _lseek( fd, 0, SEEK_CUR );
1536     ok( cur == pos, "File pointer changed from: %d to: %d\n", cur, pos );
1537     ok( _filelength( fd ) == sizeof(temptext) / 2, "Wrong file size\n" );
1538
1539     /* enlarge the file */
1540     ok( _chsize( fd, sizeof(temptext) * 2 ) == 0, "_chsize() failed\n" ); 
1541
1542     pos = _lseek( fd, 0, SEEK_CUR );
1543     ok( cur == pos, "File pointer changed from: %d to: %d\n", cur, pos );
1544     ok( _filelength( fd ) == sizeof(temptext) * 2, "Wrong file size\n" );
1545
1546     _close( fd );
1547     _unlink( tempfile );
1548     free( tempfile );
1549 }
1550
1551 static void test_fopen_fclose_fcloseall( void )
1552 {
1553     char fname1[] = "empty1";
1554     char fname2[] = "empty2";
1555     char fname3[] = "empty3";
1556     FILE *stream1, *stream2, *stream3, *stream4;
1557     int ret, numclosed;
1558
1559     /* testing fopen() */
1560     stream1 = fopen(fname1, "w+");
1561     ok(stream1 != NULL, "The file '%s' was not opened\n", fname1);
1562     stream2 = fopen(fname2, "w ");
1563     ok(stream2 != NULL, "The file '%s' was not opened\n", fname2 );
1564     _unlink(fname3);
1565     stream3 = fopen(fname3, "r");
1566     ok(stream3 == NULL, "The file '%s' shouldn't exist before\n", fname3 );
1567     stream3 = fopen(fname3, "w+");
1568     ok(stream3 != NULL, "The file '%s' should be opened now\n", fname3 );
1569     errno = 0xfaceabad;
1570     stream4 = fopen("", "w+");
1571     ok(stream4 == NULL && (errno == EINVAL || errno == ENOENT),
1572        "filename is empty, errno = %d (expected 2 or 22)\n", errno);
1573     errno = 0xfaceabad;
1574     stream4 = fopen(NULL, "w+");
1575     ok(stream4 == NULL && (errno == EINVAL || errno == ENOENT), 
1576        "filename is NULL, errno = %d (expected 2 or 22)\n", errno);
1577
1578     /* testing fclose() */
1579     ret = fclose(stream2);
1580     ok(ret == 0, "The file '%s' was not closed\n", fname2);
1581     ret = fclose(stream3);
1582     ok(ret == 0, "The file '%s' was not closed\n", fname3);
1583     ret = fclose(stream2);
1584     ok(ret == EOF, "Closing file '%s' returned %d\n", fname2, ret);
1585     ret = fclose(stream3);
1586     ok(ret == EOF, "Closing file '%s' returned %d\n", fname3, ret);
1587
1588     /* testing fcloseall() */
1589     numclosed = _fcloseall();
1590     /* fname1 should be closed here */
1591     ok(numclosed == 1, "Number of files closed by fcloseall(): %u\n", numclosed);
1592     numclosed = _fcloseall();
1593     ok(numclosed == 0, "Number of files closed by fcloseall(): %u\n", numclosed);
1594
1595     ok(_unlink(fname1) == 0, "Couldn't unlink file named '%s'\n", fname1);
1596     ok(_unlink(fname2) == 0, "Couldn't unlink file named '%s'\n", fname2);
1597     ok(_unlink(fname3) == 0, "Couldn't unlink file named '%s'\n", fname3);
1598 }
1599
1600 static void test_fopen_s( void )
1601 {
1602     const char name[] = "empty1";
1603     char buff[16];
1604     unsigned char *ubuff = (unsigned char*)buff;
1605     FILE *file;
1606     int ret;
1607     int len;
1608
1609     if (!p_fopen_s)
1610     {
1611         win_skip("Skipping fopen_s test\n");
1612         return;
1613     }
1614     /* testing fopen_s */
1615     ret = p_fopen_s(&file, name, "w");
1616     ok(ret == 0, "fopen_s failed with %d\n", ret);
1617     ok(file != 0, "fopen_s failed to return value\n");
1618     fwrite(name, sizeof(name), 1, file);
1619
1620     ret = fclose(file);
1621     ok(ret != EOF, "File failed to close\n");
1622
1623     file = fopen(name, "r");
1624     ok(file != 0, "fopen failed\n");
1625     len = fread(buff, 1, sizeof(name), file);
1626     ok(len == sizeof(name), "File length is %d\n", len);
1627     buff[sizeof(name)] = '\0';
1628     ok(strcmp(name, buff) == 0, "File content mismatch! Got %s, expected %s\n", buff, name);
1629
1630     ret = fclose(file);
1631     ok(ret != EOF, "File failed to close\n");
1632
1633     ret = p_fopen_s(&file, name, "w,  ccs=UNIcode");
1634     ok(ret == 0, "fopen_s failed with %d\n", ret);
1635     ret = fwrite("a", 1, 2, file);
1636     ok(ret == 2, "fwrite returned %d\n", ret);
1637     fclose(file);
1638
1639     ret = p_fopen_s(&file, name, "r");
1640     ok(ret == 0, "fopen_s failed with %d\n", ret);
1641     len = fread(buff, 1, 2, file);
1642     ok(len == 2, "len = %d\n", len);
1643     ok(ubuff[0]==0xff && ubuff[1]==0xfe, "buff[0]=%02x, buff[1]=%02x\n",
1644             ubuff[0], ubuff[1]);
1645     fclose(file);
1646
1647     ret = p_fopen_s(&file, name, "r,ccs=unicode");
1648     ok(ret == 0, "fopen_s failed with %d\n", ret);
1649     len = fread(buff, 1, 2, file);
1650     ok(len == 2, "len = %d\n", len);
1651     ok(ubuff[0]=='a' && ubuff[1]==0, "buff[0]=%02x, buff[1]=%02x\n",
1652             ubuff[0], ubuff[1]);
1653     fclose(file);
1654
1655     ret = p_fopen_s(&file, name, "r,ccs=utf-16le");
1656     ok(ret == 0, "fopen_s failed with %d\n", ret);
1657     len = fread(buff, 1, 2, file);
1658     ok(len == 2, "len = %d\n", len);
1659     ok(ubuff[0]=='a' && ubuff[1]==0, "buff[0]=%02x, buff[1]=%02x\n",
1660             ubuff[0], ubuff[1]);
1661     fclose(file);
1662
1663     ret = p_fopen_s(&file, name, "r,ccs=utf-8");
1664     ok(ret == 0, "fopen_s failed with %d\n", ret);
1665     len = fread(buff, 1, 2, file);
1666     ok(len == 2, "len = %d\n", len);
1667     ok(ubuff[0]=='a' && ubuff[1]==0, "buff[0]=%02x, buff[1]=%02x\n",
1668             ubuff[0], ubuff[1]);
1669     fclose(file);
1670
1671     ret = p_fopen_s(&file, name, "w,ccs=utf-16le");
1672     ok(ret == 0, "fopen_s failed with %d\n", ret);
1673     fclose(file);
1674
1675     ret = p_fopen_s(&file, name, "r");
1676     ok(ret == 0, "fopen_s failed with %d\n", ret);
1677     len = fread(buff, 1, 3, file);
1678     ok(len == 2, "len = %d\n", len);
1679     ok(ubuff[0]==0xff && ubuff[1]==0xfe, "buff[0]=%02x, buff[1]=%02x\n",
1680             ubuff[0], ubuff[1]);
1681     fclose(file);
1682
1683     ret = p_fopen_s(&file, name, "w,ccs=utf-8");
1684     ok(ret == 0, "fopen_s failed with %d\n", ret);
1685     fclose(file);
1686
1687     ret = p_fopen_s(&file, name, "r");
1688     ok(ret == 0, "fopen_s failed with %d\n", ret);
1689     len = fread(buff, 1, 4, file);
1690     ok(len == 3, "len = %d\n", len);
1691     ok(ubuff[0]==0xef && ubuff[1]==0xbb && ubuff[2]==0xbf,
1692             "buff[0]=%02x, buff[1]=%02x, buff[2]=%02x\n",
1693             ubuff[0], ubuff[1], ubuff[2]);
1694     fclose(file);
1695
1696     ok(_unlink(name) == 0, "Couldn't unlink file named '%s'\n", name);
1697 }
1698
1699 static void test__wfopen_s( void )
1700 {
1701     const char name[] = "empty1";
1702     const WCHAR wname[] = {
1703        'e','m','p','t','y','1',0
1704     };
1705     const WCHAR wmode[] = {
1706        'w',0
1707     };
1708     char buff[16];
1709     FILE *file;
1710     int ret;
1711     int len;
1712
1713     if (!p__wfopen_s)
1714     {
1715         win_skip("Skipping _wfopen_s test\n");
1716         return;
1717     }
1718     /* testing _wfopen_s */
1719     ret = p__wfopen_s(&file, wname, wmode);
1720     ok(ret == 0, "_wfopen_s failed with %d\n", ret);
1721     ok(file != 0, "_wfopen_s failed to return value\n");
1722     fwrite(name, sizeof(name), 1, file);
1723
1724     ret = fclose(file);
1725     ok(ret != EOF, "File failed to close\n");
1726
1727     file = fopen(name, "r");
1728     ok(file != 0, "fopen failed\n");
1729     len = fread(buff, 1, sizeof(name), file);
1730     ok(len == sizeof(name), "File length is %d\n", len);
1731     buff[sizeof(name)] = '\0';
1732     ok(strcmp(name, buff) == 0, "File content mismatch! Got %s, expected %s\n", buff, name);
1733
1734     ret = fclose(file);
1735     ok(ret != EOF, "File failed to close\n");
1736
1737     ok(_unlink(name) == 0, "Couldn't unlink file named '%s'\n", name);
1738 }
1739
1740 static void test_setmode(void)
1741 {
1742     const char name[] = "empty1";
1743     int fd, ret;
1744
1745     if(!p_fopen_s) {
1746         win_skip("unicode file modes are not available, skipping setmode tests\n");
1747         return;
1748     }
1749
1750     fd = _open(name, _O_CREAT|_O_WRONLY, _S_IWRITE);
1751     ok(fd != -1, "failed to open file\n");
1752
1753     errno = 0xdeadbeef;
1754     ret = _setmode(fd, 0xffffffff);
1755     ok(ret == -1, "_setmode returned %x, expected -1\n", ret);
1756     ok(errno == EINVAL, "errno = %d\n", errno);
1757
1758     errno = 0xdeadbeef;
1759     ret = _setmode(fd, 0);
1760     ok(ret == -1, "_setmode returned %x, expected -1\n", ret);
1761     ok(errno == EINVAL, "errno = %d\n", errno);
1762
1763     errno = 0xdeadbeef;
1764     ret = _setmode(fd, _O_BINARY|_O_TEXT);
1765     ok(ret == -1, "_setmode returned %x, expected -1\n", ret);
1766     ok(errno == EINVAL, "errno = %d\n", errno);
1767
1768     errno = 0xdeadbeef;
1769     ret = _setmode(fd, _O_WTEXT|_O_U16TEXT);
1770     ok(ret == -1, "_setmode returned %x, expected -1\n", ret);
1771     ok(errno == EINVAL, "errno = %d\n", errno);
1772
1773     ret = _setmode(fd, _O_BINARY);
1774     ok(ret == _O_TEXT, "_setmode returned %x, expected _O_TEXT\n", ret);
1775
1776     ret = _setmode(fd, _O_WTEXT);
1777     ok(ret == _O_BINARY, "_setmode returned %x, expected _O_BINARY\n", ret);
1778
1779     ret = _setmode(fd, _O_TEXT);
1780     ok(ret == _O_WTEXT, "_setmode returned %x, expected _O_WTEXT\n", ret);
1781
1782     ret = _setmode(fd, _O_U16TEXT);
1783     ok(ret == _O_TEXT, "_setmode returned %x, expected _O_TEXT\n", ret);
1784
1785     ret = _setmode(fd, _O_U8TEXT);
1786     ok(ret == _O_WTEXT, "_setmode returned %x, expected _O_WTEXT\n", ret);
1787
1788     ret = _setmode(fd, _O_TEXT);
1789     ok(ret == _O_WTEXT, "_setmode returned %x, expected _O_WTEXT\n", ret);
1790
1791     _close(fd);
1792     _unlink(name);
1793 }
1794
1795 static void test_get_osfhandle(void)
1796 {
1797     int fd;
1798     char fname[] = "t_get_osfhanle";
1799     DWORD bytes_written;
1800     HANDLE handle;
1801
1802     fd = _sopen(fname, _O_CREAT|_O_RDWR, _SH_DENYRW, _S_IREAD | _S_IWRITE);
1803     handle = (HANDLE)_get_osfhandle(fd);
1804     WriteFile(handle, "bar", 3, &bytes_written, NULL);
1805     _close(fd);
1806     fd = _open(fname, _O_RDONLY, 0);
1807     ok(fd != -1, "Couldn't open '%s' after _get_osfhandle()\n", fname);
1808
1809     _close(fd);
1810     _unlink(fname);
1811 }
1812
1813 static void test_setmaxstdio(void)
1814 {
1815     ok(2048 == _setmaxstdio(2048),"_setmaxstdio returned %d instead of 2048\n",_setmaxstdio(2048));
1816     ok(-1 == _setmaxstdio(2049),"_setmaxstdio returned %d instead of -1\n",_setmaxstdio(2049));
1817 }
1818
1819 static void test_stat(void)
1820 {
1821     int fd;
1822     int pipes[2];
1823     int ret;
1824     struct stat buf;
1825
1826     /* Tests for a file */
1827     fd = open("stat.tst", O_WRONLY | O_CREAT | O_BINARY, _S_IREAD |_S_IWRITE);
1828     if (fd >= 0)
1829     {
1830         ret = fstat(fd, &buf);
1831         ok(!ret, "fstat failed: errno=%d\n", errno);
1832         ok((buf.st_mode & _S_IFMT) == _S_IFREG, "bad format = %06o\n", buf.st_mode);
1833         ok((buf.st_mode & 0777) == 0666, "bad st_mode = %06o\n", buf.st_mode);
1834         ok(buf.st_dev == 0, "st_dev is %d, expected 0\n", buf.st_dev);
1835         ok(buf.st_dev == buf.st_rdev, "st_dev (%d) and st_rdev (%d) differ\n", buf.st_dev, buf.st_rdev);
1836         ok(buf.st_nlink == 1, "st_nlink is %d, expected 1\n", buf.st_nlink);
1837         ok(buf.st_size == 0, "st_size is %d, expected 0\n", buf.st_size);
1838
1839         ret = stat("stat.tst", &buf);
1840         ok(!ret, "stat failed: errno=%d\n", errno);
1841         ok((buf.st_mode & _S_IFMT) == _S_IFREG, "bad format = %06o\n", buf.st_mode);
1842         ok((buf.st_mode & 0777) == 0666, "bad st_mode = %06o\n", buf.st_mode);
1843         ok(buf.st_dev == buf.st_rdev, "st_dev (%d) and st_rdev (%d) differ\n", buf.st_dev, buf.st_rdev);
1844         ok(buf.st_nlink == 1, "st_nlink is %d, expected 1\n", buf.st_nlink);
1845         ok(buf.st_size == 0, "st_size is %d, expected 0\n", buf.st_size);
1846
1847         errno = 0xdeadbeef;
1848         ret = stat("stat.tst\\", &buf);
1849         ok(ret == -1, "stat returned %d\n", ret);
1850         ok(errno == ENOENT, "errno = %d\n", errno);
1851
1852         close(fd);
1853         remove("stat.tst");
1854     }
1855     else
1856         skip("open failed with errno %d\n", errno);
1857
1858     /* Tests for a char device */
1859     if (_dup2(0, 10) == 0)
1860     {
1861         ret = fstat(10, &buf);
1862         ok(!ret, "fstat(stdin) failed: errno=%d\n", errno);
1863         if ((buf.st_mode & _S_IFMT) == _S_IFCHR)
1864         {
1865             ok(buf.st_mode == _S_IFCHR, "bad st_mode=%06o\n", buf.st_mode);
1866             ok(buf.st_dev == 10, "st_dev is %d, expected 10\n", buf.st_dev);
1867             ok(buf.st_rdev == 10, "st_rdev is %d, expected 10\n", buf.st_rdev);
1868             ok(buf.st_nlink == 1, "st_nlink is %d, expected 1\n", buf.st_nlink);
1869         }
1870         else
1871             skip("stdin is not a char device? st_mode=%06o\n", buf.st_mode);
1872         close(10);
1873     }
1874     else
1875         skip("_dup2 failed with errno %d\n", errno);
1876
1877     /* Tests for pipes */
1878     if (_pipe(pipes, 1024, O_BINARY) == 0)
1879     {
1880         ret = fstat(pipes[0], &buf);
1881         ok(!ret, "fstat(pipe) failed: errno=%d\n", errno);
1882         ok(buf.st_mode == _S_IFIFO, "bad st_mode=%06o\n", buf.st_mode);
1883         ok(buf.st_dev == pipes[0], "st_dev is %d, expected %d\n", buf.st_dev, pipes[0]);
1884         ok(buf.st_rdev == pipes[0], "st_rdev is %d, expected %d\n", buf.st_rdev, pipes[0]);
1885         ok(buf.st_nlink == 1, "st_nlink is %d, expected 1\n", buf.st_nlink);
1886         close(pipes[0]);
1887         close(pipes[1]);
1888     }
1889     else
1890         skip("pipe failed with errno %d\n", errno);
1891
1892     /* Tests for directory */
1893     if(mkdir("stat.tst") == 0)
1894     {
1895         ret = stat("stat.tst                         ", &buf);
1896         ok(!ret, "stat(directory) failed: errno=%d\n", errno);
1897         ok((buf.st_mode & _S_IFMT) == _S_IFDIR, "bad format = %06o\n", buf.st_mode);
1898         ok((buf.st_mode & 0777) == 0777, "bad st_mode = %06o\n", buf.st_mode);
1899         ok(buf.st_dev == buf.st_rdev, "st_dev (%d) and st_rdev (%d) differ\n", buf.st_dev, buf.st_rdev);
1900         ok(buf.st_nlink == 1, "st_nlink is %d, expected 1\n", buf.st_nlink);
1901
1902         errno = 0xdeadbeef;
1903         ret = stat("stat.tst\\ ", &buf);
1904         ok(ret == -1, "stat returned %d\n", ret);
1905         ok(errno == ENOENT, "errno = %d\n", errno);
1906         rmdir( "stat.tst" );
1907     }
1908     else
1909         skip("mkdir failed with errno %d\n", errno);
1910 }
1911
1912 static const char* pipe_string="Hello world";
1913
1914 /* How many messages to transfer over the pipe */
1915 #define N_TEST_MESSAGES 3
1916
1917 static void test_pipes_child(int argc, char** args)
1918 {
1919     int fd;
1920     int nwritten;
1921     int i;
1922
1923     if (argc < 5)
1924     {
1925         ok(0, "not enough parameters: %d\n", argc);
1926         return;
1927     }
1928
1929     fd=atoi(args[3]);
1930     i=close(fd);
1931     ok(!i, "unable to close %d: %d\n", fd, errno);
1932
1933     fd=atoi(args[4]);
1934
1935     for (i=0; i<N_TEST_MESSAGES; i++) {
1936        nwritten=write(fd, pipe_string, strlen(pipe_string));
1937        ok(nwritten == strlen(pipe_string), "i %d, expected to write '%s' wrote %d\n", i, pipe_string, nwritten);
1938        /* let other process wake up so they can show off their "keep reading until EOF" behavior */
1939        if (i < N_TEST_MESSAGES-1)
1940            Sleep(100);
1941     }
1942
1943     i=close(fd);
1944     ok(!i, "unable to close %d: %d\n", fd, errno);
1945 }
1946
1947 static void test_pipes(const char* selfname)
1948 {
1949     int pipes[2];
1950     char str_fdr[12], str_fdw[12];
1951     FILE* file;
1952     const char* arg_v[6];
1953     char buf[4096];
1954     char expected[4096];
1955     int r;
1956     int i;
1957
1958     /* Test reading from a pipe with read() */
1959     if (_pipe(pipes, 1024, O_BINARY) < 0)
1960     {
1961         ok(0, "pipe failed with errno %d\n", errno);
1962         return;
1963     }
1964
1965     arg_v[0] = selfname;
1966     arg_v[1] = "tests/file.c";
1967     arg_v[2] = "pipes";
1968     arg_v[3] = str_fdr; sprintf(str_fdr, "%d", pipes[0]);
1969     arg_v[4] = str_fdw; sprintf(str_fdw, "%d", pipes[1]);
1970     arg_v[5] = NULL;
1971     proc_handles[0] = (HANDLE)_spawnvp(_P_NOWAIT, selfname, arg_v);
1972     i=close(pipes[1]);
1973     ok(!i, "unable to close %d: %d\n", pipes[1], errno);
1974
1975     for (i=0; i<N_TEST_MESSAGES; i++) {
1976        r=read(pipes[0], buf, sizeof(buf)-1);
1977        ok(r == strlen(pipe_string), "i %d, got %d\n", i, r);
1978        if (r > 0)
1979            buf[r]='\0';
1980        ok(strcmp(buf, pipe_string) == 0, "expected to read '%s', got '%s'\n", pipe_string, buf);
1981    }
1982
1983     r=read(pipes[0], buf, sizeof(buf)-1);
1984     ok(r == 0, "expected to read 0 bytes, got %d\n", r);
1985     i=close(pipes[0]);
1986     ok(!i, "unable to close %d: %d\n", pipes[0], errno);
1987
1988     /* Test reading from a pipe with fread() */
1989     if (_pipe(pipes, 1024, O_BINARY) < 0)
1990     {
1991         ok(0, "pipe failed with errno %d\n", errno);
1992         return;
1993     }
1994
1995     arg_v[0] = selfname;
1996     arg_v[1] = "tests/file.c";
1997     arg_v[2] = "pipes";
1998     arg_v[3] = str_fdr; sprintf(str_fdr, "%d", pipes[0]);
1999     arg_v[4] = str_fdw; sprintf(str_fdw, "%d", pipes[1]);
2000     arg_v[5] = NULL;
2001     proc_handles[1] = (HANDLE)_spawnvp(_P_NOWAIT, selfname, arg_v);
2002     i=close(pipes[1]);
2003     ok(!i, "unable to close %d: %d\n", pipes[1], errno);
2004     file=fdopen(pipes[0], "r");
2005
2006     /* In blocking mode, fread will keep calling read() until it gets
2007      * enough bytes, or EOF, even on Unix.  (If this were a Unix terminal
2008      * in cooked mode instead of a pipe, it would also stop on EOL.)
2009      */
2010     expected[0] = 0;
2011     for (i=0; i<N_TEST_MESSAGES; i++)
2012        strcat(expected, pipe_string);
2013     r=fread(buf, 1, sizeof(buf)-1, file);
2014     ok(r == strlen(expected), "fread() returned %d: ferror=%d\n", r, ferror(file));
2015     if (r > 0)
2016        buf[r]='\0';
2017     ok(strcmp(buf, expected) == 0, "got '%s' expected '%s'\n", buf, expected);
2018
2019     /* Let child close the file before we read, so we can sense EOF reliably */
2020     Sleep(100);
2021     r=fread(buf, 1, sizeof(buf)-1, file);
2022     ok(r == 0, "fread() returned %d instead of 0\n", r);
2023     ok(ferror(file) == 0, "got ferror() = %d\n", ferror(file));
2024     ok(feof(file), "feof() is false!\n");
2025
2026     i=fclose(file);
2027     ok(!i, "unable to close the pipe: %d\n", errno);
2028
2029     /* test \r handling when it's the last character read */
2030     if (_pipe(pipes, 1024, O_BINARY) < 0)
2031     {
2032         ok(0, "pipe failed with errno %d\n", errno);
2033         return;
2034     }
2035     r = write(pipes[1], "\r\n\rab", 5);
2036     ok(r == 5, "write returned %d, errno = %d\n", r, errno);
2037     setmode(pipes[0], O_TEXT);
2038     r = read(pipes[0], buf, 1);
2039     ok(r == 1, "read returned %d, expected 1\n", r);
2040     ok(buf[0] == '\n', "buf[0] = %x, expected '\\n'\n", buf[0]);
2041     r = read(pipes[0], buf, 1);
2042     ok(r == 1, "read returned %d, expected 1\n", r);
2043     ok(buf[0] == '\r', "buf[0] = %x, expected '\\r'\n", buf[0]);
2044     r = read(pipes[0], buf, 1);
2045     ok(r == 1, "read returned %d, expected 1\n", r);
2046     ok(buf[0] == 'a', "buf[0] = %x, expected 'a'\n", buf[0]);
2047     r = read(pipes[0], buf, 1);
2048     ok(r == 1, "read returned %d, expected 1\n", r);
2049     ok(buf[0] == 'b', "buf[0] = %x, expected 'b'\n", buf[0]);
2050
2051     if (p_fopen_s)
2052     {
2053         /* test utf16 read with insufficient data */
2054         r = write(pipes[1], "a\0b", 3);
2055         ok(r == 3, "write returned %d, errno = %d\n", r, errno);
2056         buf[2] = 'z';
2057         buf[3] = 'z';
2058         setmode(pipes[0], _O_WTEXT);
2059         r = read(pipes[0], buf, 4);
2060         ok(r == 2, "read returned %d, expected 2\n", r);
2061         ok(!memcmp(buf, "a\0bz", 4), "read returned incorrect data\n");
2062         r = write(pipes[1], "\0", 1);
2063         ok(r == 1, "write returned %d, errno = %d\n", r, errno);
2064         buf[0] = 'z';
2065         buf[1] = 'z';
2066         r = read(pipes[0], buf, 2);
2067         ok(r == 0, "read returned %d, expected 0\n", r);
2068         ok(!memcmp(buf, "\0z", 2), "read returned incorrect data\n");
2069     }
2070     else
2071     {
2072         win_skip("unicode mode tests on pipe\n");
2073     }
2074
2075     close(pipes[1]);
2076     close(pipes[0]);
2077 }
2078
2079 static void test_unlink(void)
2080 {
2081     FILE* file;
2082     ok(mkdir("test_unlink") == 0, "unable to create test dir\n");
2083     file = fopen("test_unlink\\empty", "w");
2084     ok(file != NULL, "unable to create test file\n");
2085     if(file)
2086       fclose(file);
2087     ok(_unlink("test_unlink") != 0, "unlinking a non-empty directory must fail\n");
2088     unlink("test_unlink\\empty");
2089     rmdir("test_unlink");
2090 }
2091
2092 static void test_dup2(void)
2093 {
2094     ok(-1 == _dup2(0, -1), "expected _dup2 to fail when second arg is negative\n" );
2095 }
2096
2097 static void test_stdin(void)
2098 {
2099     HANDLE stdinh = GetStdHandle(STD_INPUT_HANDLE);
2100     int stdin_dup, fd;
2101     HANDLE h;
2102     DWORD r;
2103
2104     stdin_dup = _dup(STDIN_FILENO);
2105     ok(stdin_dup != -1, "_dup(STDIN_FILENO) failed\n");
2106
2107     ok(stdinh == (HANDLE)_get_osfhandle(STDIN_FILENO),
2108             "GetStdHandle(STD_INPUT_HANDLE) != _get_osfhandle(STDIN_FILENO)\n");
2109
2110     r = SetStdHandle(STD_INPUT_HANDLE, INVALID_HANDLE_VALUE);
2111     ok(r == TRUE, "SetStdHandle returned %x, expected TRUE\n", r);
2112     h = GetStdHandle(STD_INPUT_HANDLE);
2113     ok(h == INVALID_HANDLE_VALUE, "h = %p\n", h);
2114
2115     close(STDIN_FILENO);
2116     h = GetStdHandle(STD_INPUT_HANDLE);
2117     ok(h == NULL, "h != NULL\n");
2118
2119     fd = open("stdin.tst", O_WRONLY | O_CREAT, _S_IREAD |_S_IWRITE);
2120     ok(fd != -1, "open failed\n");
2121     ok(fd == STDIN_FILENO, "fd = %d, expected STDIN_FILENO\n", fd);
2122     h = GetStdHandle(STD_INPUT_HANDLE);
2123     ok(h != NULL, "h == NULL\n");
2124     close(fd);
2125     unlink("stdin.tst");
2126
2127     r = _dup2(stdin_dup, STDIN_FILENO);
2128     ok(r != -1, "_dup2 failed\n");
2129     h = GetStdHandle(STD_INPUT_HANDLE);
2130     ok(h != NULL, "h == NULL\n");
2131 }
2132
2133 START_TEST(file)
2134 {
2135     int arg_c;
2136     char** arg_v;
2137
2138     init();
2139
2140     arg_c = winetest_get_mainargs( &arg_v );
2141
2142     /* testing low-level I/O */
2143     if (arg_c >= 3)
2144     {
2145         if (strcmp(arg_v[2], "inherit") == 0)
2146             test_file_inherit_child(arg_v[3]);
2147         else if (strcmp(arg_v[2], "inherit_no") == 0)
2148             test_file_inherit_child_no(arg_v[3]);
2149         else if (strcmp(arg_v[2], "pipes") == 0)
2150             test_pipes_child(arg_c, arg_v);
2151         else
2152             ok(0, "invalid argument '%s'\n", arg_v[2]);
2153         return;
2154     }
2155     test_dup2();
2156     test_file_inherit(arg_v[0]);
2157     test_file_write_read();
2158     test_chsize();
2159     test_stat();
2160     test_unlink();
2161
2162     /* testing stream I/O */
2163     test_filbuf();
2164     test_fdopen();
2165     test_fopen_fclose_fcloseall();
2166     test_fopen_s();
2167     test__wfopen_s();
2168     test_setmode();
2169     test_fileops();
2170     test_asciimode();
2171     test_asciimode2();
2172     test_filemodeT();
2173     test_readmode(FALSE); /* binary mode */
2174     test_readmode(TRUE);  /* ascii mode */
2175     test_readboundary();
2176     test_fgetc();
2177     test_fputc();
2178     test_flsbuf();
2179     test_fflush();
2180     test_fgetwc();
2181     /* \x83\xa9 is double byte character, \xe0\x7f is not (undefined). */
2182     test_fgetwc_locale("AB\x83\xa9\xe0\x7f", "Japanese_Japan.932", 932);
2183     /* \x83 is U+0192 */
2184     test_fgetwc_locale("AB\x83\xa9", "English", 1252);
2185     /* \x83 is U+0083 */
2186     test_fgetwc_locale("AB\x83\xa9", "C", 0);
2187     test_fgetwc_unicode();
2188     test_fputwc();
2189     test_ctrlz();
2190     test_file_put_get();
2191     test_tmpnam();
2192     test_get_osfhandle();
2193     test_setmaxstdio();
2194     test_pipes(arg_v[0]);
2195     test_stdin();
2196
2197     /* Wait for the (_P_NOWAIT) spawned processes to finish to make sure the report
2198      * file contains lines in the correct order
2199      */
2200     WaitForMultipleObjects(sizeof(proc_handles)/sizeof(proc_handles[0]), proc_handles, TRUE, 5000);
2201 }