104e0dc4aSTimo Kreuzer /*** 204e0dc4aSTimo Kreuzer *localref.c - Contains the __[add|remove]localeref() functions. 304e0dc4aSTimo Kreuzer * 404e0dc4aSTimo Kreuzer * Copyright (c) Microsoft Corporation. All rights reserved. 504e0dc4aSTimo Kreuzer * 604e0dc4aSTimo Kreuzer *Purpose: 704e0dc4aSTimo Kreuzer * Contains the __[add|remove]localeref() functions. 804e0dc4aSTimo Kreuzer * 904e0dc4aSTimo Kreuzer *******************************************************************************/ 1004e0dc4aSTimo Kreuzer #include <corecrt_internal.h> 1104e0dc4aSTimo Kreuzer #include <locale.h> 1204e0dc4aSTimo Kreuzer 1304e0dc4aSTimo Kreuzer 1404e0dc4aSTimo Kreuzer 1504e0dc4aSTimo Kreuzer /*** 1604e0dc4aSTimo Kreuzer * __acrt_add_locale_ref(__crt_locale_data* ptloci) 1704e0dc4aSTimo Kreuzer * 1804e0dc4aSTimo Kreuzer * Purpose: 1904e0dc4aSTimo Kreuzer * Increment the refrence count for each element in the localeinfo struct. 2004e0dc4aSTimo Kreuzer * 2104e0dc4aSTimo Kreuzer *******************************************************************************/ __acrt_add_locale_ref(__crt_locale_data * ptloci)2204e0dc4aSTimo Kreuzerextern "C" void __cdecl __acrt_add_locale_ref(__crt_locale_data* ptloci) 2304e0dc4aSTimo Kreuzer { 2404e0dc4aSTimo Kreuzer _InterlockedIncrement(&ptloci->refcount); 2504e0dc4aSTimo Kreuzer 2604e0dc4aSTimo Kreuzer if (ptloci->lconv_intl_refcount != nullptr) 2704e0dc4aSTimo Kreuzer { 2804e0dc4aSTimo Kreuzer _InterlockedIncrement(ptloci->lconv_intl_refcount); 2904e0dc4aSTimo Kreuzer } 3004e0dc4aSTimo Kreuzer 3104e0dc4aSTimo Kreuzer if (ptloci->lconv_mon_refcount != nullptr) 3204e0dc4aSTimo Kreuzer { 3304e0dc4aSTimo Kreuzer _InterlockedIncrement(ptloci->lconv_mon_refcount); 3404e0dc4aSTimo Kreuzer } 3504e0dc4aSTimo Kreuzer 3604e0dc4aSTimo Kreuzer if (ptloci->lconv_num_refcount != nullptr) 3704e0dc4aSTimo Kreuzer { 3804e0dc4aSTimo Kreuzer _InterlockedIncrement(ptloci->lconv_num_refcount); 3904e0dc4aSTimo Kreuzer } 4004e0dc4aSTimo Kreuzer 4104e0dc4aSTimo Kreuzer if (ptloci->ctype1_refcount != nullptr) 4204e0dc4aSTimo Kreuzer { 4304e0dc4aSTimo Kreuzer _InterlockedIncrement(ptloci->ctype1_refcount); 4404e0dc4aSTimo Kreuzer } 4504e0dc4aSTimo Kreuzer 4604e0dc4aSTimo Kreuzer for (int category = LC_MIN; category <= LC_MAX; ++category) 4704e0dc4aSTimo Kreuzer { 4804e0dc4aSTimo Kreuzer if (ptloci->lc_category[category].wlocale != __acrt_wide_c_locale_string && 4904e0dc4aSTimo Kreuzer ptloci->lc_category[category].wrefcount != nullptr) 5004e0dc4aSTimo Kreuzer { 5104e0dc4aSTimo Kreuzer _InterlockedIncrement(ptloci->lc_category[category].wrefcount); 5204e0dc4aSTimo Kreuzer } 5304e0dc4aSTimo Kreuzer 5404e0dc4aSTimo Kreuzer if (ptloci->lc_category[category].locale != nullptr && 5504e0dc4aSTimo Kreuzer ptloci->lc_category[category].refcount != nullptr) 5604e0dc4aSTimo Kreuzer { 5704e0dc4aSTimo Kreuzer _InterlockedIncrement(ptloci->lc_category[category].refcount); 5804e0dc4aSTimo Kreuzer } 5904e0dc4aSTimo Kreuzer } 6004e0dc4aSTimo Kreuzer 6104e0dc4aSTimo Kreuzer __acrt_locale_add_lc_time_reference(ptloci->lc_time_curr); 6204e0dc4aSTimo Kreuzer } 6304e0dc4aSTimo Kreuzer 6404e0dc4aSTimo Kreuzer /*** 6504e0dc4aSTimo Kreuzer * __acrt_release_locale_ref(__crt_locale_data* ptloci) 6604e0dc4aSTimo Kreuzer * 6704e0dc4aSTimo Kreuzer * Purpose: 6804e0dc4aSTimo Kreuzer * Decrement the refrence count for each elemnt in the localeinfo struct. 6904e0dc4aSTimo Kreuzer * 7004e0dc4aSTimo Kreuzer ******************************************************************************/ __acrt_release_locale_ref(__crt_locale_data * ptloci)7104e0dc4aSTimo Kreuzerextern "C" void __cdecl __acrt_release_locale_ref(__crt_locale_data* ptloci) 7204e0dc4aSTimo Kreuzer { 7304e0dc4aSTimo Kreuzer if (ptloci == nullptr) 7404e0dc4aSTimo Kreuzer return; 7504e0dc4aSTimo Kreuzer 7604e0dc4aSTimo Kreuzer _InterlockedDecrement(&ptloci->refcount); 7704e0dc4aSTimo Kreuzer 7804e0dc4aSTimo Kreuzer if (ptloci->lconv_intl_refcount != nullptr) 7904e0dc4aSTimo Kreuzer _InterlockedDecrement(ptloci->lconv_intl_refcount); 8004e0dc4aSTimo Kreuzer 8104e0dc4aSTimo Kreuzer if (ptloci->lconv_mon_refcount != nullptr) 8204e0dc4aSTimo Kreuzer _InterlockedDecrement(ptloci->lconv_mon_refcount); 8304e0dc4aSTimo Kreuzer 8404e0dc4aSTimo Kreuzer if (ptloci->lconv_num_refcount != nullptr) 8504e0dc4aSTimo Kreuzer _InterlockedDecrement(ptloci->lconv_num_refcount); 8604e0dc4aSTimo Kreuzer 8704e0dc4aSTimo Kreuzer if (ptloci->ctype1_refcount != nullptr) 8804e0dc4aSTimo Kreuzer _InterlockedDecrement(ptloci->ctype1_refcount); 8904e0dc4aSTimo Kreuzer 9004e0dc4aSTimo Kreuzer for (int category = LC_MIN; category <= LC_MAX; ++category) 9104e0dc4aSTimo Kreuzer { 9204e0dc4aSTimo Kreuzer if (ptloci->lc_category[category].wlocale != __acrt_wide_c_locale_string && 9304e0dc4aSTimo Kreuzer ptloci->lc_category[category].wrefcount != nullptr) 9404e0dc4aSTimo Kreuzer { 9504e0dc4aSTimo Kreuzer _InterlockedDecrement(ptloci->lc_category[category].wrefcount); 9604e0dc4aSTimo Kreuzer } 9704e0dc4aSTimo Kreuzer 9804e0dc4aSTimo Kreuzer if (ptloci->lc_category[category].locale != nullptr && 9904e0dc4aSTimo Kreuzer ptloci->lc_category[category].refcount != nullptr) 10004e0dc4aSTimo Kreuzer { 10104e0dc4aSTimo Kreuzer _InterlockedDecrement(ptloci->lc_category[category].refcount); 10204e0dc4aSTimo Kreuzer } 10304e0dc4aSTimo Kreuzer } 10404e0dc4aSTimo Kreuzer 10504e0dc4aSTimo Kreuzer __acrt_locale_release_lc_time_reference(ptloci->lc_time_curr); 10604e0dc4aSTimo Kreuzer } 10704e0dc4aSTimo Kreuzer 10804e0dc4aSTimo Kreuzer 10904e0dc4aSTimo Kreuzer /*** 11004e0dc4aSTimo Kreuzer *__acrt_free_locale() - free __crt_locale_data 11104e0dc4aSTimo Kreuzer * 11204e0dc4aSTimo Kreuzer *Purpose: 11304e0dc4aSTimo Kreuzer * Free up the per-thread locale info structure specified by the passed 11404e0dc4aSTimo Kreuzer * pointer. 11504e0dc4aSTimo Kreuzer * 11604e0dc4aSTimo Kreuzer *Entry: 11704e0dc4aSTimo Kreuzer * __crt_locale_data* ptloci 11804e0dc4aSTimo Kreuzer * 11904e0dc4aSTimo Kreuzer *Exit: 12004e0dc4aSTimo Kreuzer * 12104e0dc4aSTimo Kreuzer *Exceptions: 12204e0dc4aSTimo Kreuzer * 12304e0dc4aSTimo Kreuzer *******************************************************************************/ 12404e0dc4aSTimo Kreuzer __acrt_free_locale(__crt_locale_data * ptloci)12504e0dc4aSTimo Kreuzerextern "C" void __cdecl __acrt_free_locale(__crt_locale_data* ptloci) 12604e0dc4aSTimo Kreuzer { 12704e0dc4aSTimo Kreuzer /* 12804e0dc4aSTimo Kreuzer * Free up lconv struct 12904e0dc4aSTimo Kreuzer */ 13004e0dc4aSTimo Kreuzer if (ptloci->lconv != nullptr && 13104e0dc4aSTimo Kreuzer ptloci->lconv != &__acrt_lconv_c && 13204e0dc4aSTimo Kreuzer ptloci->lconv_intl_refcount != nullptr && 13304e0dc4aSTimo Kreuzer *ptloci->lconv_intl_refcount == 0) 13404e0dc4aSTimo Kreuzer { 13504e0dc4aSTimo Kreuzer if (ptloci->lconv_mon_refcount != nullptr && *ptloci->lconv_mon_refcount == 0) 13604e0dc4aSTimo Kreuzer { 13704e0dc4aSTimo Kreuzer _free_crt(ptloci->lconv_mon_refcount); 13804e0dc4aSTimo Kreuzer __acrt_locale_free_monetary(ptloci->lconv); 13904e0dc4aSTimo Kreuzer } 14004e0dc4aSTimo Kreuzer 14104e0dc4aSTimo Kreuzer if (ptloci->lconv_num_refcount != nullptr && *ptloci->lconv_num_refcount == 0) 14204e0dc4aSTimo Kreuzer { 14304e0dc4aSTimo Kreuzer _free_crt(ptloci->lconv_num_refcount); 14404e0dc4aSTimo Kreuzer __acrt_locale_free_numeric(ptloci->lconv); 14504e0dc4aSTimo Kreuzer } 14604e0dc4aSTimo Kreuzer 14704e0dc4aSTimo Kreuzer _free_crt(ptloci->lconv_intl_refcount); 14804e0dc4aSTimo Kreuzer _free_crt(ptloci->lconv); 14904e0dc4aSTimo Kreuzer } 15004e0dc4aSTimo Kreuzer 15104e0dc4aSTimo Kreuzer /* 15204e0dc4aSTimo Kreuzer * Free up ctype tables 15304e0dc4aSTimo Kreuzer */ 15404e0dc4aSTimo Kreuzer if (ptloci->ctype1_refcount != nullptr && *ptloci->ctype1_refcount == 0) 15504e0dc4aSTimo Kreuzer { 15604e0dc4aSTimo Kreuzer _free_crt(ptloci->ctype1 - _COFFSET); 15704e0dc4aSTimo Kreuzer _free_crt(const_cast<unsigned char*>(ptloci->pclmap - _COFFSET - 1)); 15804e0dc4aSTimo Kreuzer _free_crt(const_cast<unsigned char*>(ptloci->pcumap - _COFFSET - 1)); 15904e0dc4aSTimo Kreuzer _free_crt(ptloci->ctype1_refcount); 16004e0dc4aSTimo Kreuzer } 16104e0dc4aSTimo Kreuzer 16204e0dc4aSTimo Kreuzer __acrt_locale_free_lc_time_if_unreferenced(ptloci->lc_time_curr); 16304e0dc4aSTimo Kreuzer 16404e0dc4aSTimo Kreuzer for (int category = LC_MIN; category <= LC_MAX; ++category) 16504e0dc4aSTimo Kreuzer { 16604e0dc4aSTimo Kreuzer if (ptloci->lc_category[category].wlocale != __acrt_wide_c_locale_string && 16704e0dc4aSTimo Kreuzer ptloci->lc_category[category].wrefcount != nullptr && 16804e0dc4aSTimo Kreuzer *ptloci->lc_category[category].wrefcount == 0) 16904e0dc4aSTimo Kreuzer { 17004e0dc4aSTimo Kreuzer _free_crt(ptloci->lc_category[category].wrefcount); 17104e0dc4aSTimo Kreuzer _free_crt(ptloci->locale_name[category]); 17204e0dc4aSTimo Kreuzer } 17304e0dc4aSTimo Kreuzer 17404e0dc4aSTimo Kreuzer _ASSERTE((ptloci->lc_category[category].locale != nullptr && ptloci->lc_category[category].refcount != nullptr) || 17504e0dc4aSTimo Kreuzer (ptloci->lc_category[category].locale == nullptr && ptloci->lc_category[category].refcount == nullptr)); 17604e0dc4aSTimo Kreuzer 17704e0dc4aSTimo Kreuzer if (ptloci->lc_category[category].locale != nullptr && 17804e0dc4aSTimo Kreuzer ptloci->lc_category[category].refcount != nullptr && 17904e0dc4aSTimo Kreuzer *ptloci->lc_category[category].refcount == 0) 18004e0dc4aSTimo Kreuzer { 18104e0dc4aSTimo Kreuzer _free_crt(ptloci->lc_category[category].refcount); 18204e0dc4aSTimo Kreuzer } 18304e0dc4aSTimo Kreuzer } 18404e0dc4aSTimo Kreuzer 18504e0dc4aSTimo Kreuzer /* 18604e0dc4aSTimo Kreuzer * Free up the __crt_locale_data struct 18704e0dc4aSTimo Kreuzer */ 18804e0dc4aSTimo Kreuzer _free_crt(ptloci); 18904e0dc4aSTimo Kreuzer } 19004e0dc4aSTimo Kreuzer 19104e0dc4aSTimo Kreuzer 19204e0dc4aSTimo Kreuzer /*** 19304e0dc4aSTimo Kreuzer * 19404e0dc4aSTimo Kreuzer * _updatelocinfoEx_nolock(__crt_locale_data* *pptlocid, __crt_locale_data* ptlocis) 19504e0dc4aSTimo Kreuzer * 19604e0dc4aSTimo Kreuzer * Purpose: 19704e0dc4aSTimo Kreuzer * Update *pptlocid to ptlocis. This might include freeing contents of *pptlocid. 19804e0dc4aSTimo Kreuzer * 19904e0dc4aSTimo Kreuzer ******************************************************************************/ _updatetlocinfoEx_nolock(__crt_locale_data ** pptlocid,__crt_locale_data * ptlocis)20004e0dc4aSTimo Kreuzerextern "C" __crt_locale_data* __cdecl _updatetlocinfoEx_nolock( 20104e0dc4aSTimo Kreuzer __crt_locale_data** pptlocid, 20204e0dc4aSTimo Kreuzer __crt_locale_data* ptlocis 20304e0dc4aSTimo Kreuzer ) 20404e0dc4aSTimo Kreuzer { 20504e0dc4aSTimo Kreuzer if (ptlocis == nullptr || pptlocid == nullptr) 20604e0dc4aSTimo Kreuzer return nullptr; 20704e0dc4aSTimo Kreuzer 20804e0dc4aSTimo Kreuzer __crt_locale_data* const ptloci = *pptlocid; 20904e0dc4aSTimo Kreuzer if (ptloci == ptlocis) 21004e0dc4aSTimo Kreuzer return ptlocis; 21104e0dc4aSTimo Kreuzer 21204e0dc4aSTimo Kreuzer /* 21304e0dc4aSTimo Kreuzer * Update to the current locale info structure and increment the 21404e0dc4aSTimo Kreuzer * reference counts. 21504e0dc4aSTimo Kreuzer */ 21604e0dc4aSTimo Kreuzer *pptlocid = ptlocis; 21704e0dc4aSTimo Kreuzer __acrt_add_locale_ref(ptlocis); 21804e0dc4aSTimo Kreuzer 21904e0dc4aSTimo Kreuzer /* 22004e0dc4aSTimo Kreuzer * Decrement the reference counts in the old locale info 22104e0dc4aSTimo Kreuzer * structure. 22204e0dc4aSTimo Kreuzer */ 22304e0dc4aSTimo Kreuzer if (ptloci != nullptr) 22404e0dc4aSTimo Kreuzer { 22504e0dc4aSTimo Kreuzer __acrt_release_locale_ref(ptloci); 22604e0dc4aSTimo Kreuzer } 22704e0dc4aSTimo Kreuzer 22804e0dc4aSTimo Kreuzer /* 22904e0dc4aSTimo Kreuzer * Free the old locale info structure, if necessary. Must be done 23004e0dc4aSTimo Kreuzer * after incrementing reference counts in current locale in case 23104e0dc4aSTimo Kreuzer * any refcounts are shared with the old locale. 23204e0dc4aSTimo Kreuzer */ 23304e0dc4aSTimo Kreuzer if (ptloci != nullptr && 23404e0dc4aSTimo Kreuzer ptloci->refcount == 0 && 23504e0dc4aSTimo Kreuzer ptloci != &__acrt_initial_locale_data) 23604e0dc4aSTimo Kreuzer { 23704e0dc4aSTimo Kreuzer __acrt_free_locale(ptloci); 23804e0dc4aSTimo Kreuzer } 23904e0dc4aSTimo Kreuzer 24004e0dc4aSTimo Kreuzer return ptlocis; 24104e0dc4aSTimo Kreuzer } 24204e0dc4aSTimo Kreuzer 24304e0dc4aSTimo Kreuzer 24404e0dc4aSTimo Kreuzer /*** 24504e0dc4aSTimo Kreuzer *__acrt_update_thread_locale_data() - refresh the thread's locale info 24604e0dc4aSTimo Kreuzer * 24704e0dc4aSTimo Kreuzer *Purpose: 24804e0dc4aSTimo Kreuzer * If this thread does not have it's ownlocale which means that either 24904e0dc4aSTimo Kreuzer * ownlocale flag in ptd is not set or ptd->ptloci == nullptr, then Update 25004e0dc4aSTimo Kreuzer * the current thread's reference to the locale information to match the 25104e0dc4aSTimo Kreuzer * current global locale info. Decrement the reference on the old locale 25204e0dc4aSTimo Kreuzer * information struct and if this count is now zero (so that no threads 25304e0dc4aSTimo Kreuzer * are using it), free it. 25404e0dc4aSTimo Kreuzer * 25504e0dc4aSTimo Kreuzer *Entry: 25604e0dc4aSTimo Kreuzer * 25704e0dc4aSTimo Kreuzer *Exit: 25804e0dc4aSTimo Kreuzer * 25904e0dc4aSTimo Kreuzer * if (!_getptd()->ownlocale || _getptd()->ptlocinfo == nullptr) 26004e0dc4aSTimo Kreuzer * _getptd()->ptlocinfo == __acrt_current_locale_data 26104e0dc4aSTimo Kreuzer * else 26204e0dc4aSTimo Kreuzer * _getptd()->ptlocinfo 26304e0dc4aSTimo Kreuzer * 26404e0dc4aSTimo Kreuzer *Exceptions: 26504e0dc4aSTimo Kreuzer * 26604e0dc4aSTimo Kreuzer *******************************************************************************/ __acrt_update_thread_locale_data()26704e0dc4aSTimo Kreuzerextern "C" __crt_locale_data* __cdecl __acrt_update_thread_locale_data() 26804e0dc4aSTimo Kreuzer { 26904e0dc4aSTimo Kreuzer __crt_locale_data* ptloci = nullptr; 27004e0dc4aSTimo Kreuzer __acrt_ptd* const ptd = __acrt_getptd(); 27104e0dc4aSTimo Kreuzer 27204e0dc4aSTimo Kreuzer if (__acrt_should_sync_with_global_locale(ptd) || ptd->_locale_info == nullptr) 27304e0dc4aSTimo Kreuzer { 27404e0dc4aSTimo Kreuzer __acrt_lock(__acrt_locale_lock); 27504e0dc4aSTimo Kreuzer __try 27604e0dc4aSTimo Kreuzer { 27704e0dc4aSTimo Kreuzer ptloci = _updatetlocinfoEx_nolock(&ptd->_locale_info, __acrt_current_locale_data.value()); 27804e0dc4aSTimo Kreuzer } 27904e0dc4aSTimo Kreuzer __finally 28004e0dc4aSTimo Kreuzer { 28104e0dc4aSTimo Kreuzer __acrt_unlock(__acrt_locale_lock); 28204e0dc4aSTimo Kreuzer } 283*e98e9000STimo Kreuzer __endtry 28404e0dc4aSTimo Kreuzer } 28504e0dc4aSTimo Kreuzer else 28604e0dc4aSTimo Kreuzer { 28704e0dc4aSTimo Kreuzer ptloci = ptd->_locale_info; 28804e0dc4aSTimo Kreuzer } 28904e0dc4aSTimo Kreuzer 29004e0dc4aSTimo Kreuzer if (!ptloci) 29104e0dc4aSTimo Kreuzer { 29204e0dc4aSTimo Kreuzer abort(); 29304e0dc4aSTimo Kreuzer } 29404e0dc4aSTimo Kreuzer 29504e0dc4aSTimo Kreuzer return ptloci; 29604e0dc4aSTimo Kreuzer } 29704e0dc4aSTimo Kreuzer 29804e0dc4aSTimo Kreuzer 29904e0dc4aSTimo Kreuzer 30004e0dc4aSTimo Kreuzer //-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 30104e0dc4aSTimo Kreuzer // 30204e0dc4aSTimo Kreuzer // __crt_lc_time_data reference counting 30304e0dc4aSTimo Kreuzer // 30404e0dc4aSTimo Kreuzer //-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 30504e0dc4aSTimo Kreuzer // The C locale lc_time data is immutable and persistent. The lc_time data for 30604e0dc4aSTimo Kreuzer // any other locale is dynamically allocated (and thus not actually immutable). 30704e0dc4aSTimo Kreuzer // The lc_time_curr data member of __crt_locale_data is declared const to help 30804e0dc4aSTimo Kreuzer // ensure that code does not accidentally attempt to modify the C locale lc_time 30904e0dc4aSTimo Kreuzer // data. 31004e0dc4aSTimo Kreuzer // 31104e0dc4aSTimo Kreuzer // These functions encapsulate all mutation of the lc_time_curr. They accept a 31204e0dc4aSTimo Kreuzer // __crt_lc_time_data const*, handle the C locale as a special case, then cast 31304e0dc4aSTimo Kreuzer // away constness to mutate the lc_time data. __acrt_locale_add_lc_time_reference(__crt_lc_time_data const * const lc_time)31404e0dc4aSTimo Kreuzerextern "C" long __cdecl __acrt_locale_add_lc_time_reference( 31504e0dc4aSTimo Kreuzer __crt_lc_time_data const* const lc_time 31604e0dc4aSTimo Kreuzer ) 31704e0dc4aSTimo Kreuzer { 31804e0dc4aSTimo Kreuzer if (lc_time == nullptr || lc_time == &__lc_time_c) 31904e0dc4aSTimo Kreuzer { 32004e0dc4aSTimo Kreuzer return LONG_MAX; 32104e0dc4aSTimo Kreuzer } 32204e0dc4aSTimo Kreuzer 32304e0dc4aSTimo Kreuzer return _InterlockedIncrement(&const_cast<__crt_lc_time_data*>(lc_time)->refcount); 32404e0dc4aSTimo Kreuzer } 32504e0dc4aSTimo Kreuzer __acrt_locale_release_lc_time_reference(__crt_lc_time_data const * const lc_time)32604e0dc4aSTimo Kreuzerextern "C" long __cdecl __acrt_locale_release_lc_time_reference( 32704e0dc4aSTimo Kreuzer __crt_lc_time_data const* const lc_time 32804e0dc4aSTimo Kreuzer ) 32904e0dc4aSTimo Kreuzer { 33004e0dc4aSTimo Kreuzer if (lc_time == nullptr || lc_time == &__lc_time_c) 33104e0dc4aSTimo Kreuzer { 33204e0dc4aSTimo Kreuzer return LONG_MAX; 33304e0dc4aSTimo Kreuzer } 33404e0dc4aSTimo Kreuzer 33504e0dc4aSTimo Kreuzer return _InterlockedDecrement(&const_cast<__crt_lc_time_data*>(lc_time)->refcount); 33604e0dc4aSTimo Kreuzer } 33704e0dc4aSTimo Kreuzer __acrt_locale_free_lc_time_if_unreferenced(__crt_lc_time_data const * const lc_time)33804e0dc4aSTimo Kreuzerextern "C" void __cdecl __acrt_locale_free_lc_time_if_unreferenced( 33904e0dc4aSTimo Kreuzer __crt_lc_time_data const* const lc_time 34004e0dc4aSTimo Kreuzer ) 34104e0dc4aSTimo Kreuzer { 34204e0dc4aSTimo Kreuzer if (lc_time == nullptr || lc_time == &__lc_time_c) 34304e0dc4aSTimo Kreuzer { 34404e0dc4aSTimo Kreuzer return; 34504e0dc4aSTimo Kreuzer } 34604e0dc4aSTimo Kreuzer 34704e0dc4aSTimo Kreuzer if (__crt_interlocked_read(&lc_time->refcount) != 0) 34804e0dc4aSTimo Kreuzer { 34904e0dc4aSTimo Kreuzer return; 35004e0dc4aSTimo Kreuzer } 35104e0dc4aSTimo Kreuzer 35204e0dc4aSTimo Kreuzer __acrt_locale_free_time(const_cast<__crt_lc_time_data*>(lc_time)); 35304e0dc4aSTimo Kreuzer _free_crt(const_cast<__crt_lc_time_data*>(lc_time)); 35404e0dc4aSTimo Kreuzer } 355