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