diff --git a/dlls/kernel32/kernel32.spec b/dlls/kernel32/kernel32.spec index 3f6943a29d5..00703d7014a 100644 --- a/dlls/kernel32/kernel32.spec +++ b/dlls/kernel32/kernel32.spec @@ -394,9 +394,9 @@ @ stdcall EnterCriticalSection(ptr) ntdll.RtlEnterCriticalSection @ stdcall EnumCalendarInfoA(ptr long long long) @ stdcall EnumCalendarInfoExA(ptr long long long) -@ stdcall EnumCalendarInfoExEx(ptr wstr long wstr long long) -@ stdcall EnumCalendarInfoExW(ptr long long long) -@ stdcall EnumCalendarInfoW(ptr long long long) +@ stdcall -import EnumCalendarInfoExEx(ptr wstr long wstr long long) +@ stdcall -import EnumCalendarInfoExW(ptr long long long) +@ stdcall -import EnumCalendarInfoW(ptr long long long) @ stdcall EnumDateFormatsA(ptr long long) @ stdcall EnumDateFormatsExA(ptr long long) @ stdcall -import EnumDateFormatsExEx(ptr wstr long long) diff --git a/dlls/kernel32/lcformat.c b/dlls/kernel32/lcformat.c index 28e305a8ee5..165cb07dd4e 100644 --- a/dlls/kernel32/lcformat.c +++ b/dlls/kernel32/lcformat.c @@ -1767,264 +1767,3 @@ int WINAPI GetCurrencyFormatEx(LPCWSTR localename, DWORD flags, LPCWSTR value, return GetCurrencyFormatW( LocaleNameToLCID(localename, 0), flags, value, format, str, len); } - - -/* FIXME: Everything below here needs to move somewhere else along with the - * other EnumXXX functions, when a method for storing resources for - * alternate calendars is determined. - */ - -enum enum_callback_type { - CALLBACK_ENUMPROC, - CALLBACK_ENUMPROCEX, - CALLBACK_ENUMPROCEXEX -}; - -struct enumcalendar_context { - enum enum_callback_type type; /* callback kind */ - union { - CALINFO_ENUMPROCW callback; /* user callback pointer */ - CALINFO_ENUMPROCEXW callbackex; - CALINFO_ENUMPROCEXEX callbackexex; - } u; - LCID lcid; /* locale of interest */ - CALID calendar; /* specific calendar or ENUM_ALL_CALENDARS */ - CALTYPE caltype; /* calendar information type */ - LPARAM lParam; /* user input parameter passed to callback, for ExEx case only */ - BOOL unicode; /* A vs W callback type, only for regular and Ex callbacks */ -}; - -/****************************************************************************** - * NLS_EnumCalendarInfo - * Enumerates calendar information for a specified locale. - * - * PARAMS - * ctxt [I] enumeration context, see 'struct enumcalendar_context' - * - * 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. - */ -static BOOL NLS_EnumCalendarInfo(const struct enumcalendar_context *ctxt) -{ - WCHAR *buf, *opt = NULL, *iter = NULL; - CALID calendar = ctxt->calendar; - BOOL ret = FALSE; - int bufSz = 200; /* the size of the buffer */ - - if (ctxt->u.callback == 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(ctxt->lcid, LOCALE_IOPTIONALCALENDAR, NULL, 0); - if (optSz > 1) - { - opt = HeapAlloc(GetProcessHeap(), 0, optSz * sizeof(WCHAR)); - if (opt == NULL) - { - SetLastError(ERROR_NOT_ENOUGH_MEMORY); - goto cleanup; - } - if (GetLocaleInfoW(ctxt->lcid, LOCALE_IOPTIONALCALENDAR, opt, optSz)) - iter = opt; - } - calendar = NLS_GetLocaleNumber(ctxt->lcid, LOCALE_ICALENDARTYPE); - } - - while (TRUE) /* loop through calendars */ - { - do /* loop until there's no error */ - { - if (ctxt->caltype & CAL_RETURN_NUMBER) - ret = GetCalendarInfoW(ctxt->lcid, calendar, ctxt->caltype, NULL, bufSz / sizeof(WCHAR), (LPDWORD)buf); - else if (ctxt->unicode) - ret = GetCalendarInfoW(ctxt->lcid, calendar, ctxt->caltype, buf, bufSz / sizeof(WCHAR), NULL); - else ret = GetCalendarInfoA(ctxt->lcid, calendar, ctxt->caltype, (CHAR*)buf, bufSz / sizeof(CHAR), NULL); - - if (!ret) - { - if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) - { /* so resize it */ - int newSz; - if (ctxt->unicode) - newSz = GetCalendarInfoW(ctxt->lcid, calendar, ctxt->caltype, NULL, 0, NULL) * sizeof(WCHAR); - else newSz = GetCalendarInfoA(ctxt->lcid, calendar, ctxt->caltype, NULL, 0, NULL) * sizeof(CHAR); - if (bufSz >= newSz) - { - ERR("Buffer resizing disorder: was %d, requested %d.\n", bufSz, newSz); - goto cleanup; - } - bufSz = newSz; - WARN("Buffer too small; resizing to %d bytes.\n", bufSz); - buf = HeapReAlloc(GetProcessHeap(), 0, buf, bufSz); - if (buf == NULL) - goto cleanup; - } else goto 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. - */ - switch (ctxt->type) - { - case CALLBACK_ENUMPROC: - ret = ctxt->u.callback(buf); - break; - case CALLBACK_ENUMPROCEX: - ret = ctxt->u.callbackex(buf, calendar); - break; - case CALLBACK_ENUMPROCEXEX: - ret = ctxt->u.callbackexex(buf, calendar, NULL, ctxt->lParam); - break; - default: - ; - } - - 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; - } - } - -cleanup: - HeapFree(GetProcessHeap(), 0, opt); - HeapFree(GetProcessHeap(), 0, buf); - return ret; -} - -/****************************************************************************** - * EnumCalendarInfoA [KERNEL32.@] - */ -BOOL WINAPI EnumCalendarInfoA( CALINFO_ENUMPROCA calinfoproc,LCID locale, - CALID calendar,CALTYPE caltype ) -{ - struct enumcalendar_context ctxt; - - TRACE("(%p,0x%08x,0x%08x,0x%08x)\n", calinfoproc, locale, calendar, caltype); - - ctxt.type = CALLBACK_ENUMPROC; - ctxt.u.callback = (CALINFO_ENUMPROCW)calinfoproc; - ctxt.lcid = locale; - ctxt.calendar = calendar; - ctxt.caltype = caltype; - ctxt.lParam = 0; - ctxt.unicode = FALSE; - return NLS_EnumCalendarInfo(&ctxt); -} - -/****************************************************************************** - * EnumCalendarInfoW [KERNEL32.@] - */ -BOOL WINAPI EnumCalendarInfoW( CALINFO_ENUMPROCW calinfoproc,LCID locale, - CALID calendar,CALTYPE caltype ) -{ - struct enumcalendar_context ctxt; - - TRACE("(%p,0x%08x,0x%08x,0x%08x)\n", calinfoproc, locale, calendar, caltype); - - ctxt.type = CALLBACK_ENUMPROC; - ctxt.u.callback = calinfoproc; - ctxt.lcid = locale; - ctxt.calendar = calendar; - ctxt.caltype = caltype; - ctxt.lParam = 0; - ctxt.unicode = TRUE; - return NLS_EnumCalendarInfo(&ctxt); -} - -/****************************************************************************** - * EnumCalendarInfoExA [KERNEL32.@] - */ -BOOL WINAPI EnumCalendarInfoExA( CALINFO_ENUMPROCEXA calinfoproc,LCID locale, - CALID calendar,CALTYPE caltype ) -{ - struct enumcalendar_context ctxt; - - TRACE("(%p,0x%08x,0x%08x,0x%08x)\n", calinfoproc, locale, calendar, caltype); - - ctxt.type = CALLBACK_ENUMPROCEX; - ctxt.u.callbackex = (CALINFO_ENUMPROCEXW)calinfoproc; - ctxt.lcid = locale; - ctxt.calendar = calendar; - ctxt.caltype = caltype; - ctxt.lParam = 0; - ctxt.unicode = FALSE; - return NLS_EnumCalendarInfo(&ctxt); -} - -/****************************************************************************** - * EnumCalendarInfoExW [KERNEL32.@] - */ -BOOL WINAPI EnumCalendarInfoExW( CALINFO_ENUMPROCEXW calinfoproc,LCID locale, - CALID calendar,CALTYPE caltype ) -{ - struct enumcalendar_context ctxt; - - TRACE("(%p,0x%08x,0x%08x,0x%08x)\n", calinfoproc, locale, calendar, caltype); - - ctxt.type = CALLBACK_ENUMPROCEX; - ctxt.u.callbackex = calinfoproc; - ctxt.lcid = locale; - ctxt.calendar = calendar; - ctxt.caltype = caltype; - ctxt.lParam = 0; - ctxt.unicode = TRUE; - return NLS_EnumCalendarInfo(&ctxt); -} - -/****************************************************************************** - * EnumCalendarInfoExEx [KERNEL32.@] - */ -BOOL WINAPI EnumCalendarInfoExEx( CALINFO_ENUMPROCEXEX calinfoproc, LPCWSTR locale, CALID calendar, - LPCWSTR reserved, CALTYPE caltype, LPARAM lParam) -{ - struct enumcalendar_context ctxt; - - TRACE("(%p,%s,0x%08x,%p,0x%08x,0x%ld)\n", calinfoproc, debugstr_w(locale), calendar, reserved, caltype, lParam); - - ctxt.type = CALLBACK_ENUMPROCEXEX; - ctxt.u.callbackexex = calinfoproc; - ctxt.lcid = LocaleNameToLCID(locale, 0); - ctxt.calendar = calendar; - ctxt.caltype = caltype; - ctxt.lParam = lParam; - ctxt.unicode = TRUE; - return NLS_EnumCalendarInfo(&ctxt); -} diff --git a/dlls/kernel32/locale.c b/dlls/kernel32/locale.c index d7f32cbfdac..323110daa6e 100644 --- a/dlls/kernel32/locale.c +++ b/dlls/kernel32/locale.c @@ -59,6 +59,9 @@ WINE_DEFAULT_DEBUG_CHANNEL(nls); #define WC_FLAGSMASK (WC_DISCARDNS|WC_SEPCHARS|WC_DEFAULTCHAR|WC_ERR_INVALID_CHARS|\ WC_COMPOSITECHECK|WC_NO_BEST_FIT_CHARS) +extern BOOL WINAPI Internal_EnumCalendarInfo( CALINFO_ENUMPROCW proc, LCID lcid, CALID id, + CALTYPE type, BOOL unicode, BOOL ex, + BOOL exex, LPARAM lparam ); extern BOOL WINAPI Internal_EnumDateFormats( DATEFMT_ENUMPROCW proc, LCID lcid, DWORD flags, BOOL unicode, BOOL ex, BOOL exex, LPARAM lparam ); extern BOOL WINAPI Internal_EnumLanguageGroupLocales( LANGGROUPLOCALE_ENUMPROCW proc, LGRPID id, @@ -3628,6 +3631,22 @@ BOOL WINAPI EnumLanguageGroupLocalesA( LANGGROUPLOCALE_ENUMPROCA proc, LGRPID id return Internal_EnumLanguageGroupLocales( (LANGGROUPLOCALE_ENUMPROCW)proc, id, flags, param, FALSE ); } +/****************************************************************************** + * EnumCalendarInfoA [KERNEL32.@] + */ +BOOL WINAPI EnumCalendarInfoA( CALINFO_ENUMPROCA proc, LCID lcid, CALID id, CALTYPE type ) +{ + return Internal_EnumCalendarInfo( (CALINFO_ENUMPROCW)proc, lcid, id, type, FALSE, FALSE, FALSE, 0 ); +} + +/****************************************************************************** + * EnumCalendarInfoExA [KERNEL32.@] + */ +BOOL WINAPI EnumCalendarInfoExA( CALINFO_ENUMPROCEXA proc, LCID lcid, CALID id, CALTYPE type ) +{ + return Internal_EnumCalendarInfo( (CALINFO_ENUMPROCW)proc, lcid, id, type, FALSE, TRUE, FALSE, 0 ); +} + /************************************************************************** * EnumDateFormatsExA (KERNEL32.@) * diff --git a/dlls/kernelbase/kernelbase.spec b/dlls/kernelbase/kernelbase.spec index 546a52c7ef6..943978a7d60 100644 --- a/dlls/kernelbase/kernelbase.spec +++ b/dlls/kernelbase/kernelbase.spec @@ -290,9 +290,9 @@ # @ stub EnterCriticalPolicySectionInternal @ stdcall EnterCriticalSection(ptr) ntdll.RtlEnterCriticalSection # @ stub EnterSynchronizationBarrier -@ stdcall EnumCalendarInfoExEx(ptr wstr long wstr long long) kernel32.EnumCalendarInfoExEx -@ stdcall EnumCalendarInfoExW(ptr long long long) kernel32.EnumCalendarInfoExW -@ stdcall EnumCalendarInfoW(ptr long long long) kernel32.EnumCalendarInfoW +@ stdcall EnumCalendarInfoExEx(ptr wstr long wstr long long) +@ stdcall EnumCalendarInfoExW(ptr long long long) +@ stdcall EnumCalendarInfoW(ptr long long long) @ stdcall EnumDateFormatsExEx(ptr wstr long long) @ stdcall EnumDateFormatsExW(ptr long long) @ stdcall EnumDateFormatsW(ptr long long) @@ -824,7 +824,7 @@ @ stdcall -fastcall InterlockedPushListSList(ptr ptr ptr long) ntdll.RtlInterlockedPushListSList @ stdcall InterlockedPushListSListEx(ptr ptr ptr long) ntdll.RtlInterlockedPushListSListEx @ stub InternalLcidToName -@ stub Internal_EnumCalendarInfo +@ stdcall Internal_EnumCalendarInfo(ptr long long long long long long long) @ stdcall Internal_EnumDateFormats(ptr long long long long long long) @ stdcall Internal_EnumLanguageGroupLocales(ptr long long ptr long) @ stdcall Internal_EnumSystemCodePages(ptr long long) diff --git a/dlls/kernelbase/locale.c b/dlls/kernelbase/locale.c index 473e6e2391e..367618c48a4 100644 --- a/dlls/kernelbase/locale.c +++ b/dlls/kernelbase/locale.c @@ -53,6 +53,62 @@ static const WCHAR locales_key[] = static const WCHAR altsort_key[] = {'A','l','t','e','r','n','a','t','e',' ','S','o','r','t','s',0}; +/* Note: the Internal_ functions are not documented. The number of parameters + * should be correct, but their exact meaning may not. + */ + +/****************************************************************************** + * Internal_EnumCalendarInfo (kernelbase.@) + */ +BOOL WINAPI DECLSPEC_HOTPATCH Internal_EnumCalendarInfo( CALINFO_ENUMPROCW proc, LCID lcid, CALID id, + CALTYPE type, BOOL unicode, BOOL ex, + BOOL exex, LPARAM lparam ) +{ + WCHAR buffer[256]; + DWORD optional; + INT ret; + + if (!proc) + { + SetLastError( ERROR_INVALID_PARAMETER ); + return FALSE; + } + + if (id == ENUM_ALL_CALENDARS) + { + if (!GetLocaleInfoW( lcid, LOCALE_ICALENDARTYPE | LOCALE_RETURN_NUMBER, + (WCHAR *)&id, sizeof(id) / sizeof(WCHAR) )) return FALSE; + if (!GetLocaleInfoW( lcid, LOCALE_IOPTIONALCALENDAR | LOCALE_RETURN_NUMBER, + (WCHAR *)&optional, sizeof(optional) / sizeof(WCHAR) )) optional = 0; + } + + for (;;) + { + if (type & CAL_RETURN_NUMBER) + ret = GetCalendarInfoW( lcid, id, type, NULL, 0, (LPDWORD)buffer ); + else if (unicode) + ret = GetCalendarInfoW( lcid, id, type, buffer, ARRAY_SIZE(buffer), NULL ); + else + { + WCHAR bufW[256]; + ret = GetCalendarInfoW( lcid, id, type, bufW, ARRAY_SIZE(bufW), NULL ); + if (ret) WideCharToMultiByte( CP_ACP, 0, bufW, -1, (char *)buffer, sizeof(buffer), NULL, NULL ); + } + + if (ret) + { + if (exex) ret = ((CALINFO_ENUMPROCEXEX)proc)( buffer, id, NULL, lparam ); + else if (ex) ret = ((CALINFO_ENUMPROCEXW)proc)( buffer, id ); + else ret = proc( buffer ); + } + if (!ret) break; + if (!optional) break; + id = optional; + } + return TRUE; +} + + /************************************************************************** * Internal_EnumDateFormats (kernelbase.@) */ @@ -353,6 +409,36 @@ INT WINAPI DECLSPEC_HOTPATCH CompareStringOrdinal( const WCHAR *str1, INT len1, } +/****************************************************************************** + * EnumCalendarInfoW (kernelbase.@) + */ +BOOL WINAPI DECLSPEC_HOTPATCH EnumCalendarInfoW( CALINFO_ENUMPROCW proc, LCID lcid, + CALID id, CALTYPE type ) +{ + return Internal_EnumCalendarInfo( proc, lcid, id, type, TRUE, FALSE, FALSE, 0 ); +} + + +/****************************************************************************** + * EnumCalendarInfoExW (kernelbase.@) + */ +BOOL WINAPI DECLSPEC_HOTPATCH EnumCalendarInfoExW( CALINFO_ENUMPROCEXW proc, LCID lcid, + CALID id, CALTYPE type ) +{ + return Internal_EnumCalendarInfo( (CALINFO_ENUMPROCW)proc, lcid, id, type, TRUE, TRUE, FALSE, 0 ); +} + +/****************************************************************************** + * EnumCalendarInfoExEx (kernelbase.@) + */ +BOOL WINAPI DECLSPEC_HOTPATCH EnumCalendarInfoExEx( CALINFO_ENUMPROCEXEX proc, LPCWSTR locale, CALID id, + LPCWSTR reserved, CALTYPE type, LPARAM lparam ) +{ + LCID lcid = LocaleNameToLCID( locale, 0 ); + return Internal_EnumCalendarInfo( (CALINFO_ENUMPROCW)proc, lcid, id, type, TRUE, TRUE, TRUE, lparam ); +} + + /************************************************************************** * EnumDateFormatsW (kernelbase.@) */