Piotr Caban : msvcrt: Added support for unicode text mode in open functions family.

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


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

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

msvcrt: Added support for unicode text mode in open functions family.

---

 dlls/msvcrt/file.c |  104 ++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 101 insertions(+), 3 deletions(-)

diff --git a/dlls/msvcrt/file.c b/dlls/msvcrt/file.c
index a9f0d87..8ee6bed 100644
--- a/dlls/msvcrt/file.c
+++ b/dlls/msvcrt/file.c
@@ -66,6 +66,15 @@ WINE_DEFAULT_DEBUG_CHANNEL(msvcrt);
 #define WX_APPEND         0x20
 #define WX_TEXT           0x80
 
+/* values for exflag - it's used differently in msvcr90.dll*/
+#define EF_UTF8           0x01
+#define EF_UTF16          0x02
+#define EF_CRIT_INIT      0x04
+#define EF_UNK_UNICODE    0x08
+
+static char utf8_bom[3] = { 0xef, 0xbb, 0xbf };
+static char utf16_bom[2] = { 0xff, 0xfe };
+
 /* FIXME: this should be allocated dynamically */
 #define MSVCRT_MAX_FILES 2048
 #define MSVCRT_FD_BLOCK_SIZE 32
@@ -75,7 +84,7 @@ typedef struct {
     HANDLE              handle;
     unsigned char       wxflag;
     char                unk1;
-    BOOL                crit_init;
+    int                 exflag;
     CRITICAL_SECTION    crit;
 } ioinfo;
 
@@ -311,6 +320,7 @@ static int msvcrt_alloc_fd_from(HANDLE hand, int flag, int fd)
 
   fdinfo->handle = hand;
   fdinfo->wxflag = WX_OPEN | (flag & (WX_DONTINHERIT | WX_APPEND | WX_TEXT));
+  fdinfo->exflag = 0;
 
   /* locate next free slot */
   if (fd == MSVCRT_fdstart && fd == MSVCRT_fdend)
@@ -484,6 +494,7 @@ void msvcrt_init_io(void)
                                                          GetCurrentProcess(), &fdinfo->handle,
                                                          0, TRUE, DUPLICATE_SAME_ACCESS))
           fdinfo->wxflag = WX_OPEN | WX_TEXT;
+      fdinfo->exflag = 0;
   }
 
   fdinfo = msvcrt_get_ioinfo(1);
@@ -494,6 +505,7 @@ void msvcrt_init_io(void)
                                                          GetCurrentProcess(), &fdinfo->handle,
                                                          0, TRUE, DUPLICATE_SAME_ACCESS))
           fdinfo->wxflag = WX_OPEN | WX_TEXT;
+      fdinfo->exflag = 0;
   }
 
   fdinfo = msvcrt_get_ioinfo(2);
@@ -504,6 +516,7 @@ void msvcrt_init_io(void)
                                                          GetCurrentProcess(), &fdinfo->handle,
                                                          0, TRUE, DUPLICATE_SAME_ACCESS))
           fdinfo->wxflag = WX_OPEN | WX_TEXT;
+      fdinfo->exflag = 0;
   }
 
   TRACE(":handles (%p)(%p)(%p)\n", msvcrt_get_ioinfo(0)->handle,
@@ -1859,6 +1872,29 @@ int CDECL MSVCRT__sopen( const char *path, int oflags, int shflags, ... )
   return fd;
 }
 
+static int check_bom(HANDLE h, int oflags, BOOL seek)
+{
+    char bom[sizeof(utf8_bom)];
+    DWORD r;
+
+    oflags &= ~(MSVCRT__O_WTEXT|MSVCRT__O_U16TEXT|MSVCRT__O_U8TEXT);
+
+    if (!ReadFile(h, bom, sizeof(utf8_bom), &r, NULL))
+        return oflags;
+
+    if (r==sizeof(utf8_bom) && !memcmp(bom, utf8_bom, sizeof(utf8_bom))) {
+        oflags |= MSVCRT__O_U8TEXT;
+    }else if (r>=sizeof(utf16_bom) && !memcmp(bom, utf16_bom, sizeof(utf16_bom))) {
+        if (seek && r>2)
+            SetFilePointer(h, 2, NULL, FILE_BEGIN);
+        oflags |= MSVCRT__O_U16TEXT;
+    }else if (seek) {
+        SetFilePointer(h, 0, NULL, FILE_BEGIN);
+    }
+
+    return oflags;
+}
+
 /*********************************************************************
  *              _wsopen_s (MSVCRT.@)
  */
@@ -1937,16 +1973,78 @@ int CDECL MSVCRT__wsopen_s( int *fd, const MSVCRT_wchar_t* path, int oflags, int
   sa.lpSecurityDescriptor = NULL;
   sa.bInheritHandle       = !(oflags & MSVCRT__O_NOINHERIT);
 
-  hand = CreateFileW(path, access, sharing, &sa, creation, attrib, 0);
+  if ((oflags&(MSVCRT__O_WTEXT|MSVCRT__O_U16TEXT|MSVCRT__O_U8TEXT))
+          && (creation==OPEN_ALWAYS || creation==OPEN_EXISTING)
+          && !(access&GENERIC_READ))
+  {
+      hand = CreateFileW(path, GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE,
+              &sa, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
+      if (hand != INVALID_HANDLE_VALUE)
+      {
+          oflags = check_bom(hand, oflags, FALSE);
+          CloseHandle(hand);
+      }
+      else
+          oflags &= ~(MSVCRT__O_WTEXT|MSVCRT__O_U16TEXT|MSVCRT__O_U8TEXT);
+  }
 
+  hand = CreateFileW(path, access, sharing, &sa, creation, attrib, 0);
   if (hand == INVALID_HANDLE_VALUE)  {
     WARN(":failed-last error (%d)\n",GetLastError());
     msvcrt_set_errno(GetLastError());
-    msvcrt_set_errno(GetLastError());
     return *MSVCRT__errno();
   }
 
+  if (oflags & (MSVCRT__O_WTEXT|MSVCRT__O_U16TEXT|MSVCRT__O_U8TEXT))
+  {
+      if ((access & GENERIC_WRITE) && (creation==CREATE_NEW
+                  || creation==CREATE_ALWAYS || creation==TRUNCATE_EXISTING
+                  || (creation==OPEN_ALWAYS && GetLastError()==ERROR_ALREADY_EXISTS)))
+      {
+          if (oflags & MSVCRT__O_U8TEXT)
+          {
+              DWORD written = 0, tmp;
+
+              while(written!=sizeof(utf8_bom) && WriteFile(hand, (char*)utf8_bom+written,
+                          sizeof(utf8_bom)-written, &tmp, NULL))
+                  written += tmp;
+              if (written != sizeof(utf8_bom)) {
+                  WARN("error writting BOM\n");
+                  CloseHandle(hand);
+                  msvcrt_set_errno(GetLastError());
+                  return *MSVCRT__errno();
+              }
+          }
+          else
+          {
+              DWORD written = 0, tmp;
+
+              while(written!=sizeof(utf16_bom) && WriteFile(hand, (char*)utf16_bom+written,
+                          sizeof(utf16_bom)-written, &tmp, NULL))
+                  written += tmp;
+              if (written != sizeof(utf16_bom))
+              {
+                  WARN("error writting BOM\n");
+                  CloseHandle(hand);
+                  msvcrt_set_errno(GetLastError());
+                  return *MSVCRT__errno();
+              }
+          }
+      }
+      else if (access & GENERIC_READ)
+          oflags = check_bom(hand, oflags, TRUE);
+  }
+
   *fd = msvcrt_alloc_fd(hand, wxflag);
+  if (*fd == -1)
+      return *MSVCRT__errno();
+
+  if (oflags & MSVCRT__O_WTEXT)
+      msvcrt_get_ioinfo(*fd)->exflag |= EF_UTF16|EF_UNK_UNICODE;
+  else if (oflags & MSVCRT__O_U16TEXT)
+      msvcrt_get_ioinfo(*fd)->exflag |= EF_UTF16;
+  else if (oflags & MSVCRT__O_U8TEXT)
+      msvcrt_get_ioinfo(*fd)->exflag |= EF_UTF8;
 
   TRACE(":fd (%d) handle (%p)\n", *fd, hand);
   return 0;




More information about the wine-cvs mailing list