in reply to Re^6: Adding WlanConnect() to Win32::Wlan::API (modded Wlan::API.pm)
in thread Adding WlanConnect() to Win32::Wlan::API

Win32::API::Struct->typedef('WLAN_CONNECTION_PARAMETERS', qw( WLAN_CONNECTION_MODE wlanConnectionMode; LPCWSTR strProfile; PDOT11_SSID pDot11Ssid; PDOT11_BSSID_LIST pDesiredBssidList; DOT11_BSS_TYPE dot11BssType; DWORD dwFlags; )); Win32::API::Struct->typedef ('DOT11_SSID', qw( ULONG uSSIDLength; UCHAR ucSSID; ));
"WLAN_CONNECTION_MODE wlanConnectionMode;", "PDOT11_SSID pDot11Ssid;", "PDOT11_BSSID_LIST pDesiredBssidList;", "DOT11_BSS_TYPE dot11BssType;" as types have never been registered earlier with Win32::API::Struct. Some of those are enums and not pointers to structs, which leads me to the next issue
# unused Win32::API::Struct->typedef('WLAN_CONNECTION_MODE', qw( wlan_connection_mode_profile = 0, wlan_connection_mode_temporary_profile, wlan_connection_mode_discovery_secure, wlan_connection_mode_discovery_unsecure, wlan_connection_mode_auto, wlan_connection_mode_invalid ));
Win32::API::Struct does NOT support enums. On Windows, enum is a "int", which always 32 bits, regardless of platform (32/64).

Win32::API::Struct can do a better job giving error messages when encountering unknown types.

update, your script doesn't run,
C:\Documents and Settings\Owner\Desktop\cpan libs\Win32-Wlan-0.06>perl + wlan.pl Win32::API::Struct::typedef: unknown member type="WLAN_CONNECTION_MODE +", name="w lanConnectionMode" at C:/perl512/site/lib/Win32/API/Struct.pm line 46. Win32::API::Struct::typedef: unknown member type="wlan_connection_mode +_profile", name="=" at C:/perl512/site/lib/Win32/API/Struct.pm line 46. Unknown Win32::API::Struct 'WLAN_CONNECTION_PARAMETERS' at C:/perl512/ +site/lib/W in32/Wlan/API.pm line 373 Can't call method "Pack" on unblessed reference at C:/perl512/site/lib +/Win32/Wla n/API.pm line 381. C:\Documents and Settings\Owner\Desktop\cpan libs\Win32-Wlan-0.06>

Replies are listed 'Best First'.
Re^8: Adding WlanConnect() to Win32::Wlan::API (structs no go?)
by tomsell (Acolyte) on Jun 27, 2012 at 20:00 UTC

    So, I take it that even with properly declared types, Win32::API::Struct is a no go here as the native Wlan API uses enums all over the place, e.g. those DOT11 things?

    There are no workarounds? I mean, in the call to the DLL, I cut corners by using ints.

    Code doesn't run? OK, I had just typed the .pl in w/o testing it. Now, I just d/led script and module from the website and they don't throw errors here. My Struct.pm contains this header info:

    ###################################################################### +# # # Win32::API::Struct - Perl Win32 API struct Facility # # Version: 0.45 # Date: 28 Nov 2006 # Author: Aldo Calpini <dada@perl.it> # Maintainer: Cosimo Streppone <cosimo@cpan.org> # # $Id: Struct.pm,v 1.0 2001/10/30 13:57:31 dada Exp $ ###################################################################### +#
      Your using a module 6 years older than the current version with .68-.45*100 releases in between. A 6 year old module isn't necessarily bad, but if it has had 2 dozen releases since in 6 years, using such an old version is ill advised. Try using the latest version of Win32::API.

      As an experiment, I installed 0.45 of Win32::API, your code still doesn't run.
      C:\Documents and Settings\Owner\Desktop\cpan libs\Win32-Wlan-0.06>perl + wlan.pl The system cannot find the file specified at C:/perl512/site/lib/Win32 +/Wlan/API. pm line 381, <DATA> line 164. C:\Documents and Settings\Owner\Desktop\cpan libs\Win32-Wlan-0.06>perl + -MWin32:: API -MWin32::Wlan::API -e "print $Win32::API::VERSION" 0.45 C:\Documents and Settings\Owner\Desktop\cpan libs\Win32-Wlan-0.06>
      Internally, Win32::API 0.45 still generates a garbage struct since your using undefined Win32::API types.
      #from Win32::API::Struct 0.45 sub Pack { my $self = shift; my($packing, $items, $recipients) = $self->getPack(); DEBUG "(PM)Struct::Pack: $self->{__typedef__}(buffer) = pack($pack +ing, @$items)\n"; $self->{buffer} = pack($packing, @$items); if(DEBUG) { for my $i (0..$self->sizeof-1) { printf " %3d: 0x%02x\n", $i, ord(substr($self->{buffer} +, $i, 1)); } } $self->{buffer_recipients} = $recipients }
      $packing contains "SL". I modified Wlan::API's WlanConnect to
      sub WlanConnect { croak "Wlan functions are not available" unless $wlan_available; my ($handle, $guuid, $profilename, $ssid) = @_; my $pDot11Ssid = Win32::API::Struct->new('DOT11_SSID'); $pDot11Ssid->{uSSIDLength} = length $ssid; $pDot11Ssid->{ucSSID} = $ssid; my $Wlan_connection_parameters = Win32::API::Struct->new('WLAN_CON +NECTION_PARAMETERS'); $Wlan_connection_parameters->{wlanConnectionMode} = 0; $Wlan_connection_parameters->{strProfile} = $profilename; $Wlan_connection_parameters->{pDot11Ssid} = $pDot11Ssid; $Wlan_connection_parameters->{pDesiredBssidList} = 0; $Wlan_connection_parameters->{dot11BssType} = 3; $Wlan_connection_parameters->{dwFlags} = 0; my $reterr = $API{ WlanConnect }->Call($handle, $guuid, $Wlan_con +nection_parameters, 0); $reterr == 0 or die "WlanConnect return Error $reterr "; };
      and reran it under Win32::API, 0.45.
      C:\Documents and Settings\Owner\Desktop\cpan libs\Win32-Wlan-0.06>perl + wlan.pl WlanConnect return Error 87 at C:/perl512/site/lib/Win32/Wlan/API.pm +line 382, <DATA> line 164. C:\Documents and Settings\Owner\Desktop\cpan libs\Win32-Wlan-0.06>perl + -MWin32: API -MWin32::Wlan::API -e "print $Win32::API::VERSION" 0.45 C:\Documents and Settings\Owner\Desktop\cpan libs\Win32-Wlan-0.06>
      The work around is to use "INT" instead of enums specific types and keep a hash that converts enum slice names (as hash key names) to numeric equivalents (hash key value). Not all the things in WLAN_CONNECTION_PARAMETERS are enums. Some are pointers to other structs. Can I ask what level is your knowledge of C?

      update, at first glance, there seems to be a bug in latest Win32::API, a ::Struct with a pointer to a ::Struct is broken, the parent ::Struct always treats the child ::Struct nested inline struct, not a struct pointer. So the Error 87 invalid parameter is the limit of using Win32::API::Struct module. You have to use pack, there probably is no alternative.
        i got WlanConnect to work, here is your WlanConnect, it makes my wireless popup bubble come up, so it works
        sub WlanConnect { croak "Wlan functions are not available" unless $wlan_available; my ($handle, $guuid, $profilename, $ssid) = @_; # possibly overkill, a pDot11Ssid = 0 should suffice #my $pDot11Ssid = Win32::API::Struct->new('PDOT11_SSID'); #$pDot11Ssid->{uSSIDLength} = length $ssid; #$pDot11Ssid->{ucSSID} = $ssid; my $SSIDstruct = pack('LZ[32]',length $ssid, $ssid ); #not overflo +w checked my $Wlan_connection_parameters = pack('LPPJLL', 0, $profilename, $ +SSIDstruct, 0, 3, 0); #$Wlan_connection_parameters->{wlanConnectionMode} = 0; #$Wlan_connection_parameters->{strProfile} = $profilename; #$Wlan_connection_parameters->{pDot11Ssid} = $pDot11Ssid; #$Wlan_connection_parameters->{pDesiredBssidList} = 0; #$Wlan_connection_parameters->{dot11BssType} = 3; #$Wlan_connection_parameters->{dwFlags} = 0; my $reterr = $API{ WlanConnect }->Call($handle, $guuid, $Wlan_con +nection_parameters, 0); $reterr == 0 or die "WlanConnect return Error $reterr "; }
        I also changed main for null safety and to work on my machine
        sub main { $ARGV[0] = 'removed'; $ARGV[1] = 'removed'; die "USAGE: $0 PROFILENAME SSID\n" unless($ARGV[1]); my $profilename = $ARGV[0]; my $ssid = $ARGV[1]; my $wlan_handle = WlanOpenHandle(); my @interfaces = WlanEnumInterfaces($wlan_handle); my $wlan_guuid = $interfaces[0]->{guuid}; $profilename = encode('UTF-16LE', $profilename."\x00"); WlanConnect($wlan_handle, $wlan_guuid, $profilename, $ssid); }
        I dont think my pack codes work on x64 BTW. Perhaps another monk can rewrite them to be portable, or you can just make another SOPW post.