Piotr Caban : oleaut32: Fixed VarBstrFromDate behavior on dates before year 1600.

Alexandre Julliard julliard at winehq.org
Fri Feb 22 14:14:00 CST 2013


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

Author: Piotr Caban <piotr at codeweavers.com>
Date:   Fri Feb 22 18:46:32 2013 +0100

oleaut32: Fixed VarBstrFromDate behavior on dates before year 1600.

---

 dlls/oleaut32/tests/vartype.c |    2 +-
 dlls/oleaut32/vartype.c       |  120 +++++++++++++++++++++++++++++++++++++++-
 2 files changed, 118 insertions(+), 4 deletions(-)

diff --git a/dlls/oleaut32/tests/vartype.c b/dlls/oleaut32/tests/vartype.c
index e925fa5..4411d7d 100644
--- a/dlls/oleaut32/tests/vartype.c
+++ b/dlls/oleaut32/tests/vartype.c
@@ -4952,7 +4952,7 @@ static void test_VarBstrFromDate(void)
   BSTR_DATE(1461.0, "12/31/1903");
   BSTR_DATE(1461.5, "12/31/1903 12:00:00 PM");
   BSTR_DATE(-49192.24, "4/24/1765 5:45:36 AM");
-  todo_wine { BSTR_DATE(-657434.0, "1/1/100"); }
+  BSTR_DATE(-657434.0, "1/1/100");
   BSTR_DATE(2958465.0, "12/31/9999");
 
 #undef BSTR_DATE
diff --git a/dlls/oleaut32/vartype.c b/dlls/oleaut32/vartype.c
index 8632055..28795a7 100644
--- a/dlls/oleaut32/vartype.c
+++ b/dlls/oleaut32/vartype.c
@@ -6576,6 +6576,120 @@ HRESULT WINAPI VarBstrFromCy(CY cyIn, LCID lcid, ULONG dwFlags, BSTR *pbstrOut)
   return *pbstrOut ? S_OK : E_OUTOFMEMORY;
 }
 
+static inline int output_int_len(int o, int min_len, WCHAR *date, int date_len)
+{
+    int len, tmp;
+
+    if(min_len >= date_len)
+        return -1;
+
+    for(len=0, tmp=o; tmp; tmp/=10) len++;
+    if(!len) len++;
+    if(len >= date_len)
+        return -1;
+
+    for(tmp=min_len-len; tmp>0; tmp--)
+        *date++ = '0';
+    for(tmp=len; tmp>0; tmp--, o/=10)
+        date[tmp-1] = '0' + o%10;
+    return min_len>len ? min_len : len;
+}
+
+/* format date string, similar to GetDateFormatW function but works on bigger range of dates */
+static BOOL get_date_format(LCID lcid, DWORD flags, const SYSTEMTIME *st,
+        const WCHAR *fmt, WCHAR *date, int date_len)
+{
+    static const LCTYPE dayname[] = {
+        LOCALE_SDAYNAME7, LOCALE_SDAYNAME1, LOCALE_SDAYNAME2, LOCALE_SDAYNAME3,
+        LOCALE_SDAYNAME4, LOCALE_SDAYNAME5, LOCALE_SDAYNAME6
+    };
+    static const LCTYPE sdayname[] = {
+        LOCALE_SABBREVDAYNAME7, LOCALE_SABBREVDAYNAME1, LOCALE_SABBREVDAYNAME2,
+        LOCALE_SABBREVDAYNAME3, LOCALE_SABBREVDAYNAME4, LOCALE_SABBREVDAYNAME5,
+        LOCALE_SABBREVDAYNAME6
+    };
+    static const LCTYPE monthname[] = {
+        LOCALE_SMONTHNAME1, LOCALE_SMONTHNAME2, LOCALE_SMONTHNAME3, LOCALE_SMONTHNAME4,
+        LOCALE_SMONTHNAME5, LOCALE_SMONTHNAME6, LOCALE_SMONTHNAME7, LOCALE_SMONTHNAME8,
+        LOCALE_SMONTHNAME9, LOCALE_SMONTHNAME10, LOCALE_SMONTHNAME11, LOCALE_SMONTHNAME12
+    };
+    static const LCTYPE smonthname[] = {
+        LOCALE_SABBREVMONTHNAME1, LOCALE_SABBREVMONTHNAME2, LOCALE_SABBREVMONTHNAME3,
+        LOCALE_SABBREVMONTHNAME4, LOCALE_SABBREVMONTHNAME5, LOCALE_SABBREVMONTHNAME6,
+        LOCALE_SABBREVMONTHNAME7, LOCALE_SABBREVMONTHNAME8, LOCALE_SABBREVMONTHNAME9,
+        LOCALE_SABBREVMONTHNAME10, LOCALE_SABBREVMONTHNAME11, LOCALE_SABBREVMONTHNAME12
+    };
+
+    if(flags & ~(LOCALE_NOUSEROVERRIDE|VAR_DATEVALUEONLY))
+        FIXME("ignoring flags %x\n", flags);
+    flags &= LOCALE_NOUSEROVERRIDE;
+
+    while(*fmt && date_len) {
+        int count = 1;
+
+        switch(*fmt) {
+            case 'd':
+            case 'M':
+            case 'y':
+            case 'g':
+                while(*fmt == *(fmt+count))
+                    count++;
+                fmt += count-1;
+        }
+
+        switch(*fmt) {
+        case 'd':
+            if(count >= 4)
+                count = GetLocaleInfoW(lcid, dayname[st->wDayOfWeek] | flags, date, date_len)-1;
+            else if(count == 3)
+                count = GetLocaleInfoW(lcid, sdayname[st->wDayOfWeek] | flags, date, date_len)-1;
+            else
+                count = output_int_len(st->wDay, count, date, date_len);
+            break;
+        case 'M':
+            if(count >= 4)
+                count = GetLocaleInfoW(lcid, monthname[st->wMonth-1] | flags, date, date_len)-1;
+            else if(count == 3)
+                count = GetLocaleInfoW(lcid, smonthname[st->wMonth-1] | flags, date, date_len)-1;
+            else
+                count = output_int_len(st->wMonth, count, date, date_len);
+            break;
+        case 'y':
+            if(count >= 3)
+                count = output_int_len(st->wYear, 0, date, date_len);
+            else
+                count = output_int_len(st->wYear%100, count, date, date_len);
+            break;
+        case 'g':
+            if(count == 2) {
+                FIXME("Should be using GetCalendarInfo(CAL_SERASTRING), defaulting to 'AD'\n");
+
+                *date++ = 'A';
+                date_len--;
+                if(date_len)
+                    *date = 'D';
+                else
+                    count = -1;
+                break;
+            }
+        /* fall through */
+        default:
+            *date = *fmt;
+        }
+
+        if(count < 0)
+            break;
+        fmt++;
+        date += count;
+        date_len -= count;
+    }
+
+    if(!date_len)
+        return FALSE;
+    *date++ = 0;
+    return TRUE;
+}
+
 /******************************************************************************
  *    VarBstrFromDate    [OLEAUT32.114]
  *
@@ -6596,7 +6710,7 @@ HRESULT WINAPI VarBstrFromDate(DATE dateIn, LCID lcid, ULONG dwFlags, BSTR* pbst
 {
   SYSTEMTIME st;
   DWORD dwFormatFlags = dwFlags & LOCALE_NOUSEROVERRIDE;
-  WCHAR date[128], *time;
+  WCHAR date[128], fmt_buff[80], *time;
 
   TRACE("(%g,0x%08x,0x%08x,%p)\n", dateIn, lcid, dwFlags, pbstrOut);
 
@@ -6626,8 +6740,8 @@ HRESULT WINAPI VarBstrFromDate(DATE dateIn, LCID lcid, ULONG dwFlags, BSTR* pbst
   if (dwFlags & VAR_TIMEVALUEONLY)
     date[0] = '\0';
   else
-    if (!GetDateFormatW(lcid, dwFormatFlags|DATE_SHORTDATE, &st, NULL, date,
-                        sizeof(date)/sizeof(WCHAR)))
+    if (!GetLocaleInfoW(lcid, LOCALE_SSHORTDATE, fmt_buff, sizeof(fmt_buff)/sizeof(WCHAR)) ||
+        !get_date_format(lcid, dwFlags, &st, fmt_buff, date, sizeof(date)/sizeof(WCHAR)))
       return E_INVALIDARG;
 
   if (!(dwFlags & VAR_DATEVALUEONLY))




More information about the wine-cvs mailing list