Module: wine Branch: master Commit: 94e3647533cf503bc0d716ab9586c0d583c45c9a URL: http://source.winehq.org/git/wine.git/?a=commit;h=94e3647533cf503bc0d716ab95...
Author: Piotr Caban piotr@codeweavers.com Date: Thu Jan 10 11:43:11 2013 +0100
msvcrt: Added support for unicode mode in write function.
---
dlls/msvcrt/file.c | 227 +++++++++++++++++++++++++++++++++++----------------- 1 files changed, 154 insertions(+), 73 deletions(-)
diff --git a/dlls/msvcrt/file.c b/dlls/msvcrt/file.c index be3c3d3..90330f1 100644 --- a/dlls/msvcrt/file.c +++ b/dlls/msvcrt/file.c @@ -2586,89 +2586,170 @@ int CDECL _wutime(const MSVCRT_wchar_t* path, struct MSVCRT___utimbuf32 *t) */ int CDECL MSVCRT__write(int fd, const void* buf, unsigned int count) { - DWORD num_written; - HANDLE hand = msvcrt_fdtoh(fd); + DWORD num_written; + ioinfo *info = msvcrt_get_ioinfo(fd); + HANDLE hand = info->handle;
- /* Don't trace small writes, it gets *very* annoying */ + /* Don't trace small writes, it gets *very* annoying */ #if 0 - if (count > 32) - TRACE(":fd (%d) handle (%d) buf (%p) len (%d)\n",fd,hand,buf,count); + if (count > 32) + TRACE(":fd (%d) handle (%d) buf (%p) len (%d)\n",fd,hand,buf,count); #endif - if (hand == INVALID_HANDLE_VALUE) + if (hand == INVALID_HANDLE_VALUE) { - *MSVCRT__errno() = MSVCRT_EBADF; - return -1; + *MSVCRT__errno() = MSVCRT_EBADF; + return -1; + } + + if (((info->exflag&EF_UTF8) || (info->exflag&EF_UTF16)) && count&1) + { + *MSVCRT__errno() = MSVCRT_EINVAL; + return -1; }
- /* If appending, go to EOF */ - if (msvcrt_get_ioinfo(fd)->wxflag & WX_APPEND) - MSVCRT__lseek(fd, 0, FILE_END); + /* If appending, go to EOF */ + if (info->wxflag & WX_APPEND) + MSVCRT__lseek(fd, 0, FILE_END);
- if (!(msvcrt_get_ioinfo(fd)->wxflag & WX_TEXT)) + if (!(info->wxflag & WX_TEXT)) { - if (WriteFile(hand, buf, count, &num_written, NULL) - && (num_written == count)) - return num_written; - TRACE("WriteFile (fd %d, hand %p) failed-last error (%d)\n", fd, - hand, GetLastError()); - *MSVCRT__errno() = MSVCRT_ENOSPC; + if (WriteFile(hand, buf, count, &num_written, NULL) + && (num_written == count)) + return num_written; + TRACE("WriteFile (fd %d, hand %p) failed-last error (%d)\n", fd, + hand, GetLastError()); + *MSVCRT__errno() = MSVCRT_ENOSPC; } - else - { - unsigned int i, j, nr_lf; - char *p = NULL; - const char *q; - const char *s = buf, *buf_start = buf; - /* find number of \n ( without preceding \r ) */ - for ( nr_lf=0,i = 0; i <count; i++) - { - if (s[i]== '\n') - { - nr_lf++; - /*if ((i >1) && (s[i-1] == '\r')) nr_lf--; */ - } - } - if (nr_lf) - { - if ((q = p = MSVCRT_malloc(count + nr_lf))) - { - for (s = buf, i = 0, j = 0; i < count; i++) - { - if (s[i]== '\n') - { - p[j++] = '\r'; - /*if ((i >1) && (s[i-1] == '\r'))j--;*/ - } - p[j++] = s[i]; - } - } - else - { - FIXME("Malloc failed\n"); - nr_lf =0; - q = buf; - } - } - else - q = buf; + else + { + unsigned int i, j, nr_lf, size; + char *p = NULL; + const char *q; + const char *s = buf, *buf_start = buf;
- if ((WriteFile(hand, q, count+nr_lf, &num_written, NULL) == 0 ) || (num_written != count+nr_lf)) - { - TRACE("WriteFile (fd %d, hand %p) failed-last error (%d), num_written %d\n", - fd, hand, GetLastError(), num_written); - *MSVCRT__errno() = MSVCRT_ENOSPC; - if(nr_lf) - MSVCRT_free(p); - return s - buf_start; - } - else - { - if(nr_lf) - MSVCRT_free(p); - return count; - } - } - return -1; + if (!(info->exflag & (EF_UTF8|EF_UTF16))) + { + /* find number of \n */ + for (nr_lf=0, i=0; i<count; i++) + if (s[i] == '\n') + nr_lf++; + if (nr_lf) + { + size = count+nr_lf; + if ((q = p = MSVCRT_malloc(size))) + { + for (s = buf, i = 0, j = 0; i < count; i++) + { + if (s[i] == '\n') + p[j++] = '\r'; + p[j++] = s[i]; + } + } + else + { + FIXME("Malloc failed\n"); + nr_lf = 0; + size = count; + q = buf; + } + } + else + { + size = count; + q = buf; + } + } + else if (info->exflag & EF_UTF16) + { + for (nr_lf=0, i=0; i<count; i+=2) + if (s[i]=='\n' && s[i+1]==0) + nr_lf += 2; + if (nr_lf) + { + size = count+nr_lf; + if ((q = p = MSVCRT_malloc(size))) + { + for (s=buf, i=0, j=0; i<count; i++) + { + if (s[i]=='\n' && s[i+1]==0) + { + p[j++] = '\r'; + p[j++] = 0; + } + p[j++] = s[i++]; + p[j++] = s[i]; + } + } + else + { + FIXME("Malloc failed\n"); + nr_lf = 0; + size = count; + q = buf; + } + } + else + { + size = count; + q = buf; + } + } + else + { + DWORD conv_len; + + for(nr_lf=0, i=0; i<count; i+=2) + if (s[i]=='\n' && s[i+1]==0) + nr_lf++; + + conv_len = WideCharToMultiByte(CP_UTF8, 0, (WCHAR*)buf, count/2, NULL, 0, NULL, NULL); + if(!conv_len) { + msvcrt_set_errno(GetLastError()); + MSVCRT_free(p); + return -1; + } + + size = conv_len+nr_lf; + if((p = MSVCRT_malloc(count+nr_lf*2+size))) + { + for (s=buf, i=0, j=0; i<count; i++) + { + if (s[i]=='\n' && s[i+1]==0) + { + p[j++] = '\r'; + p[j++] = 0; + } + p[j++] = s[i++]; + p[j++] = s[i]; + } + q = p+count+nr_lf*2; + WideCharToMultiByte(CP_UTF8, 0, (WCHAR*)p, count/2+nr_lf, + p+count+nr_lf*2, conv_len+nr_lf, NULL, NULL); + } + else + { + FIXME("Malloc failed\n"); + nr_lf = 0; + size = count; + q = buf; + } + } + + if (!WriteFile(hand, q, size, &num_written, NULL)) + num_written = -1; + if(p) + MSVCRT_free(p); + if (num_written != size) + { + TRACE("WriteFile (fd %d, hand %p) failed-last error (%d), num_written %d\n", + fd, hand, GetLastError(), num_written); + *MSVCRT__errno() = MSVCRT_ENOSPC; + return s - buf_start; + } + return count; + } + + return -1; }
/*********************************************************************