in reply to Adding WlanConnect() to Win32::Wlan::API

I never got success when using the fancier ways that Win32::API provides for encoding the structs. I've always had to manually use pack and specify integers and pointers when importing functions. Maybe the numerical value of $^E is documented somewhere in the MSDN? A cursory search turns up error 1008, which seems to just mean that you used an unknown GUID...

The signature for WlanConnect() seems to be

['WlanConnect' => 'IPPI' => 'I'],

and I think it should be possible to construct the appropriate structure without involving that dark Win32::API magic that I try to avoid. You "just" have to pack the two DOT11 structs and put pointers to them (using the P pack template) into a string, and pass that string to WlanConnect. In principle it should be easy, but I currently don't have the time to investigate this, sorry.

Replies are listed 'Best First'.
Re^2: Adding WlanConnect() to Win32::Wlan::API
by tomsell (Acolyte) on Jun 26, 2012 at 19:53 UTC

    @corion Hey, thanks for the reply and suggesting pack(). Dunno about the "easy" bit but failing me getting a solution in perl, as at last resort one could outsource this to a native implementation and start an external process. Pure perl would be nicer though.

    The IPPI signature is correct as is my GUID. However, the return value of the $API{ WlanConnect }->Call() is 87. Would this be need to be massaged into something meaningful?

        I have a feeling that there's nothing obvious wrong with the values as such set in the perl application code. Under XP, it's mostly defaults that are available. Passing them on to the DLL seems to be the problem.

      How are you sure your GUID is correct? Win32::API doesn't have any built in understanding of GUIDs. If you got your GUIDs by dropping the '-'s, you did it wrong. Also there might be a bug in your using of Encode. Encode won't put a wide null unless you explicitly have a "\x00" in the scalar that you can see. Encode WONT see the secret null that perl keeps after the end of the visible string. Win32::API uses the letter S, not P for structs. P is for a scalar string (or self packed integer "\x01\x02\x03\x04" or self packed struct). An API::Struct is a object, if you print it, you'll probably get the reference in hex. So whoever is using the the IPPI prototype is very wrong.

      Post the code where you created the API object and the prototype you used. Your code isn't runnable currently.

      update, I just noticed the part where you mentioned "Win32::Wlan::API", the previous 2 paragraphs were written without me realizing your using a CPAN mod. After looking at Wlan::API, I see Wlan::API never uses API::Struct. Using P instead of S is probably your error.

        The GUID is obtained the same way the stock Wlan::API does it and it is used all over the place, e.g in the (added by me) WlanSetProfile(), which creates a new profile from the required XML structures like thus:

        sub WlanSetProfile { croak "Wlan functions are not available" unless $wlan_available; my ($handle, $guuid, $xmlref) = @_; my $reason = Zero; $API{ WlanSetProfile }->Call($handle, $guuid, 0, $$xmlref, 0, 1, 0 +, $reason) == 0 or die "$^E"; };

        Background: I want to automate establishing an ad-hoc network. On XP, insecure WEP is the only available encryption method. So, in order to make things a bit more secure, before connecting I create a new profile with a new WEP key, effectively creating a session key.

        WlanSetProfile() succeeds and I can use the new profile to connect manually. So, the GUID is good. Also, the UTF16LE profilename is good, because before creating a new profile, I do some housekeeping and delete the previously used profile with the (added by me) WlanDeleteProfile()

        sub WlanDeleteProfile { croak "Wlan functions are not available" unless $wlan_available; my ($handle, $guuid, $profilename) = @_; $API{ WlanDeleteProfile }->Call($handle, $guuid, $profilename, 0) +== 0 or die "$^E"; };

        Deleting a profile works by supplying its name in the required fashion. WlanDeleteProfile() succeeds.

        Unfortunately, using S for P in the signature

        ['WlanConnect' => 'IPSI' => 'I']

        makes no difference.

        I think my best bet is to follow Corion's suggestion and investigate pack()ing some string.