From c7471d11ef22c3bbc70a2d94657f49eb3a6b7561 Mon Sep 17 00:00:00 2001 From: Ken Belleau Date: Tue, 14 Dec 2004 19:59:43 +0000 Subject: [PATCH] Implemented EnumCalendarInfo(A/W/ExA/ExW). --- dlls/kernel/kernel32.spec | 6 +- dlls/kernel/lcformat.c | 181 +++++++++++++++++++++++++++++++++++++- 2 files changed, 182 insertions(+), 5 deletions(-) diff --git a/dlls/kernel/kernel32.spec b/dlls/kernel/kernel32.spec index 0462b77e701..3640b4496dc 100644 --- a/dlls/kernel/kernel32.spec +++ b/dlls/kernel/kernel32.spec @@ -246,9 +246,9 @@ @ stdcall EndUpdateResourceW(long long) @ stdcall EnterCriticalSection(ptr) ntdll.RtlEnterCriticalSection @ stdcall EnumCalendarInfoA(ptr long long long) -@ stub EnumCalendarInfoW -@ stub EnumCalendarInfoExA -@ stub EnumCalendarInfoExW +@ stdcall EnumCalendarInfoW(ptr long long long) +@ stdcall EnumCalendarInfoExA(ptr long long long) +@ stdcall EnumCalendarInfoExW(ptr long long long) @ stdcall EnumDateFormatsA(ptr long long) @ stdcall EnumDateFormatsW(ptr long long) @ stub EnumDateFormatsExA diff --git a/dlls/kernel/lcformat.c b/dlls/kernel/lcformat.c index 69f3d012052..8376fcd2c51 100644 --- a/dlls/kernel/lcformat.c +++ b/dlls/kernel/lcformat.c @@ -1934,12 +1934,189 @@ BOOL WINAPI EnumTimeFormatsW( TIMEFMT_ENUMPROCW lpTimeFmtEnumProc, LCID Locale, return FALSE; } +/****************************************************************************** + * NLS_EnumCalendarInfoAW + * Enumerates calendar information for a specified locale. + * + * PARAMS + * calinfoproc [I] Pointer to the callback + * locale [I] The locale for which to retrieve calendar information. + * This parameter can be a locale identifier created by the + * MAKELCID macro, or one of the following values: + * LOCALE_SYSTEM_DEFAULT + * Use the default system locale. + * LOCALE_USER_DEFAULT + * Use the default user locale. + * calendar [I] The calendar for which information is requested, or + * ENUM_ALL_CALENDARS. + * caltype [I] The type of calendar information to be returned. Note + * that only one CALTYPE value can be specified per call + * of this function, except where noted. + * unicode [I] Specifies if the callback expects a unicode string. + * ex [I] Specifies if the callback needs the calendar identifier. + * + * RETURNS + * Success: TRUE. + * Failure: FALSE. Use GetLastError() to determine the cause. + * + * NOTES + * When the ANSI version of this function is used with a Unicode-only LCID, + * the call can succeed because the system uses the system code page. + * However, characters that are undefined in the system code page appear + * in the string as a question mark (?). + * + * TODO + * The above note should be respected by GetCalendarInfoA. + */ +BOOL WINAPI NLS_EnumCalendarInfoAW(void *calinfoproc, LCID locale, + CALID calendar, CALTYPE caltype, BOOL unicode, BOOL ex ) +{ + WCHAR *buf, *opt = NULL, *iter = NULL; + BOOL ret = FALSE; + int bufSz = 200; /* the size of the buffer */ + + if (calinfoproc == NULL) + { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + + buf = HeapAlloc(GetProcessHeap(), 0, bufSz); + if (buf == NULL) + { + SetLastError(ERROR_NOT_ENOUGH_MEMORY); + return FALSE; + } + + if (calendar == ENUM_ALL_CALENDARS) + { + int optSz = GetLocaleInfoW(locale, LOCALE_IOPTIONALCALENDAR, NULL, 0); + if (optSz > 1) + { + opt = HeapAlloc(GetProcessHeap(), 0, optSz * sizeof(WCHAR)); + if (opt == NULL) + { + SetLastError(ERROR_NOT_ENOUGH_MEMORY); + goto NLS_EnumCalendarInfoAW_Cleanup; + } + if (GetLocaleInfoW(locale, LOCALE_IOPTIONALCALENDAR, opt, optSz)) + iter = opt; + } + calendar = NLS_GetLocaleNumber(locale, LOCALE_ICALENDARTYPE); + } + + while (TRUE) /* loop through calendars */ + { + do /* loop until there's no error */ + { + if (unicode) + ret = GetCalendarInfoW(locale, calendar, caltype, buf, bufSz / sizeof(WCHAR), NULL); + else ret = GetCalendarInfoA(locale, calendar, caltype, (CHAR*)buf, bufSz / sizeof(CHAR), NULL); + + if (!ret) + { + if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) + { /* so resize it */ + int newSz; + if (unicode) + newSz = GetCalendarInfoW(locale, calendar, caltype, NULL, 0, NULL) * sizeof(WCHAR); + else newSz = GetCalendarInfoA(locale, calendar, caltype, NULL, 0, NULL) * sizeof(CHAR); + if (bufSz >= newSz) + { + ERR("Buffer resizing disorder: was %d, requested %d.\n", bufSz, newSz); + goto NLS_EnumCalendarInfoAW_Cleanup; + } + bufSz = newSz; + WARN("Buffer too small; resizing to %d bytes.\n", bufSz); + buf = HeapReAlloc(GetProcessHeap(), 0, buf, bufSz); + if (buf == NULL) + goto NLS_EnumCalendarInfoAW_Cleanup; + } else goto NLS_EnumCalendarInfoAW_Cleanup; + } + } while (!ret); + + /* Here we are. We pass the buffer to the correct version of + * the callback. Because it's not the same number of params, + * we must check for Ex, but we don't care about Unicode + * because the buffer is already in the correct format. + */ + if (ex) { + ret = ((CALINFO_ENUMPROCEXW)calinfoproc)(buf, calendar); + } else + ret = ((CALINFO_ENUMPROCW)calinfoproc)(buf); + + if (!ret) { /* the callback told to stop */ + ret = TRUE; + break; + } + + if ((iter == NULL) || (*iter == 0)) /* no more calendars */ + break; + + calendar = 0; + while ((*iter >= '0') && (*iter <= '9')) + calendar = calendar * 10 + *iter++ - '0'; + + if (*iter++ != 0) + { + SetLastError(ERROR_BADDB); + ret = FALSE; + break; + } + } + +NLS_EnumCalendarInfoAW_Cleanup: + if (opt != NULL) + HeapFree(GetProcessHeap(), 0, opt); + if (buf != NULL) + HeapFree(GetProcessHeap(), 0, buf); + return ret; +} + /****************************************************************************** * EnumCalendarInfoA [KERNEL32.@] + * + * See EnumCalendarInfoAW. */ BOOL WINAPI EnumCalendarInfoA( CALINFO_ENUMPROCA calinfoproc,LCID locale, CALID calendar,CALTYPE caltype ) { - FIXME("(%p,0x%04lx,0x%08lx,0x%08lx),stub!\n",calinfoproc,locale,calendar,caltype); - return FALSE; + TRACE("(%p,0x%08lx,0x%08lx,0x%08lx)\n", calinfoproc, locale, calendar, caltype); + return NLS_EnumCalendarInfoAW(calinfoproc, locale, calendar, caltype, FALSE, FALSE); +} + +/****************************************************************************** + * EnumCalendarInfoW [KERNEL32.@] + * + * See EnumCalendarInfoAW. + */ +BOOL WINAPI EnumCalendarInfoW( CALINFO_ENUMPROCW calinfoproc,LCID locale, + CALID calendar,CALTYPE caltype ) +{ + TRACE("(%p,0x%08lx,0x%08lx,0x%08lx)\n", calinfoproc, locale, calendar, caltype); + return NLS_EnumCalendarInfoAW(calinfoproc, locale, calendar, caltype, TRUE, FALSE); +} + +/****************************************************************************** + * EnumCalendarInfoExA [KERNEL32.@] + * + * See EnumCalendarInfoAW. + */ +BOOL WINAPI EnumCalendarInfoExA( CALINFO_ENUMPROCEXA calinfoproc,LCID locale, + CALID calendar,CALTYPE caltype ) +{ + TRACE("(%p,0x%08lx,0x%08lx,0x%08lx)\n", calinfoproc, locale, calendar, caltype); + return NLS_EnumCalendarInfoAW(calinfoproc, locale, calendar, caltype, FALSE, TRUE); +} + +/****************************************************************************** + * EnumCalendarInfoExW [KERNEL32.@] + * + * See EnumCalendarInfoAW. + */ +BOOL WINAPI EnumCalendarInfoExW( CALINFO_ENUMPROCEXW calinfoproc,LCID locale, + CALID calendar,CALTYPE caltype ) +{ + TRACE("(%p,0x%08lx,0x%08lx,0x%08lx)\n", calinfoproc, locale, calendar, caltype); + return NLS_EnumCalendarInfoAW(calinfoproc, locale, calendar, caltype, TRUE, TRUE); }