g319909.nwytg.coM
g319909.nwytg.coM

Reputation: 37

Get a code page for each locale in OEM and Ansi

How do I get the code page for each locale (not only for my locale)?

I looking for a simple function in python / c# / c (prefer with python or c#) to found for each locale that I want what is the code page in Ansi and in OEM.

Upvotes: 4

Views: 663

Answers (1)

Eryk Sun
Eryk Sun

Reputation: 34260

In C, starting with Windows Vista, you can query information for a locale name via GetLocaleInfoEx. The locale information constants to query the ANSI and OEM codepages are, respectively,LOCALE_IDEFAULTANSICODEPAGE (0x1004) and LOCALE_IDEFAULTCODEPAGE (0x000B). You can enumerate all system locale names via EnumSystemLocalesEx and query the ANSI and OEM codepages for each locale in the callback.

In a Python script, you can call these functions via ctypes. For example:

import ctypes
from ctypes import c_int
from ctypes.wintypes import BOOL, DWORD, LPVOID, LPWSTR, LPARAM, WCHAR

kernel32 = ctypes.WinDLL('kernel32', use_last_error=True)

CP_ACP = 0
CP_OEMCP = 1
LOCALE_NAME_USER_DEFAULT = None
LOCALE_NAME_SYSTEM_DEFAULT = "!x-sys-default-locale"
LOCALE_RETURN_NUMBER = 0x20000000
LOCALE_IDEFAULTCODEPAGE = 0x0000000B
LOCALE_IDEFAULTANSICODEPAGE = 0x00001004
LOCALE_SENGLISHLANGUAGENAME = 0x00001001
LOCALE_SENGLISHCOUNTRYNAME = 0x00001002

LOCALE_ENUMPROCEX = ctypes.WINFUNCTYPE(BOOL, 
    LPWSTR, # lpLocaleString
    DWORD,  # dwFlags
    LPARAM) # lParam

def _check_zero(result, func, args):
    if not result:
        raise ctypes.WinError(ctypes.get_last_error())
    return args

kernel32.EnumSystemLocalesEx.errcheck = _check_zero
kernel32.EnumSystemLocalesEx.argtypes = (
    LOCALE_ENUMPROCEX, # lpLocaleEnumProcEx
    DWORD,             # dwFlags
    LPARAM,            # lParam
    LPVOID)            # lpReserved

LCTYPE = DWORD
kernel32.GetLocaleInfoEx.errcheck = _check_zero
kernel32.GetLocaleInfoEx.argtypes = (
    LPWSTR, # lpLocaleName,
    LCTYPE, # LCType,
    LPVOID, # lpLCData,
    c_int)  # cchData

def get_language(locale=LOCALE_NAME_SYSTEM_DEFAULT):
    length = kernel32.GetLocaleInfoEx(locale, LOCALE_SENGLISHLANGUAGENAME, 
        None, 0)
    language = (WCHAR * length)()
    kernel32.GetLocaleInfoEx(locale, LOCALE_SENGLISHLANGUAGENAME, 
        language, length)
    return language.value

def get_country(locale=LOCALE_NAME_SYSTEM_DEFAULT):
    length = kernel32.GetLocaleInfoEx(locale, LOCALE_SENGLISHCOUNTRYNAME, 
        None, 0)
    country = (WCHAR * length)()
    kernel32.GetLocaleInfoEx(locale, LOCALE_SENGLISHCOUNTRYNAME, 
        country, length)
    return country.value

def get_acp(locale=LOCALE_NAME_SYSTEM_DEFAULT):
    cp_ansi = DWORD()
    kernel32.GetLocaleInfoEx(locale, LOCALE_IDEFAULTANSICODEPAGE | 
        LOCALE_RETURN_NUMBER, ctypes.byref(cp_ansi), 
        ctypes.sizeof(cp_ansi) // ctypes.sizeof(WCHAR))
    return cp_ansi.value

def get_oemcp(locale=LOCALE_NAME_SYSTEM_DEFAULT):
    cp_oem = DWORD()
    kernel32.GetLocaleInfoEx(locale, LOCALE_IDEFAULTCODEPAGE | 
        LOCALE_RETURN_NUMBER, ctypes.byref(cp_oem), 
        ctypes.sizeof(cp_oem) // ctypes.sizeof(WCHAR))
    return cp_oem.value

def list_system_locales():
    system_locales = []
    @LOCALE_ENUMPROCEX
    def enum_cb(locale, flags, param):
        system_locales.append((locale, 
            get_language(locale), get_country(locale), 
            get_acp(locale), get_oemcp(locale)))
        return True
    kernel32.EnumSystemLocalesEx(enum_cb, 0, 0, None)
    return sorted(system_locales)

Note that Unicode-only locales do not have an ANSI or OEM codepage. In this case the values returned are for the current system ANSI and OEM codepages, i.e. CP_ACP (0) and CP_OEMCP (1). For example, the Hindi (hi) language in India (IN) is a Unicode-only locale:

>>> (get_acp('hi-IN'), get_oemcp('hi-IN')) == (CP_ACP, CP_OEMCP)
True

Upvotes: 4

Related Questions