blob: 3bbe7e64c542b0c1b4fb634e0392d4324601ae95 [file]
//-------------------------------------------------------------------------------------------------------
// Copyright (C) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
//-------------------------------------------------------------------------------------------------------
#include "RuntimeBasePch.h"
#if defined(ENABLE_INTL_OBJECT) || defined(ENABLE_ES6_CHAR_CLASSIFIER)
#include "strsafe.h"
#define __WRL_ASSERT__(cond) Assert(cond)
#include <wrl\implements.h>
#ifdef NTBUILD
using namespace Windows::Globalization;
using namespace Windows::Foundation::Collections;
#else
using namespace ABI::Windows::Globalization;
using namespace ABI::Windows::Foundation::Collections;
#endif
#define IfFailThrowHr(op) \
if (FAILED(hr=(op))) \
{ \
JavascriptError::MapAndThrowError(scriptContext, hr);\
} \
#define IfNullReturnError(EXPR, ERROR) do { if (!(EXPR)) { return (ERROR); } } while(FALSE)
#define IfFailedReturn(EXPR) do { hr = (EXPR); if (FAILED(hr)) { return hr; }} while(FALSE)
#define IfFailedSetErrorCodeAndReturn(EXPR, hrVariable) do { hr = (EXPR); if (FAILED(hr)) { hrVariable = hr; return hr; }} while(FALSE)
#define IfFailedGoLabel(expr, label) if (FAILED(expr)) { goto label; }
#define IfFailedGo(expr) IfFailedGoLabel(expr, LReturn)
namespace Js
{
#ifdef ENABLE_INTL_OBJECT
class HSTRINGIterator : public Microsoft::WRL::RuntimeClass<IIterator<HSTRING>>
{
HSTRING *items;
uint32 length;
boolean hasMore;
uint32 currentPosition;
public:
HRESULT RuntimeClassInitialize(HSTRING *items, uint32 length)
{
this->items = items;
this->currentPosition = 0;
this->length = length;
this->hasMore = currentPosition < this->length;
return S_OK;
}
~HSTRINGIterator()
{
}
// IIterator
IFACEMETHODIMP get_Current(_Out_ HSTRING *current)
{
if (current != nullptr)
{
if (hasMore)
{
return WindowsDuplicateString(items[currentPosition], current);
}
else
{
*current = nullptr;
}
}
return E_BOUNDS;
}
IFACEMETHODIMP get_HasCurrent(_Out_ boolean *hasCurrent)
{
if (hasCurrent != nullptr)
{
*hasCurrent = hasMore;
}
return S_OK;
}
IFACEMETHODIMP MoveNext(_Out_opt_ boolean *hasCurrent) sealed
{
this->currentPosition++;
this->hasMore = this->currentPosition < this->length;
if (hasCurrent != nullptr)
{
*hasCurrent = hasMore;
}
return S_OK;
}
IFACEMETHODIMP GetMany(_In_ unsigned capacity,
_Out_writes_to_(capacity,*actual) HSTRING *value,
_Out_ unsigned *actual)
{
uint count = 0;
while (this->hasMore)
{
if (count == capacity)
{
break;
}
if (value != nullptr)
{
get_Current(value + count);
}
count ++;
this->MoveNext(nullptr);
}
if (actual != nullptr)
{
*actual = count;
}
return S_OK;
}
IFACEMETHOD(GetRuntimeClassName)(_Out_ HSTRING* runtimeName) sealed
{
*runtimeName = nullptr;
HRESULT hr = S_OK;
const char16 *name = _u("Js.HSTRINGIterator");
hr = WindowsCreateString(name, static_cast<UINT32>(wcslen(name)), runtimeName);
return hr;
}
IFACEMETHOD(GetTrustLevel)(_Out_ TrustLevel* trustLvl)
{
*trustLvl = BaseTrust;
return S_OK;
}
IFACEMETHOD(GetIids)(_Out_ ULONG *iidCount, _Outptr_result_buffer_(*iidCount) IID **)
{
iidCount;
return E_NOTIMPL;
}
};
class HSTRINGIterable : public Microsoft::WRL::RuntimeClass<IIterable<HSTRING>>
{
HSTRING *items;
uint32 length;
public:
HRESULT RuntimeClassInitialize(HSTRING *string, uint32 length)
{
this->items = HeapNewNoThrowArray(HSTRING, length);
if (this->items == nullptr)
{
return E_OUTOFMEMORY;
}
for(uint32 i = 0; i < length; i++)
{
this->items[i] = string[i];
}
this->length = length;
return S_OK;
}
~HSTRINGIterable()
{
if(this->items != nullptr)
{
HeapDeleteArray(this->length, items);
}
}
IFACEMETHODIMP First(_Outptr_result_maybenull_ IIterator<HSTRING> **first)
{
return Microsoft::WRL::MakeAndInitialize<HSTRINGIterator>(first, this->items, this->length);
}
IFACEMETHOD(GetRuntimeClassName)(_Out_ HSTRING* runtimeName) sealed
{
*runtimeName = nullptr;
HRESULT hr = S_OK;
// Return type that does not exist in metadata
const char16 *name = _u("Js.HSTRINGIterable");
hr = WindowsCreateString(name, static_cast<UINT32>(wcslen(name)), runtimeName);
return hr;
}
IFACEMETHOD(GetTrustLevel)(_Out_ TrustLevel* trustLvl)
{
*trustLvl = BaseTrust;
return S_OK;
}
IFACEMETHOD(GetIids)(_Out_ ULONG *iidCount, _Outptr_result_buffer_(*iidCount) IID **)
{
iidCount;
return E_NOTIMPL;
}
};
#endif
inline DelayLoadWindowsGlobalization* WindowsGlobalizationAdapter::GetWindowsGlobalizationLibrary(_In_ ScriptContext* scriptContext)
{
return this->GetWindowsGlobalizationLibrary(scriptContext->GetThreadContext());
}
inline DelayLoadWindowsGlobalization* WindowsGlobalizationAdapter::GetWindowsGlobalizationLibrary(_In_ ThreadContext* threadContext)
{
return threadContext->GetWindowsGlobalizationLibrary();
}
template<typename T>
HRESULT WindowsGlobalizationAdapter::GetActivationFactory(DelayLoadWindowsGlobalization *delayLoadLibrary, LPCWSTR factoryName, T** instance)
{
*instance = nullptr;
AutoCOMPtr<IActivationFactory> factory;
HSTRING hString;
HSTRING_HEADER hStringHdr;
HRESULT hr;
// factoryName will never get truncated as the name of interfaces in Windows.globalization are not that long.
IfFailedReturn(delayLoadLibrary->WindowsCreateStringReference(factoryName, static_cast<UINT32>(wcslen(factoryName)), &hStringHdr, &hString));
AnalysisAssert(hString);
IfFailedReturn(delayLoadLibrary->DllGetActivationFactory(hString, &factory));
return factory->QueryInterface(__uuidof(T), reinterpret_cast<void**>(instance));
}
#ifdef ENABLE_INTL_OBJECT
HRESULT WindowsGlobalizationAdapter::EnsureCommonObjectsInitialized(DelayLoadWindowsGlobalization *library)
{
HRESULT hr = S_OK;
if (initializedCommonGlobObjects)
{
AssertMsg(hrForCommonGlobObjectsInit == S_OK, "If IntlGlobObjects are initialized, we should be returning S_OK.");
return hrForCommonGlobObjectsInit;
}
else if (hrForCommonGlobObjectsInit != S_OK)
{
return hrForCommonGlobObjectsInit;
}
IfFailedSetErrorCodeAndReturn(GetActivationFactory(library, RuntimeClass_Windows_Globalization_Language, &languageFactory), hrForCommonGlobObjectsInit);
IfFailedSetErrorCodeAndReturn(GetActivationFactory(library, RuntimeClass_Windows_Globalization_Language, &languageStatics), hrForCommonGlobObjectsInit);
IfFailedSetErrorCodeAndReturn(GetActivationFactory(library, RuntimeClass_Windows_Globalization_DateTimeFormatting_DateTimeFormatter, &dateTimeFormatterFactory), hrForCommonGlobObjectsInit);
hrForCommonGlobObjectsInit = S_OK;
initializedCommonGlobObjects = true;
return hr;
}
HRESULT WindowsGlobalizationAdapter::EnsureDateTimeFormatObjectsInitialized(DelayLoadWindowsGlobalization *library)
{
HRESULT hr = S_OK;
if (initializedDateTimeFormatObjects)
{
AssertMsg(hrForDateTimeFormatObjectsInit == S_OK, "If DateTimeFormatObjects are initialized, we should be returning S_OK.");
return hrForDateTimeFormatObjectsInit;
}
else if (hrForDateTimeFormatObjectsInit != S_OK)
{
return hrForDateTimeFormatObjectsInit;
}
IfFailedSetErrorCodeAndReturn(GetActivationFactory(library, RuntimeClass_Windows_Globalization_Calendar, &calendarFactory), hrForDateTimeFormatObjectsInit);
IfFailedSetErrorCodeAndReturn(this->CreateTimeZoneOnCalendar(library, &defaultTimeZoneCalendar), hrForDateTimeFormatObjectsInit);
IfFailedSetErrorCodeAndReturn(this->CreateTimeZoneOnCalendar(library, &timeZoneCalendar), hrForDateTimeFormatObjectsInit);
hrForDateTimeFormatObjectsInit = S_OK;
initializedDateTimeFormatObjects = true;
return hr;
}
HRESULT WindowsGlobalizationAdapter::EnsureNumberFormatObjectsInitialized(DelayLoadWindowsGlobalization *library)
{
HRESULT hr = S_OK;
if (initializedNumberFormatObjects)
{
AssertMsg(hrForNumberFormatObjectsInit == S_OK, "If NumberFormatObjects are initialized, we should be returning S_OK.");
return hrForNumberFormatObjectsInit;
}
else if (hrForNumberFormatObjectsInit != S_OK)
{
return hrForNumberFormatObjectsInit;
}
IfFailedSetErrorCodeAndReturn(GetActivationFactory(library, RuntimeClass_Windows_Globalization_NumberFormatting_CurrencyFormatter, &currencyFormatterFactory), hrForNumberFormatObjectsInit);
IfFailedSetErrorCodeAndReturn(GetActivationFactory(library, RuntimeClass_Windows_Globalization_NumberFormatting_DecimalFormatter, &decimalFormatterFactory), hrForNumberFormatObjectsInit);
IfFailedSetErrorCodeAndReturn(GetActivationFactory(library, RuntimeClass_Windows_Globalization_NumberFormatting_PercentFormatter, &percentFormatterFactory), hrForNumberFormatObjectsInit);
IfFailedSetErrorCodeAndReturn(GetActivationFactory(library, RuntimeClass_Windows_Globalization_NumberFormatting_SignificantDigitsNumberRounder, &significantDigitsRounderActivationFactory), hrForNumberFormatObjectsInit);
IfFailedSetErrorCodeAndReturn(GetActivationFactory(library, RuntimeClass_Windows_Globalization_NumberFormatting_IncrementNumberRounder, &incrementNumberRounderActivationFactory), hrForNumberFormatObjectsInit);
hrForNumberFormatObjectsInit = S_OK;
initializedNumberFormatObjects = true;
return hr;
}
#endif
#if ENABLE_UNICODE_API
HRESULT WindowsGlobalizationAdapter::EnsureDataTextObjectsInitialized(DelayLoadWindowsGlobalization *library)
{
HRESULT hr = S_OK;
if (initializedCharClassifierObjects)
{
AssertMsg(hrForCharClassifierObjectsInit == S_OK, "If DataTextObjects are initialized, we should be returning S_OK.");
return hrForCharClassifierObjectsInit;
}
else if (hrForCharClassifierObjectsInit != S_OK)
{
return hrForCharClassifierObjectsInit;
}
IfFailedSetErrorCodeAndReturn(GetActivationFactory(library, RuntimeClass_Windows_Data_Text_UnicodeCharacters, &unicodeStatics), hrForCharClassifierObjectsInit);
hrForCharClassifierObjectsInit = S_OK;
initializedCharClassifierObjects = true;
return hr;
}
#endif
#ifdef ENABLE_INTL_OBJECT
HRESULT WindowsGlobalizationAdapter::CreateLanguage(_In_ ScriptContext* scriptContext, _In_z_ PCWSTR languageTag, ILanguage** language)
{
HRESULT hr = S_OK;
HSTRING hString;
HSTRING_HEADER hStringHdr;
// OK for languageTag to get truncated as it would pass incomplete languageTag below which
// will be rejected by globalization dll
IfFailedReturn(GetWindowsGlobalizationLibrary(scriptContext)->WindowsCreateStringReference(languageTag, static_cast<UINT32>(wcslen(languageTag)), &hStringHdr, &hString));
AnalysisAssert(hString);
IfFailedReturn(this->languageFactory->CreateLanguage(hString, language));
return hr;
}
boolean WindowsGlobalizationAdapter::IsWellFormedLanguageTag(_In_ ScriptContext* scriptContext, _In_z_ PCWSTR languageTag)
{
boolean retVal;
HRESULT hr;
HSTRING hString = nullptr;
HSTRING_HEADER hStringHdr;
// OK for languageTag to get truncated as it would pass incomplete languageTag below which
// will be rejected by globalization dll
IfFailThrowHr(GetWindowsGlobalizationLibrary(scriptContext)->WindowsCreateStringReference(languageTag, static_cast<UINT32>(wcslen(languageTag)), &hStringHdr, &hString));
if (hString == nullptr)
{
return 0;
}
IfFailThrowHr(this->languageStatics->IsWellFormed(hString, &retVal));
return retVal;
}
HRESULT WindowsGlobalizationAdapter::NormalizeLanguageTag(_In_ ScriptContext* scriptContext, _In_z_ PCWSTR languageTag, HSTRING *result)
{
HRESULT hr;
AutoCOMPtr<ILanguage> language;
IfFailedReturn(CreateLanguage(scriptContext, languageTag, &language));
IfFailedReturn(language->get_LanguageTag(result));
IfNullReturnError(*result, E_FAIL);
return hr;
}
boolean WindowsGlobalizationAdapter::ValidateAndCanonicalizeTimeZone(_In_ ScriptContext* scriptContext, _In_z_ PCWSTR timeZoneId, HSTRING *result)
{
HRESULT hr = S_OK;
HSTRING timeZone;
HSTRING_HEADER timeZoneHeader;
// Construct HSTRING of timeZoneId passed
// OK for timeZoneId to get truncated as it would pass incomplete timeZoneId below which
// will be rejected by globalization dll
IfFailThrowHr(GetWindowsGlobalizationLibrary(scriptContext)->WindowsCreateStringReference(timeZoneId, static_cast<UINT32>(wcslen(timeZoneId)), &timeZoneHeader, &timeZone));
// The warning is timeZone could be '0'. This is valid scenario and in that case, ChangeTimeZone() would
// return error HR in which case we will throw.
#pragma warning(suppress:6387)
// ChangeTimeZone should fail if this is not a valid time zone
hr = timeZoneCalendar->ChangeTimeZone(timeZone);
if (hr != S_OK)
{
return false;
}
// Retrieve canonicalize timeZone name
IfFailThrowHr(timeZoneCalendar->GetTimeZone(result));
if (*result == nullptr)
{
return false;
}
return true;
}
HRESULT WindowsGlobalizationAdapter::GetDefaultTimeZoneId(_In_ ScriptContext* scriptContext, HSTRING *result)
{
HRESULT hr = S_OK;
IfFailThrowHr(defaultTimeZoneCalendar->GetTimeZone(result));
IfNullReturnError(*result, E_FAIL);
return hr;
}
HRESULT WindowsGlobalizationAdapter::CreateTimeZoneOnCalendar(_In_ DelayLoadWindowsGlobalization *library, __out::ITimeZoneOnCalendar** result)
{
AutoCOMPtr<::ICalendar> calendar;
HRESULT hr = S_OK;
// initialize hard-coded default languages
AutoArrayPtr<HSTRING> arr(HeapNewArray(HSTRING, 1), 1);
AutoArrayPtr<HSTRING_HEADER> headers(HeapNewArray(HSTRING_HEADER, 1), 1);
IfFailedReturn(library->WindowsCreateStringReference(_u("en-US"), static_cast<UINT32>(wcslen(_u("en-US"))), (headers), (arr)));
Microsoft::WRL::ComPtr<IIterable<HSTRING>> defaultLanguages;
IfFailedReturn(Microsoft::WRL::MakeAndInitialize<HSTRINGIterable>(&defaultLanguages, arr, 1));
// Create calendar object
IfFailedReturn(this->calendarFactory->CreateCalendarDefaultCalendarAndClock(defaultLanguages.Get(), &calendar));
// Get ITimeZoneOnCalendar part of calendar object
IfFailedReturn(calendar->QueryInterface(__uuidof(::ITimeZoneOnCalendar), reinterpret_cast<void**>(result)));
return hr;
}
#define DetachAndReleaseFactoryObjects(object) \
if (this->object) \
{ \
this->object.Detach()->Release(); \
}
void WindowsGlobalizationAdapter::ResetCommonFactoryObjects()
{
// Reset only if its not initialized completely.
if (!this->initializedCommonGlobObjects)
{
this->hrForCommonGlobObjectsInit = S_OK;
DetachAndReleaseFactoryObjects(languageFactory);
DetachAndReleaseFactoryObjects(languageStatics);
DetachAndReleaseFactoryObjects(dateTimeFormatterFactory);
}
}
void WindowsGlobalizationAdapter::ResetTimeZoneFactoryObjects()
{
DetachAndReleaseFactoryObjects(timeZoneCalendar);
DetachAndReleaseFactoryObjects(defaultTimeZoneCalendar);
}
void WindowsGlobalizationAdapter::ResetDateTimeFormatFactoryObjects()
{
// Reset only if its not initialized completely.
if (!this->initializedDateTimeFormatObjects)
{
this->hrForDateTimeFormatObjectsInit = S_OK;
DetachAndReleaseFactoryObjects(calendarFactory);
DetachAndReleaseFactoryObjects(timeZoneCalendar);
DetachAndReleaseFactoryObjects(defaultTimeZoneCalendar);
}
}
void WindowsGlobalizationAdapter::ResetNumberFormatFactoryObjects()
{
// Reset only if its not initialized completely.
if (!this->initializedNumberFormatObjects)
{
this->hrForNumberFormatObjectsInit = S_OK;
DetachAndReleaseFactoryObjects(currencyFormatterFactory);
DetachAndReleaseFactoryObjects(decimalFormatterFactory);
DetachAndReleaseFactoryObjects(percentFormatterFactory);
DetachAndReleaseFactoryObjects(incrementNumberRounderActivationFactory);
DetachAndReleaseFactoryObjects(significantDigitsRounderActivationFactory);
}
}
#undef DetachAndReleaseFactoryObjects
HRESULT WindowsGlobalizationAdapter::CreateCurrencyFormatterCode(_In_ ScriptContext* scriptContext, _In_z_ PCWSTR currencyCode, NumberFormatting::ICurrencyFormatter** currencyFormatter)
{
HRESULT hr;
HSTRING hString;
HSTRING_HEADER hStringHdr;
// OK for currencyCode to get truncated as it would pass incomplete currencyCode below which
// will be rejected by globalization dll
IfFailedReturn(GetWindowsGlobalizationLibrary(scriptContext)->WindowsCreateStringReference(currencyCode, static_cast<UINT32>(wcslen(currencyCode)), &hStringHdr, &hString));
AnalysisAssert(hString);
IfFailedReturn(this->currencyFormatterFactory->CreateCurrencyFormatterCode(hString, currencyFormatter));
return hr;
}
HRESULT WindowsGlobalizationAdapter::CreateCurrencyFormatter(_In_ ScriptContext* scriptContext, PCWSTR* localeStrings, uint32 numLocaleStrings, _In_z_ PCWSTR currencyCode, NumberFormatting::ICurrencyFormatter** currencyFormatter)
{
HRESULT hr;
HSTRING hString;
HSTRING_HEADER hStringHdr;
AutoArrayPtr<HSTRING> arr(HeapNewArray(HSTRING, numLocaleStrings), numLocaleStrings);
AutoArrayPtr<HSTRING_HEADER> headers(HeapNewArray(HSTRING_HEADER, numLocaleStrings), numLocaleStrings);
for(uint32 i = 0; i< numLocaleStrings; i++)
{
// OK for localeString to get truncated as it would pass incomplete localeString below which
// will be rejected by globalization dll.
IfFailedReturn(GetWindowsGlobalizationLibrary(scriptContext)->WindowsCreateStringReference(localeStrings[i], static_cast<UINT32>(wcslen(localeStrings[i])), (headers + i), (arr + i)));
}
Microsoft::WRL::ComPtr<IIterable<HSTRING>> languages(nullptr);
IfFailedReturn(Microsoft::WRL::MakeAndInitialize<HSTRINGIterable>(&languages, arr, numLocaleStrings));
HSTRING geoString;
HSTRING_HEADER geoStringHeader;
IfFailedReturn(GetWindowsGlobalizationLibrary(scriptContext)->WindowsCreateStringReference(_u("ZZ"), 2, &geoStringHeader, &geoString));
AnalysisAssert(geoString);
IfFailedReturn(GetWindowsGlobalizationLibrary(scriptContext)->WindowsCreateStringReference(currencyCode, static_cast<UINT32>(wcslen(currencyCode)), &hStringHdr, &hString));
AnalysisAssert(hString);
IfFailedReturn(this->currencyFormatterFactory->CreateCurrencyFormatterCodeContext(hString, languages.Get(), geoString, currencyFormatter));
return hr;
}
HRESULT WindowsGlobalizationAdapter::CreateNumberFormatter(_In_ ScriptContext* scriptContext, PCWSTR* localeStrings, uint32 numLocaleStrings, NumberFormatting::INumberFormatter** numberFormatter)
{
HRESULT hr = S_OK;
AutoArrayPtr<HSTRING> arr(HeapNewArray(HSTRING, numLocaleStrings), numLocaleStrings);
AutoArrayPtr<HSTRING_HEADER> headers(HeapNewArray(HSTRING_HEADER, numLocaleStrings), numLocaleStrings);
for(uint32 i = 0; i< numLocaleStrings; i++)
{
IfFailedReturn(GetWindowsGlobalizationLibrary(scriptContext)->WindowsCreateStringReference(localeStrings[i], static_cast<UINT32>(wcslen(localeStrings[i])), (headers + i), (arr + i)));
}
Microsoft::WRL::ComPtr<IIterable<HSTRING>> languages(nullptr);
IfFailedReturn(Microsoft::WRL::MakeAndInitialize<HSTRINGIterable>(&languages, arr, numLocaleStrings));
HSTRING geoString;
HSTRING_HEADER geoStringHeader;
IfFailedReturn(GetWindowsGlobalizationLibrary(scriptContext)->WindowsCreateStringReference(_u("ZZ"), 2, &geoStringHeader, &geoString));
AnalysisAssert(geoString);
IfFailedReturn(this->decimalFormatterFactory->CreateDecimalFormatter(languages.Get(), geoString, numberFormatter));
return hr;
}
HRESULT WindowsGlobalizationAdapter::CreatePercentFormatter(_In_ ScriptContext* scriptContext, PCWSTR* localeStrings, uint32 numLocaleStrings, NumberFormatting::INumberFormatter** numberFormatter)
{
HRESULT hr = S_OK;
AutoArrayPtr<HSTRING> arr(HeapNewArray(HSTRING, numLocaleStrings), numLocaleStrings);
AutoArrayPtr<HSTRING_HEADER> headers(HeapNewArray(HSTRING_HEADER, numLocaleStrings), numLocaleStrings);
for(uint32 i = 0; i< numLocaleStrings; i++)
{
// OK for localeString to get truncated as it would pass incomplete localeString below which
// will be rejected by globalization dll.
IfFailedReturn(GetWindowsGlobalizationLibrary(scriptContext)->WindowsCreateStringReference(localeStrings[i], static_cast<UINT32>(wcslen(localeStrings[i])), (headers + i), (arr + i)));
}
Microsoft::WRL::ComPtr<IIterable<HSTRING>> languages(nullptr);
IfFailedReturn(Microsoft::WRL::MakeAndInitialize<HSTRINGIterable>(&languages, arr, numLocaleStrings));
HSTRING geoString;
HSTRING_HEADER geoStringHeader;
IfFailedReturn(GetWindowsGlobalizationLibrary(scriptContext)->WindowsCreateStringReference(_u("ZZ"), 2, &geoStringHeader, &geoString));
AnalysisAssert(geoString);
IfFailedReturn(this->percentFormatterFactory->CreatePercentFormatter(languages.Get(), geoString, numberFormatter));
return hr;
}
HRESULT WindowsGlobalizationAdapter::CreateDateTimeFormatter(_In_ ScriptContext* scriptContext, _In_z_ PCWSTR formatString, _In_z_ PCWSTR* localeStrings,
uint32 numLocaleStrings, _In_opt_z_ PCWSTR calendar, _In_opt_z_ PCWSTR clock, _Out_ DateTimeFormatting::IDateTimeFormatter** result)
{
HRESULT hr = S_OK;
if(numLocaleStrings == 0) return E_INVALIDARG;
AnalysisAssert((calendar == nullptr && clock == nullptr) || (calendar != nullptr && clock != nullptr));
HSTRING fsHString;
HSTRING_HEADER fsHStringHdr;
// OK for formatString to get truncated as it would pass incomplete formatString below which
// will be rejected by globalization dll.
IfFailedReturn(GetWindowsGlobalizationLibrary(scriptContext)->WindowsCreateStringReference(formatString, static_cast<UINT32>(wcslen(formatString)), &fsHStringHdr, &fsHString));
AnalysisAssert(fsHString);
AutoArrayPtr<HSTRING> arr(HeapNewArray(HSTRING, numLocaleStrings), numLocaleStrings);
AutoArrayPtr<HSTRING_HEADER> headers(HeapNewArray(HSTRING_HEADER, numLocaleStrings), numLocaleStrings);
for(uint32 i = 0; i< numLocaleStrings; i++)
{
// OK for localeString to get truncated as it would pass incomplete localeString below which
// will be rejected by globalization dll.
IfFailedReturn(GetWindowsGlobalizationLibrary(scriptContext)->WindowsCreateStringReference(localeStrings[i], static_cast<UINT32>(wcslen(localeStrings[i])), (headers + i), (arr + i)));
}
Microsoft::WRL::ComPtr<IIterable<HSTRING>> languages(nullptr);
IfFailedReturn(Microsoft::WRL::MakeAndInitialize<HSTRINGIterable>(&languages, arr, numLocaleStrings));
if(clock == nullptr)
{
IfFailedReturn(this->dateTimeFormatterFactory->CreateDateTimeFormatterLanguages(fsHString, languages.Get(), result));
}
else
{
HSTRING geoString;
HSTRING_HEADER geoStringHeader;
HSTRING calString;
HSTRING_HEADER calStringHeader;
HSTRING clockString;
HSTRING_HEADER clockStringHeader;
IfFailedReturn(GetWindowsGlobalizationLibrary(scriptContext)->WindowsCreateStringReference(_u("ZZ"), 2, &geoStringHeader, &geoString));
AnalysisAssert(geoString);
// OK for calendar/clock to get truncated as it would pass incomplete text below which
// will be rejected by globalization dll.
IfFailedReturn(GetWindowsGlobalizationLibrary(scriptContext)->WindowsCreateStringReference(calendar, static_cast<UINT32>(wcslen(calendar)), &calStringHeader, &calString));
AnalysisAssert(calString);
IfFailedReturn(GetWindowsGlobalizationLibrary(scriptContext)->WindowsCreateStringReference(clock, static_cast<UINT32>(wcslen(clock)), &clockStringHeader, &clockString));
AnalysisAssert(clockString);
IfFailedReturn(this->dateTimeFormatterFactory->CreateDateTimeFormatterContext(fsHString, languages.Get(), geoString, calString, clockString, result));
}
return hr;
}
HRESULT WindowsGlobalizationAdapter::CreateIncrementNumberRounder(_In_ ScriptContext* scriptContext, NumberFormatting::INumberRounder** numberRounder)
{
return incrementNumberRounderActivationFactory->ActivateInstance(reinterpret_cast<IInspectable**>(numberRounder));
}
HRESULT WindowsGlobalizationAdapter::CreateSignificantDigitsRounder(_In_ ScriptContext* scriptContext, NumberFormatting::INumberRounder** numberRounder)
{
return significantDigitsRounderActivationFactory->ActivateInstance(reinterpret_cast<IInspectable**>(numberRounder));
}
HRESULT WindowsGlobalizationAdapter::GetResolvedLanguage(_In_ DateTimeFormatting::IDateTimeFormatter* formatter, HSTRING * locale)
{
HRESULT hr = formatter->get_ResolvedLanguage(locale);
return VerifyResult(locale, hr);
}
HRESULT WindowsGlobalizationAdapter::GetResolvedLanguage(_In_ NumberFormatting::INumberFormatterOptions* formatter, HSTRING * locale)
{
HRESULT hr = formatter->get_ResolvedLanguage(locale);
return VerifyResult(locale, hr);
}
HRESULT WindowsGlobalizationAdapter::GetNumeralSystem(_In_ NumberFormatting::INumberFormatterOptions* formatter, HSTRING * hNumeralSystem)
{
HRESULT hr = formatter->get_NumeralSystem(hNumeralSystem);
return VerifyResult(hNumeralSystem, hr);
}
HRESULT WindowsGlobalizationAdapter::GetNumeralSystem(_In_ DateTimeFormatting::IDateTimeFormatter* formatter, HSTRING * hNumeralSystem)
{
HRESULT hr = formatter->get_NumeralSystem(hNumeralSystem);
return VerifyResult(hNumeralSystem, hr);
}
HRESULT WindowsGlobalizationAdapter::GetCalendar(_In_ DateTimeFormatting::IDateTimeFormatter* formatter, HSTRING * hCalendar)
{
HRESULT hr = formatter->get_Calendar(hCalendar);
return VerifyResult(hCalendar, hr);
}
HRESULT WindowsGlobalizationAdapter::GetClock(_In_ DateTimeFormatting::IDateTimeFormatter* formatter, HSTRING * hClock)
{
HRESULT hr = formatter->get_Clock(hClock);
return VerifyResult(hClock, hr);
}
HRESULT WindowsGlobalizationAdapter::GetItemAt(_In_ IVectorView<HSTRING>* vector, _In_ uint32 index, HSTRING * item)
{
HRESULT hr = vector->GetAt(index, item);
return VerifyResult(item, hr);
}
/* static */
HRESULT WindowsGlobalizationAdapter::VerifyResult(HSTRING * result, HRESULT errCode)
{
HRESULT hr = S_OK;
IfFailedReturn(errCode);
IfNullReturnError(*result, E_FAIL);
return hr;
}
#endif
}
#endif