Piotr Caban : msvcrt: Added support for unicode mode in write function.
Alexandre Julliard
julliard at winehq.org
Thu Jan 10 13:36:11 CST 2013
Module: wine
Branch: master
Commit: 94e3647533cf503bc0d716ab9586c0d583c45c9a
URL: http://source.winehq.org/git/wine.git/?a=commit;h=94e3647533cf503bc0d716ab9586c0d583c45c9a
Author: Piotr Caban <piotr at 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;
}
/*********************************************************************
More information about the wine-cvs
mailing list