The MASM Forum Archive 2004 to 2012

General Forums => The Campus => Topic started by: Nordwind64 on June 21, 2006, 07:07:32 PM

Title: SAPI - How can I detect the users default Language ID (langid)?
Post by: Nordwind64 on June 21, 2006, 07:07:32 PM
Hi!

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

Best regards,
Nordwind
Title: Re: SAPI - How can I detect the users default Language ID (langid)?
Post by: P1 on June 21, 2006, 08:28:01 PM
Win32API offers:
GetSystemDefaultLangID
GetUserDefaultLangID

Good all the way back to W95.

Regards,  P1  :8)
Title: Re: SAPI - How can I detect the users default Language ID (langid)?
Post by: Nordwind64 on June 21, 2006, 08:49:06 PM
Hi P1,

sorry, I'm speaking about SAPI stuff. Text2Speech and such things...
Title: Re: SAPI - How can I detect the users default Language ID (langid)?
Post by: P1 on June 21, 2006, 09:17:52 PM
A User is A User is A User.

So how is a user's langid for the written part of the OS, going to be different than the spoken part of the text of the OS?

How is this any different than the screen readers for the blind work?

Just watch out for Hex vs. Decimal.

Regards,  P1  :8)
Title: Re: SAPI - How can I detect the users default Language ID (langid)?
Post by: Nordwind64 on June 22, 2006, 04:40:09 AM
Hi.

QuoteSo how is a user's langid for the written part of the OS, going to be different than the spoken part of the text of the OS?
How is this any different than the screen readers for the blind work?

Yes, sorry it is. I'm a german user, but MS Sam is the default speech in my system. The ID is 409h. To use a german speech, I had to install the german speech files. I must now detect, if the user had installed the german files or not. Thats not possible with GetSystemDefaultLangID/GetUserDefaultLangID, what only gives me 407h. Even, if MS Sam is the default users speech.

Sorry for my bad english...

Best regards,
Nordwind
Title: Re: SAPI - How can I detect the users default Language ID (langid)?
Post by: P1 on June 22, 2006, 04:17:43 PM
From:
Quote from: Nordwind64 on June 21, 2006, 07:07:32 PMSAPI - How can I detect the users default Language ID (langid)?
To:
Quote from: Nordwind64 on June 22, 2006, 04:40:09 AMTo use a german speech, I had to install the german speech files. I must now detect, if the user had installed the german files or not.

So what you really want is to check for installed files for the LangID of the OS?  And you want to know, if there is a SAPI function to enumerate the language options installed?

From a Quick Google search, what you want to do is Enumerate the Voices available to SAPI.  Each Voice will have it's plain text descriptor and it's hex LangID, plus it's options, like male or female, etc..

M$ makes doing this in English as default, so it's fairly easy.  But I understand where your fustration comes from with language options with M$ products.

Regards,  P1  :8)

M$ = Microsoft
Title: Re: SAPI - How can I detect the users default Language ID (langid)?
Post by: Nordwind64 on June 22, 2006, 05:21:36 PM
Hi.

QuoteSo what you really want is to check for installed files for the LangID of the OS?  And you want to know, if there is a SAPI function to enumerate the language options installed?

I only want to know the actual LangID from the speech, the user have changed to. The language, the user is listen to in a Text2Speech program :U

QuoteFrom a Quick Google search, what you want to do is Enumerate the Voices available to SAPI.  Each Voice will have it's plain text descriptor and it's hex LangID, plus it's options, like male or female, etc..

Yes, I know. But I don't know, how to get it work. I could get the token with GetVoice, but I cannot read it for informations.
Shit, my English is to bad...

Best regards,
Nordwind
Title: Re: SAPI - How can I detect the users default Language ID (langid)?
Post by: P1 on June 22, 2006, 06:11:46 PM
Quick and dirty is to enumerate the Registry Here:
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Speech\VOICES\TOKENS
Note:  I have only English setup, But I had to go through a Voice setup, to have these voices available ( One male, One female ). 

Otherwise, you need to work through developing code from MSDN site:
In both SpEnumTokens and ISpObjectTokenCategory::EnumTokens the following clauses are permitted in the ReqAttrs and OptAttrs strings, separated by semicolons.

When what you want, is not there, then you need to develope a setup routine for those German Languges files and Voice setup.

Regards,  P1  :8)

PS:  Loading German Files does not setup the Voice for you.  I just did and I have no new voices to use.
Title: Re: SAPI - How can I detect the users default Language ID (langid)?
Post by: Nordwind64 on June 22, 2006, 07:49:54 PM
QuotePS:  Loading German Files does not setup the Voice for you.  I just did and I have no new voices to use.

Because you must have Microsoft Reader installed...
I will try to use your tips. Thanks!

Best regards,
Nordwind
Title: Re: SAPI - How can I detect the users default Language ID (langid)?
Post by: Nordwind64 on June 23, 2006, 03:15:58 PM
Could not get it working. Ok, in the registry there are tokens for all speeches and languages. But I cannot detect, which ist the one, SAPI talks with...

Sorry, I need help.  :red
Nordwind
Title: Re: SAPI - How can I detect the users default Language ID (langid)?
Post by: P1 on June 23, 2006, 03:36:57 PM
When enumerating the tokens, under the voice name is a sub key of "ATTRIBUTES", under which you will find "Language" and the hex in text value of the LangID. 

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Speech\VOICES\TOKENS\LHMICHAEL\ATTRIBUTES]
"Gender"="Male"
"Language"="409"
"Name"="LH Michael"


I know that some registries entries are language based, so I don't know if it will say any of the above is English Key words or you may adjust for German Key words.

The registry method is going to be quicker to implement, but the SAPI function method, I am sure it's more language independent.

Regards,  P1  :8)
Title: Re: SAPI - How can I detect the users default Language ID (langid)?
Post by: Nordwind64 on June 23, 2006, 05:05:00 PM
Hi.

I understand, what you mean. I can get all infos about all installed languages, no problem.
But I cannot see, which language is marked as default! That is, what i want to know...  :P
Title: Re: SAPI - How can I detect the users default Language ID (langid)?
Post by: P1 on June 23, 2006, 06:17:08 PM
[HKEY_CURRENT_USER\Software\Microsoft\Speech\Voices]
"DefaultTokenId"="HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Speech\\Voices\\Tokens\\LHMICHAEL"
"DefaultTTSRate"=dword:00000000


LHMICHAEL is my local name for my default voice.

Regards,  P1  :8)
Title: Re: SAPI - How can I detect the users default Language ID (langid)?
Post by: Nordwind64 on June 23, 2006, 07:26:53 PM
 :U

That's it! I only looked in HKEY_LOCAL_MACHINE instead of looking in HKEY_CURRENT_USER.  :dazzled:
Now I can read the default language parameters!

Thank you a lot!   :cheekygreen:

Best regards,
Nordwind
Title: Re: SAPI - How can I detect the users default Language ID (langid)?
Post by: P1 on June 23, 2006, 09:14:58 PM
Ihr Empfang!

Haben Sie ein nettes Wochenende!  :U

Aber ich bin ängstlich Sie haben mehr Arbeit vor Ihnen, als hinter Ihnen.  :eek

Beachtungen,  P1  :8)

PS: Ich habe gedacht, dass ich ein freies Deutsch zu englischem Übersetzer ausprobieren würde.
Title: Re: SAPI - How can I detect the users default Language ID (langid)?
Post by: Nordwind64 on June 24, 2006, 08:44:21 AM
Hi.

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

Best regards,
Nordwind
Title: Re: SAPI - How can I detect the users default Language ID (langid)?
Post by: guga on November 12, 2011, 12:28:12 AM
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
Title: Re: SAPI - How can I detect the users default Language ID (langid)?
Post by: guga on November 12, 2011, 01:11:53 AM
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