Module: wine Branch: master Commit: 209b58c64e6181c9bf448cb4f3130d3ba705c5d2 URL: http://source.winehq.org/git/wine.git/?a=commit;h=209b58c64e6181c9bf448cb4f3...
Author: Piotr Caban piotr@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))