Piotr Caban : msvcrt: Added UTF16 support to read function.

Alexandre Julliard julliard at winehq.org
Thu Jan 10 13:36:12 CST 2013


Module: wine
Branch: master
Commit: ac3cdc7ffa38f2e449f9e00c1e1fa1afde39ba26
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=ac3cdc7ffa38f2e449f9e00c1e1fa1afde39ba26

Author: Piotr Caban <piotr at codeweavers.com>
Date:   Thu Jan 10 11:45:29 2013 +0100

msvcrt: Added UTF16 support to read function.

---

 dlls/msvcrt/file.c |   73 ++++++++++++++++++++++++++++++++++++++++-----------
 1 files changed, 57 insertions(+), 16 deletions(-)

diff --git a/dlls/msvcrt/file.c b/dlls/msvcrt/file.c
index 0818f8e..e3a477f 100644
--- a/dlls/msvcrt/file.c
+++ b/dlls/msvcrt/file.c
@@ -2112,7 +2112,7 @@ int CDECL MSVCRT__rmtmp(void)
  */
 static int read_i(int fd, void *buf, unsigned int count)
 {
-    DWORD num_read;
+    DWORD num_read, utf16;
     char *bufstart = buf;
     HANDLE hand = msvcrt_fdtoh(fd);
     ioinfo *fdinfo = msvcrt_get_ioinfo(fd);
@@ -2128,7 +2128,17 @@ static int read_i(int fd, void *buf, unsigned int count)
     if (count > 4)
         TRACE(":fd (%d) handle (%p) buf (%p) len (%d)\n",fd,hand,buf,count);
     if (hand == INVALID_HANDLE_VALUE)
+    {
+        *MSVCRT__errno() = MSVCRT_EBADF;
+        return -1;
+    }
+
+    utf16 = (fdinfo->exflag & EF_UTF16) != 0;
+    if (((fdinfo->exflag&EF_UTF8) || utf16) && count&1)
+    {
+        *MSVCRT__errno() = MSVCRT_EINVAL;
         return -1;
+    }
 
     if (fdinfo->lookahead[0]!='\n' || ReadFile(hand, bufstart, count, &num_read, NULL))
     {
@@ -2137,10 +2147,24 @@ static int read_i(int fd, void *buf, unsigned int count)
             bufstart[0] = fdinfo->lookahead[0];
             fdinfo->lookahead[0] = '\n';
 
-            if(count>1 && ReadFile(hand, bufstart+1, count-1, &num_read, NULL))
-                num_read++;
+            if (utf16)
+            {
+                bufstart[1] =  fdinfo->lookahead[1];
+                fdinfo->lookahead[1] = '\n';
+            }
+
+            if(count>1+utf16 && ReadFile(hand, bufstart+1+utf16, count-1-utf16, &num_read, NULL))
+                num_read += 1+utf16;
             else
-                num_read = 1;
+                num_read = 1+utf16;
+        }
+
+        if(utf16 && (num_read&1))
+        {
+            /* msvcr90 uses uninitialized value from the buffer in this case */
+            /* msvcrt ignores additional data */
+            ERR("got odd number of bytes in UTF16 mode\n");
+            num_read--;
         }
 
         if (count != 0 && num_read == 0)
@@ -2152,15 +2176,15 @@ static int read_i(int fd, void *buf, unsigned int count)
         {
             DWORD i, j;
 
-            if (bufstart[0] == '\n')
+            if (bufstart[0]=='\n' && (!utf16 || bufstart[1]==0))
                 fdinfo->wxflag |= WX_READNL;
             else
                 fdinfo->wxflag &= ~WX_READNL;
 
-            for (i=0, j=0; i<num_read; i++)
+            for (i=0, j=0; i<num_read; i+=1+utf16)
             {
                 /* in text mode, a ctrl-z signals EOF */
-                if (bufstart[i] == 0x1a)
+                if (bufstart[i]==0x1a && (!utf16 || bufstart[i+1]==0))
                 {
                     fdinfo->wxflag |= WX_ATEOF;
                     TRACE(":^Z EOF %s\n",debugstr_an(buf,num_read));
@@ -2168,31 +2192,48 @@ static int read_i(int fd, void *buf, unsigned int count)
                 }
 
                 /* in text mode, strip \r if followed by \n */
-                if (bufstart[i]=='\r' && i+1==num_read)
+                if (bufstart[i]=='\r' && (!utf16 || bufstart[i+1]==0) && i+1+utf16==num_read)
                 {
-                    char lookahead;
+                    char lookahead[2];
                     DWORD len;
 
-                    if (ReadFile(hand, &lookahead, 1, &len, NULL) && len)
+                    lookahead[1] = '\n';
+                    if (ReadFile(hand, lookahead, 1+utf16, &len, NULL) && len)
                     {
-                        if(lookahead=='\n' && j==0)
+                        if(lookahead[0]=='\n' && (!utf16 || lookahead[1]==0) && j==0)
+                        {
                             bufstart[j++] = '\n';
+                            if(utf16) bufstart[j++] = 0;
+                        }
                         else
                         {
-                            if(lookahead != '\n')
+                            if(lookahead[0]!='\n' || (utf16 && lookahead[1]!=0))
+                            {
                                 bufstart[j++] = '\r';
+                                if(utf16) bufstart[j++] = 0;
+                            }
 
                             if (fdinfo->wxflag & WX_PIPE)
-                                fdinfo->lookahead[0] = lookahead;
+                            {
+                                fdinfo->lookahead[0] = lookahead[0];
+                                fdinfo->lookahead[1] = lookahead[1];
+                            }
                             else
-                                SetFilePointer(fdinfo->handle, -1, NULL, FILE_CURRENT);
+                                SetFilePointer(fdinfo->handle, -1-utf16, NULL, FILE_CURRENT);
                         }
                     }
                     else
+                    {
                         bufstart[j++] = '\r';
+                        if(utf16) bufstart[j++] = 0;
+                    }
+                }
+                else if((bufstart[i]!='\r' || (utf16 && bufstart[i+1]!=0))
+                        || (bufstart[i+1+utf16]!='\n' || (utf16 && bufstart[i+3]!=0)))
+                {
+                    bufstart[j++] = bufstart[i];
+                    if(utf16) bufstart[j++] = bufstart[i+1];
                 }
-                else if(bufstart[i]!='\r' || bufstart[i+1]!='\n')
-		    bufstart[j++] = bufstart[i];
             }
             num_read = j;
         }




More information about the wine-cvs mailing list