diff --git a/dlls/msvcrt/file.c b/dlls/msvcrt/file.c index fe2d144d92f..465a4177692 100644 --- a/dlls/msvcrt/file.c +++ b/dlls/msvcrt/file.c @@ -4478,26 +4478,39 @@ int CDECL MSVCRT__wrename(const MSVCRT_wchar_t *oldpath,const MSVCRT_wchar_t *ne */ int CDECL MSVCRT_setvbuf(MSVCRT_FILE* file, char *buf, int mode, MSVCRT_size_t size) { - MSVCRT__lock_file(file); - if(file->_bufsiz) { - if(file->_flag & MSVCRT__IOMYBUF) - MSVCRT_free(file->_base); - file->_flag &= ~MSVCRT__IOMYBUF; - file->_base = file->_ptr = NULL; - file->_bufsiz = 0; - file->_cnt = 0; - } - if(mode == MSVCRT__IOFBF) { - file->_flag &= ~MSVCRT__IONBF; - file->_base = file->_ptr = buf; - if(buf) { - file->_bufsiz = size; - } - } else { - file->_flag |= MSVCRT__IONBF; - } - MSVCRT__unlock_file(file); - return 0; + if(!MSVCRT_CHECK_PMT(file != NULL)) return -1; + if(!MSVCRT_CHECK_PMT(mode==MSVCRT__IONBF || mode==MSVCRT__IOFBF || mode==MSVCRT__IOLBF)) return -1; + if(!MSVCRT_CHECK_PMT(mode==MSVCRT__IONBF || (size>=2 && size<=INT_MAX))) return -1; + + MSVCRT__lock_file(file); + + MSVCRT_fflush(file); + if(file->_flag & MSVCRT__IOMYBUF) + MSVCRT_free(file->_base); + file->_flag &= ~(MSVCRT__IONBF | MSVCRT__IOMYBUF | MSVCRT__USERBUF); + file->_cnt = 0; + + if(mode == MSVCRT__IONBF) { + file->_flag |= MSVCRT__IONBF; + file->_base = file->_ptr = (char*)&file->_charbuf; + file->_bufsiz = 2; + }else if(buf) { + file->_base = file->_ptr = buf; + file->_flag |= MSVCRT__USERBUF; + file->_bufsiz = size; + }else { + file->_base = file->_ptr = malloc(size); + if(!file->_base) { + file->_bufsiz = 0; + MSVCRT__unlock_file(file); + return -1; + } + + file->_flag |= MSVCRT__IOMYBUF; + file->_bufsiz = size; + } + MSVCRT__unlock_file(file); + return 0; } /********************************************************************* diff --git a/dlls/msvcrt/msvcrt.h b/dlls/msvcrt/msvcrt.h index 22ba0d40e4e..3349c9f3bfb 100644 --- a/dlls/msvcrt/msvcrt.h +++ b/dlls/msvcrt/msvcrt.h @@ -740,6 +740,7 @@ struct MSVCRT__stat64 { #define MSVCRT__IOERR 0x0020 #define MSVCRT__IOSTRG 0x0040 #define MSVCRT__IORW 0x0080 +#define MSVCRT__USERBUF 0x0100 #define MSVCRT__IOCOMMIT 0x4000 #define MSVCRT__S_IEXEC 0x0040 diff --git a/dlls/msvcrt/tests/file.c b/dlls/msvcrt/tests/file.c index 422e41d1210..2fd46f233c9 100644 --- a/dlls/msvcrt/tests/file.c +++ b/dlls/msvcrt/tests/file.c @@ -144,6 +144,9 @@ static void test_fileops( void ) fd = open ("fdopen.tst", O_RDONLY | O_BINARY); file = fdopen (fd, "rb"); setvbuf(file,NULL,bufmodes[bufmode],2048); + if(bufmodes[bufmode] == _IOFBF) + ok(file->_bufsiz == 2048, "file->_bufsiz = %d\n", file->_bufsiz); + ok(file->_base != NULL, "file->_base = NULL\n"); ok(strlen(outbuffer) == (sizeof(outbuffer)-1),"strlen/sizeof error for bufmode=%x\n", bufmodes[bufmode]); ok(fgets(buffer,sizeof(buffer),file) !=0,"fgets failed unexpected for bufmode=%x\n", bufmodes[bufmode]); ok(fgets(buffer,sizeof(buffer),file) ==0,"fgets didn't signal EOF for bufmode=%x\n", bufmodes[bufmode]); @@ -629,6 +632,7 @@ static void test_flsbuf( void ) ok(tempfh->_cnt == 0, "_cnt on freshly opened file was %d\n", tempfh->_cnt); setbuf(tempfh, NULL); ok(tempfh->_cnt == 0, "_cnt on unbuffered file was %d\n", tempfh->_cnt); + ok(tempfh->_bufsiz == 2, "_bufsiz = %d\n", tempfh->_bufsiz); /* Inlined putchar sets _cnt to -1. Native seems to ignore the value... */ tempfh->_cnt = 1234; ret = _flsbuf('Q',tempfh);