shay has asked for the wisdom of the Perl Monks concerning the following question:

I'm trying to call the Win32 API function GetSystemDefaultLangID() via Perl's Win32::API module, but I can't get it to work.

Here's the program that I thought would give me the answer:

use strict; use warnings; use Win32::API; Win32::API->Import('kernel32.dll', 'LANGID GetSystemDefaultLangID()') +or die "Can't import GetSystemDefaultLangID: $^E\n"; my $langid = GetSystemDefaultLangID(); if (defined $langid) { print "Returned '$langid'\n"; printf "Lang ID: 0x%04X\n", $langid; } else { print "Returned <undef>\n"; }

However, when I run this it just outputs:

Returned <undef>

The function itself works fine from a simple C program:

#include <stdio.h> #include <windows.h> #include <winnls.h> void main(void) { printf("Lang ID = 0x%04X\n", GetSystemDefaultLangID()); }

and similar Perl Win32::API programs involving other Win32 API functions also work fine, e.g.

use strict; use warnings; use Win32::API; Win32::API->Import('kernel32.dll', 'DWORD GetCurrentProcessId()') or die "Can't import GetCurrentProcessId: $^E\n"; my $procid = GetCurrentProcessId(); if (defined $procid) { print "Returned '$procid'\n"; } else { print "Returned <undef>\n"; }

Where can I have gone wrong with something so simple, or is this a bug in Win32::API?

- Steve

Replies are listed 'Best First'.
Re: How to call GetSystemDefaultLangID() with Win32::API
by NetWallah (Canon) on Jun 23, 2004 at 15:29 UTC
    In your API protptype declaration, replace LANGID by 'long', and it works fine.

    My guess is that the LANGID type is not interpreted properly, but, since that is a 'long' anyway, you can use that directly.

    use strict; use warnings; use Win32::API; Win32::API->Import('kernel32.dll', 'long GetSystemDefaultLangID()') or die "Can't import GetSystemDefaultLangID: $^E\n"; my $langid = GetSystemDefaultLangID() or die "ERROR: LANGID Returned < +undef>\n"; print "Returned '$langid'\n"; printf "Lang ID: 0x%04X\n", $langid; #---- Run on Win XP (US English) Returns --- #Returned '2011563017' #Lang ID: 0x77E60409

    Earth first! (We'll rob the other planets later)

      Well, Win32::API::Types lists LANGID as 's', which I assume means a (signed?) short. Actually, LANGID is typedef'd as WORD (in <winnt.h>), which is an unsigned short (not a LONG), so specifying USHORT should have fixed it, but still doesn't.

      Your idea of specifying LONG certainly produces some output: I get similar output to you:

      Returned '2011563020' Lang ID: 0x77E6040C

      but it's utter crap: the Lang ID is actually 0x0809 (2057) for UK English or 0x0409 (1033) for US English. (And the C program in my original post correctly produces these numbers.)

      How do I get the /right/ answer out of it, not just any old rubbish?

        OK - since this is a SHORT, you need to mask out the high-order bytes for this to make sense.

        The following code DOES produce the expected "1033" value for English:

        use strict; use warnings; use Win32::API; Win32::API->Import('kernel32.dll', 'long GetSystemDefaultLangID()') or die "Can't import GetSystemDefaultLangID: $^E\n"; my $langid = GetSystemDefaultLangID() & 0xFFFF # Mask out the garbage + in high-order bytes or die "ERROR: LANGID Returned <undef>\n"; print "Returned '$langid'\n"; printf "Lang ID: 0x%04X\n", $langid; # Print output---- # Returned '1033' # Lang ID: 0x0409

        Earth first! (We'll rob the other planets later)

        How do I get the /right/ answer out of it, not just any old rubbish?

        You work out for yourself how to make the 9 character addition to the snippet I posted required to get the answer you need.

        use strict; use warnings; use Win32::API::Prototype; ApiLink( 'kernel32.dll', 'LONG GetSystemDefaultLangID( VOID )' ) or die "Can't import GetSystemDefaultLangID: $^E\n"; my $langid = GetSystemDefaultLangID( 0 ) & 0xffff; if (defined $langid) { print "Returned '$langid'\n"; printf "Lang ID: 0x%04X\n", $langid; } else { print "Returned <undef>\n"; } __END__ P:\test>369060 Returned '1033' Lang ID: 0x0409

        Of course, I could have searched through the header files, looked up what a LANGID was, and added these characters to my post, but I didn't have any real interest in doing that. You need the solution, not me.

        Perhaps I could clean your keyboard for you?


        Examine what is said, not who speaks.
        "Efficiency is intelligent laziness." -David Dunham
        "Think for yourself!" - Abigail
        "Memory, processor, disk in that order on the hardware side. Algorithm, algoritm, algorithm on the code side." - tachyon
Re: How to call GetSystemDefaultLangID() with Win32::API
by BrowserUk (Patriarch) on Jun 23, 2004 at 15:38 UTC

    Try this

    use strict; use warnings; use Win32::API::Prototype; ApiLink( 'kernel32.dll', 'LONG GetSystemDefaultLangID( VOID )' ) or die "Can't import GetSystemDefaultLangID: $^E\n"; my $langid = GetSystemDefaultLangID( 0 ); if (defined $langid) { print "Returned '$langid'\n"; printf "Lang ID: 0x%04X\n", $langid; } else { print "Returned <undef>\n"; } __END__ P:\test>test3 Returned '2011563017' Lang ID: 0x77E60409

    Examine what is said, not who speaks.
    "Efficiency is intelligent laziness." -David Dunham
    "Think for yourself!" - Abigail
    "Memory, processor, disk in that order on the hardware side. Algorithm, algoritm, algorithm on the code side." - tachyon
Re: How to call GetSystemDefaultLangID() with Win32::API
by slloyd (Hermit) on Jun 23, 2004 at 20:44 UTC
    This is a link to what you are looking for.
    http://cwashington.netreach.net/depo/view.asp?Index=309&ScriptType=perl
      That looks like good code (++), but it has the same problem - it returns junk in the high-order bits.

      I also had to change the [V] to "", in the "new" method for GetSystemDefaultLangID() . This may be due to different versions of perl, and Win32::API, and usage of strict and warnings.

          Earth first! (We'll rob the other planets later)