SAPI - How can I detect the users default Language ID (langid)?

Started by Nordwind64, June 21, 2006, 07:07:32 PM

Previous topic - Next topic

Nordwind64

Hi.

Hehe. Your German is as bad as my English...  :bg
Most work is done. Thanks!  :U

Best regards,
Nordwind
Greetings, Nordwind.
Windows 7 (64Bit), JWASM/PoLink

guga

I know this is a long delay, but i´m slowling coming back.

Here is the full source inside sapi translated to assembly (RosAsm syntax). The function needs to remove some annoyances (useless code, such as SpHrFromWin32 or SpHrFromLastWin32Error)
The macros are the default user made RosAsm ones, but...this can be easily ported to masm as well. (Proc, Local, If, Else, Else_If seems to be similar as in masm as far i can remember masm syntax).

The function below should work on all windows versions since win95 to Win7 and newer. This is only the 1st version, i´ll review the code later.

If suceeded the function will return the language ID. ON error the function will return FALSE.

This function have no parameters.



[OSVersionInfo:
OSVersionInfo.Size: D$ ?
OSVersionInfo.MajorVersion: D$ ?
OSVersionInfo.MinorVersion: D$ ?
OSVersionInfo.BuildNumber: D$ ?
OSVersionInfo.PlatformId: D$ ?
OSVersionInfo.CSDVersion: B$ ? #128
OSVersionInfo.ServicePackMajor: W$ ?
OSVersionInfo.ServicePackMinor: W$ ?
OSVersionInfo.SuiteMask: W$ ?
OSVersionInfo.ProductType: B$ ?
OSVersionInfo.Reserved: B$ ?]

[OSVI_SIZE 148 OSVI_EX_SIZE 156]
[SzData: B$ 0 #32]
[SzData2: B$ 0 #64]

Proc SpGetUserDefaultUILanguage:
    Local @hr, @hKey, @dwSize, @ValueName, @SzData
    Uses edi, esi, ebx, ecx, edx

    mov D$OSVersionInfo.Size OSVI_SIZE
    call 'Kernel32.GetVersionExA' OSVersionInfo
    ...If eax = &FALSE
        call SpHrFromLastWin32Error; This is just to retrieve the error code. It have no pratical use on this function.
        call 'KERNEL32.GetUserDefaultLangID'
        ; Get the UI language by one of three methods, depending on the system
    ...Else_If D$OSVersionInfo.PlatformId = &VER_PLATFORM_WIN32_NT

        ..If D$OSVersionInfo.MajorVersion <= 4 ; running on WinNT4 or earlier
            lea eax D@hKey
            call 'ADVAPI32.RegOpenKeyExA' &HKEY_USERS, {'.DEFAULT\Control Panel\International', 0}, 0, &KEY_READ, eax
            call SpHrFromWin32 eax ; Function succeed return &ERROR_SUCCESS = 0
                                   ; This is just to retrieve the error code. It have no pratical use on this function.
            .If eax = &SUCCEEDED
                mov D@dwSize 64
                lea edx D@dwSize
                call 'ADVAPI32.RegQueryValueExA' D@hKey, {'Locale', 0}, &NULL, &NULL, SzData2, edx
                mov D@hr eax ; Function succeed return &ERROR_SUCCESS = 0

                call SpHrFromWin32 eax ; This is just to retrieve the error code. It have no pratical use on this function.

                call 'ADVAPI32.RegCloseKey' D@hKey
                If D@hr = &SUCCEEDED ; Convert string to number
                    C_Call 'msvcrt.wcstol' SzData2, &NULL, 16
                    movzx eax ax
                    mov D@hr eax
                End_If

                If D@hr = 0401; Arabic Language
                    mov eax 0409 ; English US
                Else_If D@hr = 040F ; Hebrew
                    mov eax 0409 ; English US
                Else_If D@hr = 041E ; Thai
                    mov eax 0409 ; English US
                Else_If D@hr = 0
                    call 'KERNEL32.GetUserDefaultLangID'
                End_If

            .Else
                call 'KERNEL32.GetUserDefaultLangID'
            .End_If


        ..Else ; running on win2000 or later

            call 'KERNEL32.LoadLibraryA' {B$ 'kernel32.dll', 0}
            .If eax = &FALSE
                call SpHrFromLastWin32Error ; This is just to retrieve the error code. It have no pratical use on this function.
                call 'KERNEL32.GetUserDefaultLangID'
            .Else
                mov ebx eax
                call 'KERNEL32.GetProcAddress' eax, {B$ "GetUserDefaultUILanguage", 0}
                If eax = 0
                    call SpHrFromLastWin32Error ; This is just to retrieve the error code. It have no pratical use on this function.
                    xor eax eax
                Else
                    call eax
                End_If
                movzx eax ax
                mov D@hr eax
                call 'KERNEL32.FreeLibrary' ebx
                If D@hr = 0
                    call 'KERNEL32.GetUserDefaultLangID'
                Else
                    mov eax D@hr
                End_If
            .End_If

        ..End_If

    ...Else_If D$OSVersionInfo.PlatformId = &VER_PLATFORM_WIN32_WINDOWS ; Running on Win9X or earlier

        lea eax D@hKey
        call 'ADVAPI32.RegOpenKeyExA' &HKEY_USERS, {'.Default\Control Panel\desktop\ResourceLocale', 0}, 0, &KEY_READ, eax
        call SpHrFromWin32 eax ; Function succeed return &ERROR_SUCCESS = 0
        .If eax = &SUCCEEDED
            mov D@dwSize 32
            mov D@ValueName 0
            lea eax D@ValueName
            lea edx D@dwSize
            call 'ADVAPI32.RegQueryValueExA' D@hKey, eax, &NULL, &NULL, SzData, edx

             ; Function succeed return &ERROR_SUCCESS = 0
            call SpHrFromWin32 eax ; This is just to retrieve the error code. It have no pratical use on this function.
            movzx eax ax
            mov D@hr eax

            call 'ADVAPI32.RegCloseKey' D@hKey
            If D@hr = &SUCCEEDED ; Convert string to number
                C_Call 'msvcrt.strtol' SzData, &NULL, 16
                movzx eax ax
                On eax <> 0, ExitP
            End_If
        .End_If
        call 'KERNEL32.GetUserDefaultLangID'
    ...Else ; unsupported windows version. (Win3s or unknown)
        xor eax eax
    ...End_If

EndP

_______________________


Proc SpHrFromLastWin32Error:

    call 'KERNEL32.GetLastError'
    If eax = 0
        mov eax &E_FAIL
    Else
        call SpHrFromWin32 eax
    End_If

EndP
_____________________________

[HRESULT_FROM_WIN32 | #If #1=reg
                            #Error 'Please use only an address, immediate value or constant on this macro'
                      #Else_If #1=str
                            #Error 'Please use only an address, immediate value or constant on this macro'
                      #Else
                            mov eax #1 | test eax eax | jle L1> | and eax 0FFFF | or eax (&FACILITY_WIN32 shl 16 or 080000000) | L1:
                      #End_If]

Proc SpHrFromWin32:
    Arguments @dwErr


    HRESULT_FROM_WIN32 D@dwErr

EndP
_____________________________



Note: Edgar, Steve, and any others...feel free to translate it to masm syntax if you like.

BestRegards,

Guga

guga

Version 2.0


[OSVersionInfo:
OSVersionInfo.Size: D$ ?
OSVersionInfo.MajorVersion: D$ ?
OSVersionInfo.MinorVersion: D$ ?
OSVersionInfo.BuildNumber: D$ ?
OSVersionInfo.PlatformId: D$ ?
OSVersionInfo.CSDVersion: B$ ? #128
OSVersionInfo.ServicePackMajor: W$ ?
OSVersionInfo.ServicePackMinor: W$ ?
OSVersionInfo.SuiteMask: W$ ?
OSVersionInfo.ProductType: B$ ?
OSVersionInfo.Reserved: B$ ?]

[OSVI_SIZE 148 OSVI_EX_SIZE 156]

[SzData: B$ 0 #32]
[SzData2: B$ 0 #64]

Proc SpGetUserDefaultUILanguage:
    Local @hr, @hKey, @dwSize, @ValueName
    Uses edi, esi, ebx, ecx, edx

    mov D$OSVersionInfo.Size OSVI_SIZE
    call 'Kernel32.GetVersionExA' OSVersionInfo
    ...If eax = &FALSE

        call 'KERNEL32.GetUserDefaultLangID'
        ; Get the UI language by one of three methods, depending on the system
    ...Else_If D$OSVersionInfo.PlatformId = &VER_PLATFORM_WIN32_NT

        ..If D$OSVersionInfo.MajorVersion <= 4 ; running on WinNT4 or earlier
            lea eax D@hKey
            call 'ADVAPI32.RegOpenKeyExA' &HKEY_USERS, {'.DEFAULT\Control Panel\International', 0}, 0, &KEY_READ, eax

            .If eax = &ERROR_SUCCESS
                mov D@dwSize 64
                lea edx D@dwSize
                call 'ADVAPI32.RegQueryValueExA' D@hKey, {'Locale', 0}, &NULL, &NULL, SzData2, edx
                mov D@hr eax
                call 'ADVAPI32.RegCloseKey' D@hKey
                If D@hr = &ERROR_SUCCESS ; Convert string to number
                    C_Call 'msvcrt.wcstol' SzData2, &NULL, 16
                    movzx eax ax
                Else
                    xor eax eax
                End_If

                mov D@hr eax

                If D@hr = 0401; Arabic Language
                    mov eax 0409 ; English US
                Else_If D@hr = 040F ; Hebrew
                    mov eax 0409 ; English US
                Else_If D@hr = 041E ; Thai
                    mov eax 0409 ; English US
                Else_If D@hr = 0
                    call 'KERNEL32.GetUserDefaultLangID'
                End_If

            .Else
                call 'KERNEL32.GetUserDefaultLangID'
            .End_If

        ..Else ; running on win2000 or later

            call 'KERNEL32.LoadLibraryA' {B$ 'kernel32.dll', 0}
            .If eax = &FALSE
                call 'KERNEL32.GetUserDefaultLangID'
            .Else
                mov ebx eax
                call 'KERNEL32.GetProcAddress' eax, {B$ "GetUserDefaultUILanguage", 0}
                If eax <> &NULL
                    call eax
                End_If
                mov D@hr eax
                call 'KERNEL32.FreeLibrary' ebx
                If D@hr = &NULL
                    call 'KERNEL32.GetUserDefaultLangID'
                Else
                    mov eax D@hr
                End_If
            .End_If

        ..End_If

    ...Else_If D$OSVersionInfo.PlatformId = &VER_PLATFORM_WIN32_WINDOWS ; Running on Win9X or earlier

        lea eax D@hKey
        call 'ADVAPI32.RegOpenKeyExA' &HKEY_USERS, {'.Default\Control Panel\desktop\ResourceLocale', 0}, 0, &KEY_READ, eax
        .If eax = &ERROR_SUCCESS
            mov D@dwSize 32
            mov D@ValueName 0
            lea eax D@ValueName
            lea edx D@dwSize
            call 'ADVAPI32.RegQueryValueExA' D@hKey, eax, &NULL, &NULL, SzData, edx
            movzx eax ax
            mov D@hr eax
            call 'ADVAPI32.RegCloseKey' D@hKey
            If D@hr = &ERROR_SUCCESS; Convert string to number
                C_Call 'msvcrt.strtol' SzData, &NULL, 16
                movzx eax ax
                On eax <> 0, ExitP
            End_If
        .End_If
        call 'KERNEL32.GetUserDefaultLangID'

    ...Else ; unsupported windows version. (Win3s or unknown)
        xor eax eax
    ...End_If

EndP