in reply to help with Win32::API (Struct and general)

It would us to help you if the code you posted at least compiled clean of simple typos.

  1. $rasentry = Win32::API::Struct->New( 'RASENTRY' );

    The is no method New(...), it is new(...)

  2. $ret = RasSetEntryProperties( $Phonebook, $Entry, $rasentry, (Win32::API::Struct::sizeof($rasentry), 0, 0);

    There is an extraneous left paren.

If you had enabled warnings (-w or use warnings;) then you would see that once the above typos are corrected, your code produces 938 lines of warnings.

These two

Useless use of hash element in void context at test.pl8 line 170. Useless use of hash element in void context at test.pl8 line 349.

relate to these two lines where you have forgotten to add the assignment.

$rasentry->{dwDialExtraSampleSeconds}; #170 $rasentry->{dwDialExtraSampleSeconds}; #349

The other 936 come from Win32::API::Struct or Win32::API::Type. When a module starts producing large numbers of warnings like this, you can draw one of two conclusions: Either the module author ignored warnings and published a really crap module--which does happen, but for the most part not-- or, you are using it incorrectly.

For my part, I usually assume the latter, and I'm rarely disappointed:)

Picking out a few lines of your code and analysing them

The upshot is that you will need to resolve these symbolic constants to their numeric values. There are several approaches to doing this, and it would be an interesting project to extend Win32::API to automate some more of this type of thing, but it would entail a great deal of work and would not be something to take on lightly.

I hope that this post won't offend you and will clarify some of the problems that you face in re-writing Win32::RASE to work with Win2K. None of the problems are insurmountable, but there is no readily available shortcut to the process.


Examine what is said, not who speaks.
"Efficiency is intelligent laziness." -David Dunham
"When I'm working on a problem, I never think about beauty. I think only how to solve the problem. But when I have finished, if the solution is not beautiful, I know it is wrong." -Richard Buckminster Fuller
If I understand your problem, I can solve it! Of course, the same can be said for you.

Replies are listed 'Best First'.
Re: Re: help with Win32::API (Struct and general)
by mabman (Novice) on Aug 22, 2003 at 02:56 UTC
    No problem, not offended :) Thanks for pointing out the "warnings" thing, I wasn't aware of that option.

    I thought I had mentioned that I was testing on Windows 2000, which means only the 3rd condition in the if..else loop was relevant for me, which has the correct case for "new" and also had the offending hash assignment commented out. It's probably bad form that I didn't change all the loops equally, but I'm more concerned with getting it to actually work for me :)

    The RASOPTIONS thing is definitely confusing for me; I'm trying to understand it conceptually. How it's defined in C is mentioned in the my original post; I'm not sure how that translates to Perl. In my mind the DWORD does not compute - each of those options is represented by a checkbox in the normal Windows configuration GUI, and therefore it seems to me each should be a simple Boolean option.

    I'll keep trying when I have some more time...

    Thanks again for taking the time to look it over.

      In my mind the DWORD does not compute - each of those options is represented by a checkbox in the normal Windows configuration GUI, and therefore it seems to me each should be a simple Boolean option.

      That's exactly what they are...simple booleans. In fact each option is represented by a single binary bit. It's just that all the bits are put together into a lump of memory that is convenient for the processor to manipulate, in this case, a 32-bit unsigned value.

      The ras.h #defines for this field are

      /* RASENTRY 'dwfOptions' bit flags. */ #define RASEO_UseCountryAndAreaCodes 0x00000001 #define RASEO_SpecificIpAddr 0x00000002 #define RASEO_SpecificNameServers 0x00000004 #define RASEO_IpHeaderCompression 0x00000008 #define RASEO_RemoteDefaultGateway 0x00000010 #define RASEO_DisableLcpExtensions 0x00000020 #define RASEO_TerminalBeforeDial 0x00000040 #define RASEO_TerminalAfterDial 0x00000080 #define RASEO_ModemLights 0x00000100 #define RASEO_SwCompression 0x00000200 #define RASEO_RequireEncryptedPw 0x00000400 #define RASEO_RequireMsEncryptedPw 0x00000800 #define RASEO_RequireDataEncryption 0x00001000 #define RASEO_NetworkLogon 0x00002000 #define RASEO_UseLogonCredentials 0x00004000 #define RASEO_PromoteAlternates 0x00008000 #if (WINVER >= 0x401) #define RASEO_SecureLocalFiles 0x00010000 #endif #if (WINVER >= 0x500) #define RASEO_RequireEAP 0x00020000 #define RASEO_RequirePAP 0x00040000 #define RASEO_RequireSPAP 0x00080000 #define RASEO_Custom 0x00100000

      As you can see, each option is a represented by a seperate bit in the 32-bit DWORD. This means that to determine the value required to set the options you were trying to set

      $RASOPTIONS = "RASEO_IpHeaderCompression+RASEO_RemoteDefaultGateway+RA +SEO_SwCompression";

      You need to combine the numeric values defined for each of the options you require. You can use +, but oring (|)them is the usual idiom with boolean values like this.

      my $RASOPTIONS = 0x00000008 | 0x00000010 | 0x00000200;

      This leaves $RASOPTIONS with a value of 0x00000218, which may not make much sense until you look at that in binary.

      0x00000008 0000 0000 0000 0000 0000 0000 0000 1000 | 0x00000010 0000 0000 0000 0000 0000 0000 0001 0000 | 0x00000200 0000 0000 0000 0000 0000 0010 0000 0000 = 0x00000218 0000 0000 0000 0000 0000 0010 0001 1000

      By representing these booleans this way, up to 32 different options can be stored in an efficient manor. Currently 21 of them are used which leaves 11 for future expansion without requiring big changes to the APIs.

      It also make it possible to set, clear and test individual or combinations of options easily and efficiently.

      # Set options # RASEO_IpHeaderCompression # RASEO_RemoteDefaultGateway # RASEO_SwCompression # without affecting any other options. $options |= 0x00000008 | 0x00000010 | 0x00000200; # Clear those same options again leaving every other option as it was $options &= ~(0x00000008 | 0x00000010 | 0x00000200); # do something if all three options are set # regardless of what other options are set. if( ($options & (0x00000008 | 0x00000010 | 0x00000200)) == (0x0000000 +8 | 0x00000010 | 0x00000200) ) { # do something } # Do something if ONLY those three options are set if( $options == (0x00000008 | 0x00000010 | 0x00000200) ) { # do it }

      Of course, it is much more readable to use symbolic names instead of binary or hex constants for this, and you can do this nicely in perl by

      use constant RASEO_IpHeaderCompression = 0x00000008;

      which makes for nice, readable and efficient code. The only downside is that you will have to define these yourself as Perl doesn't read C header files. Actually it is possible to ask perl to pre-process your script through a C pre-preocessor using the -P option, but is "highly discouraged" and perlrun lists a whole bunch of reasons why you shouldn't do this. It also gives a better solution, Filter::cpp. If you have a compiler on your system, and therefor have access to ras.h, then you could use this to save you needing to hand-code all the constant definitions.

      It is also fairly trivial matter to write a perl script to convert all the simple #defines in a header file into a set of constant definitions for inclusion into your module. If you built your own copy of perl, then there is at least one script included in sources for doing this.

      Hope that this makes some sense and will assist you when you get time to persue the matter further. Good luck.


      Examine what is said, not who speaks.
      "Efficiency is intelligent laziness." -David Dunham
      "When I'm working on a problem, I never think about beauty. I think only how to solve the problem. But when I have finished, if the solution is not beautiful, I know it is wrong." -Richard Buckminster Fuller
      If I understand your problem, I can solve it! Of course, the same can be said for you.

        Thanks!! That makes sense.