For me this is a learning experience, I haven't done anything like this before - so my code isn't pretty, and I may not have all the concepts down pat - I beg your indulgence :)
I've been using Win32::RASE as a bit of a reference, but it crashes with memory errors on Windows 2000 and hasn't been updated for a couple of years, hence my experiment.
My code attempt is below; I'm running it on Windows 2000 Pro with the latest ActiveState Perl, so it enters the 3rd conditional loop in my code, which is what I've been experimenting with.
Right now, the code does not work as anticipated; it always returns an error "632", which is a RAS error meaning "The structure size is incorrect."
I'm interested in all suggestions; there are a few things I'm not sure of which may make a good starting point:
- I went through the Win32::API::Struct documentation and followed the example as best I could; it did say I should be able to simply copy and paste a C-style struct, which I pretty much did from MSDN (here); did I do that properly? I assumed the constants mentioned in the MSDN entry may not work (they're not defined elsewhere in my Perl script), so I tried hard-coding the values directly into the script (no effect)
- as well, the Win32::API::Struct docs mention variable are initialized automatically and automatically passed as NULL if not expressly defined, so I've tried explicitly setting them and also just commenting out the entries I'm not interested in - no effect
- I wasn't sure how to use the Win32::API::Struct::sizeof() call exactly - I found a sample C program using the same API call, and it seems to use the name of the #define rather than the name of the instance (for instance, the C code says "sizeof(RASENTRY)", not "sizeof(newrasentry)" where newrasentry is an instance of RASENTRY) - not sure how that's supposed to look in Perl
- I'm not sure how the $RASOPTIONS variable is supposed to be defined; in the sample C program I found, the C code looked like:
Again, not sure what that's supposed to look like in Perl#define RAS_OPTIONS \ RASEO_UseCountryAndAreaCodes+\ RASEO_RemoteDefaultGateway+\ RASEO_ModemLights+\ RASEO_TerminalAfterDial
Code below; note that the RasSetEntryProperties call needs to have a modem installed on the system; for testing purposes I hard-coded the "dummy" modem I set up into the script. Thanks again.
#! /usr/bin/perl use Win32::API::Prototype; use Win32::API; use Win32::API::Struct; use Win32; # access RasSetEntryProperties win32 API ApiLink ( 'rasapi32.dll', 'DWORD RasSetEntryProperties( LPCTSTR lpszPhonebook, LPCTSTR lpszEntry, LPRASENTRY lpRasEntry, DWORD dwEntryInfoSize, LPBYTE lpbDeviceInfo, DWORD dwDeviceInfoSize )' ) || die "can't create API prototype"; # figure out what version of Windows this is running on - # important for contents of RASENTRY struct $winvermajor = (Win32::GetOSVersion)[1]; $winverminor = (Win32::GetOSVersion)[2]; print ("Major Windows version: ", $winvermajor, "\n"); print ("Minor windows version: ", $winverminor, "\n"); $RASOPTIONS = "RASEO_IpHeaderCompression+RASEO_RemoteDefaultGateway+RA +SEO_SwCompression"; # I'm not sure how win32::API::Struct handles conditional "if" stateme +nts inside of structs; # So I'm just going to define different structs depending on what Wind +ows version it's running on: # the 1st for Win95/WinNT, the 2nd for Win98/ME, the 3rd for Win2k, an +d the 4th for WinXP; # These correspond to the MS conventions for major/minor number OS des +ignations if (($winvermajor == 4) and ($winverminor == 0)) { print ("hit loop 1\n"); Win32::API::Struct->typedef( 'RASENTRY', qw( DWORD dwSize; DWORD dwfOptions; DWORD dwCountryID; DWORD dwCountryCode; TCHAR szAreaCode[ RAS_MaxAreaCode + 1 ]; TCHAR szLocalPhoneNumber[ RAS_MaxPhoneNumber + 1 ]; DWORD dwAlternateOffset; RASIPADDR ipaddr; RASIPADDR ipaddrDns; RASIPADDR ipaddrDnsAlt; RASIPADDR ipaddrWins; RASIPADDR ipaddrWinsAlt; DWORD dwFrameSize; DWORD dwfNetProtocols; DWORD dwFramingProtocol; TCHAR szScript[ MAX_PATH ]; TCHAR szAutodialDll[ MAX_PATH ]; TCHAR szAutodialFunc[ MAX_PATH ]; TCHAR szDeviceType[ RAS_MaxDeviceType + 1 ]; TCHAR szDeviceName[ RAS_MaxDeviceName + 1 ]; TCHAR szX25PadType[ RAS_MaxPadType + 1 ]; TCHAR szX25Address[ RAS_MaxX25Address + 1 ]; TCHAR szX25Facilities[ RAS_MaxFacilities + 1 ]; TCHAR szX25UserData[ RAS_MaxUserData + 1 ]; DWORD dwChannels; DWORD dwReserved1; DWORD dwReserved2; )) || die "Can't create RASENTRY struct"; $rasentry = Win32::API::Struct->New( 'RASENTRY' ); # Not sure if the syntax for dwSize below is correct $rasentry->{dwSize} = (Win32::API::Struct::sizeof($rasentry)); $rasentry->{dwfOptions} = $RASOPTIONS; $rasentry->{dwCountryID} = 0; $rasentry->{dwCountryCode} = 0; $rasentry->{szAreaCode} = ""; $rasentry->{szLocalPhoneNumber} = "3910895"; $rasentry->{ipaddr} = [0,0,0,0]; $rasentry->{ipaddrDns} = [0,0,0,0]; $rasentry->{ipaddrDnsAlt} = [0,0,0,0]; $rasentry->{ipaddrWins} = [0,0,0,0]; $rasentry->{ipaddrWinsAlt} = [0,0,0,0]; $rasentry->{dwFrameSize} = 0; $rasentry->{dwfNetProtocols} = RASNP_Ip; $rasentry->{dwFramingProtocol} = RASFP_Ppp; $rasentry->{szScript} = ""; $rasentry->{szAutodialDll} = ""; $rasentry->{szAutodialFunc} = ""; $rasentry->{szDeviceType} = "modem"; $rasentry->{szDeviceName} = "Standard 56000 bps V90 Modem"; $rasentry->{szX25PadType} = ""; $rasentry->{szX25Address} = ""; $rasentry->{szX25Facilities} = ""; $rasentry->{szX25UserData} = ""; $rasentry->{dwChannels} = 0; $rasentry->{dwReserved1} = 0; $rasentry->{dwReserved2} = 0; } elsif (($winvermajor == 4) and ($winverminor > 0)) { print ("hit loop 2\n"); Win32::API::Struct->typedef ('RASENTRY', qw( DWORD dwSize; DWORD dwfOptions; DWORD dwCountryID; DWORD dwCountryCode; TCHAR szAreaCode[ RAS_MaxAreaCode + 1 ]; TCHAR szLocalPhoneNumber[ RAS_MaxPhoneNumber + 1 ]; DWORD dwAlternateOffset; RASIPADDR ipaddr; RASIPADDR ipaddrDns; RASIPADDR ipaddrDnsAlt; RASIPADDR ipaddrWins; RASIPADDR ipaddrWinsAlt; DWORD dwFrameSize; DWORD dwfNetProtocols; DWORD dwFramingProtocol; TCHAR szScript[ MAX_PATH ]; TCHAR szAutodialDll[ MAX_PATH ]; TCHAR szAutodialFunc[ MAX_PATH ]; TCHAR szDeviceType[ RAS_MaxDeviceType + 1 ]; TCHAR szDeviceName[ RAS_MaxDeviceName + 1 ]; TCHAR szX25PadType[ RAS_MaxPadType + 1 ]; TCHAR szX25Address[ RAS_MaxX25Address + 1 ]; TCHAR szX25Facilities[ RAS_MaxFacilities + 1 ]; TCHAR szX25UserData[ RAS_MaxUserData + 1 ]; DWORD dwChannels; DWORD dwReserved1; DWORD dwReserved2; DWORD dwSubEntries; DWORD dwDialMode; DWORD dwDialExtraPercent; DWORD dwDialExtraSampleSeconds; DWORD dwHangUpExtraPercent; DWORD dwHangUpExtraSampleSeconds; DWORD dwIdleDisconnectSeconds; )) || die "Can't create RASENTRY struct"; $rasentry = Win32::API::Struct->New( 'RASENTRY' ); $rasentry->{dwSize} = (Win32::API::Struct::sizeof($rasentry)); $rasentry->{dwfOptions} = $RASOPTIONS; $rasentry->{dwCountryID} = 0; $rasentry->{dwCountryCode} = 0; $rasentry->{szAreaCode} = ""; $rasentry->{szLocalPhoneNumber} = "3910895"; $rasentry->{ipaddr} = [0,0,0,0]; $rasentry->{ipaddrDns} = [0,0,0,0]; $rasentry->{ipaddrDnsAlt} = [0,0,0,0]; $rasentry->{ipaddrWins} = [0,0,0,0]; $rasentry->{ipaddrWinsAlt} = [0,0,0,0]; $rasentry->{dwFrameSize} = 0; $rasentry->{dwfNetProtocols} = RASNP_Ip; $rasentry->{dwFramingProtocol} = RASFP_Ppp; $rasentry->{szScript} = ""; $rasentry->{szAutodialDll} = ""; $rasentry->{szAutodialFunc} = ""; $rasentry->{szDeviceType} = "modem"; $rasentry->{szDeviceName} = "Standard 56000 bps V90 Modem"; $rasentry->{szX25PadType} = ""; $rasentry->{szX25Address} = ""; $rasentry->{szX25Facilities} = ""; $rasentry->{szX25UserData} = ""; $rasentry->{dwChannels} = 0; $rasentry->{dwReserved1} = 0; $rasentry->{dwReserved2} = 0; $rasentry->{dwSubEntries} = 0; $rasentry->{dwDialMode} = 0; $rasentry->{dwDialExtraPercent} = 0; $rasentry->{dwDialExtraSampleSeconds}; $rasentry->{dwHangUpExtraPercent} = 0; $rasentry->{dwHangUpExtraSampleSeconds} = 0; $rasentry->{dwIdleDisconnectSeconds} = 0; } elsif (($winvermajor == 5) and ($winverminor == 0)) { print ("hit loop 3\n"); Win32::API::Struct->typedef( 'RASENTRY', qw( DWORD dwSize; DWORD dwfOptions; DWORD dwCountryID; DWORD dwCountryCode; TCHAR szAreaCode[ 10 + 1 ]; TCHAR szLocalPhoneNumber[ 128 + 1 ]; DWORD dwAlternateOffset; RASIPADDR ipaddr; RASIPADDR ipaddrDns; RASIPADDR ipaddrDnsAlt; RASIPADDR ipaddrWins; RASIPADDR ipaddrWinsAlt; DWORD dwFrameSize; DWORD dwfNetProtocols; DWORD dwFramingProtocol; TCHAR szScript[ 260 ]; TCHAR szAutodialDll[ 260 ]; TCHAR szAutodialFunc[ 260 ]; TCHAR szDeviceType[ 16 + 1 ]; TCHAR szDeviceName[ 128 + 1 ]; TCHAR szX25PadType[ 32 + 1 ]; TCHAR szX25Address[ 200 + 1 ]; TCHAR szX25Facilities[ 200 + 1 ]; TCHAR szX25UserData[ 200 + 1 ]; DWORD dwChannels; DWORD dwReserved1; DWORD dwReserved2; DWORD dwSubEntries; DWORD dwDialMode; DWORD dwDialExtraPercent; DWORD dwDialExtraSampleSeconds; DWORD dwHangUpExtraPercent; DWORD dwHangUpExtraSampleSeconds; DWORD dwIdleDisconnectSeconds; DWORD dwType; DWORD dwEncryptionType; DWORD dwCustomAuthKey; GUID guidId; TCHAR szCustomDialDll[260]; DWORD dwVpnStrategy; )) || die "can't create RASENTRY struct"; $rasentry = Win32::API::Struct->new( 'RASENTRY' ); $rasentry->{dwSize} = (Win32::API::Struct::sizeof($rasentry) +); $rasentry->{dwfOptions} = $RASOPTIONS; # $rasentry->{dwCountryID} = 0; # $rasentry->{dwCountryCode} = 0; # $rasentry->{szAreaCode} = ""; $rasentry->{szLocalPhoneNumber} = "3910895"; # $rasentry->{ipaddr} = [0,0,0,0]; # $rasentry->{ipaddrDns} = [0,0,0,0]; # $rasentry->{ipaddrDnsAlt} = [0,0,0,0]; # $rasentry->{ipaddrWins} = [0,0,0,0]; # $rasentry->{ipaddrWinsAlt} = [0,0,0,0]; # $rasentry->{dwFrameSize} = 0; $rasentry->{dwfNetProtocols} = RASNP_Ip; $rasentry->{dwFramingProtocol} = RASFP_Ppp; # $rasentry->{szScript} = ""; # $rasentry->{szAutodialDll} = ""; # $rasentry->{szAutodialFunc} = ""; $rasentry->{szDeviceType} = "RASDT_Modem"; $rasentry->{szDeviceName} = "Standard 56000 bps V90 Modem"; # $rasentry->{szX25PadType} = ""; # $rasentry->{szX25Address} = ""; # $rasentry->{szX25Facilities} = ""; # $rasentry->{szX25UserData} = ""; # $rasentry->{dwChannels} = 0; # $rasentry->{dwReserved1} = 0; # $rasentry->{dwReserved2} = 0; # $rasentry->{dwSubEntries} = 0; # $rasentry->{dwDialMode} = 0; # $rasentry->{dwDialExtraPercent} = 0; # $rasentry->{dwDialExtraSampleSeconds}; # $rasentry->{dwHangUpExtraPercent} = 0; # $rasentry->{dwHangUpExtraSampleSeconds} = 0; # $rasentry->{dwIdleDisconnectSeconds} = 0; $rasentry->{dwType} = RASET_Phone; # $rasentry->{dwEncryptionType} = 0; # $rasentry->{dwCustomAuthKey} = 0; # $rasentry->{guidID} = 0; # $rasentry->{szCustomDialDll} = ""; # $rasentry->{dwVpnStrategy} = 0; } elsif (($winvermajor == 5) and ($winverminor > 0)) { print ("hit loop 4\n"); Win32::API::Struct->typedef( 'RASENTRY', qw( DWORD dwSize; DWORD dwfOptions; DWORD dwCountryID; DWORD dwCountryCode; TCHAR szAreaCode[ RAS_MaxAreaCode + 1 ]; TCHAR szLocalPhoneNumber[ RAS_MaxPhoneNumber + 1 ]; DWORD dwAlternateOffset; RASIPADDR ipaddr; RASIPADDR ipaddrDns; RASIPADDR ipaddrDnsAlt; RASIPADDR ipaddrWins; RASIPADDR ipaddrWinsAlt; DWORD dwFrameSize; DWORD dwfNetProtocols; DWORD dwFramingProtocol; TCHAR szScript[ MAX_PATH ]; TCHAR szAutodialDll[ MAX_PATH ]; TCHAR szAutodialFunc[ MAX_PATH ]; TCHAR szDeviceType[ RAS_MaxDeviceType + 1 ]; TCHAR szDeviceName[ RAS_MaxDeviceName + 1 ]; TCHAR szX25PadType[ RAS_MaxPadType + 1 ]; TCHAR szX25Address[ RAS_MaxX25Address + 1 ]; TCHAR szX25Facilities[ RAS_MaxFacilities + 1 ]; TCHAR szX25UserData[ RAS_MaxUserData + 1 ]; DWORD dwChannels; DWORD dwReserved1; DWORD dwReserved2; DWORD dwSubEntries; DWORD dwDialMode; DWORD dwDialExtraPercent; DWORD dwDialExtraSampleSeconds; DWORD dwHangUpExtraPercent; DWORD dwHangUpExtraSampleSeconds; DWORD dwIdleDisconnectSeconds; DWORD dwType; DWORD dwEncryptionType; DWORD dwCustomAuthKey; GUID guidId; TCHAR szCustomDialDll[MAX_PATH]; DWORD dwVpnStrategy; DWORD dwfOptions2; DWORD dwfOptions3; TCHAR szDnsSuffix[RAS_MaxDnsSuffix]; DWORD dwTcpWindowSize; TCHAR szPrerequisitePbk[MAX_PATH]; TCHAR szPrerequisiteEntry[RAS_MaxEntryName + 1]; DWORD dwRedialCount; DWORD dwRedialPause; )) || die "Can't create RASENTRY struct"; $rasentry = Win32::API::Struct->New( 'RASENTRY' ); $rasentry->{dwSize} = (Win32::API::Struct::sizeof($rasent +ry)); $rasentry->{dwfOptions} = $RASOPTIONS; $rasentry->{dwCountryID} = 0; $rasentry->{dwCountryCode} = 0; $rasentry->{szAreaCode} = ""; $rasentry->{szLocalPhoneNumber} = "3910895"; $rasentry->{ipaddr} = [0,0,0,0]; $rasentry->{ipaddrDns} = [0,0,0,0]; $rasentry->{ipaddrDnsAlt} = [0,0,0,0]; $rasentry->{ipaddrWins} = [0,0,0,0]; $rasentry->{ipaddrWinsAlt} = [0,0,0,0]; $rasentry->{dwFrameSize} = 0; $rasentry->{dwfNetProtocols} = RASNP_Ip; $rasentry->{dwFramingProtocol} = RASFP_Ppp; $rasentry->{szScript} = ""; $rasentry->{szAutodialDll} = ""; $rasentry->{szAutodialFunc} = ""; $rasentry->{szDeviceType} = "modem"; $rasentry->{szDeviceName} = "Standard 56000 bps V90 Modem +"; $rasentry->{szX25PadType} = ""; $rasentry->{szX25Address} = ""; $rasentry->{szX25Facilities} = ""; $rasentry->{szX25UserData} = ""; $rasentry->{dwChannels} = 0; $rasentry->{dwReserved1} = 0; $rasentry->{dwReserved2} = 0; $rasentry->{dwSubEntries} = 0; $rasentry->{dwDialMode} = 0; $rasentry->{dwDialExtraPercent} = 0; $rasentry->{dwDialExtraSampleSeconds}; $rasentry->{dwHangUpExtraPercent} = 0; $rasentry->{dwHangUpExtraSampleSeconds} = 0; $rasentry->{dwIdleDisconnectSeconds} = 0; $rasentry->{dwType} = 0; $rasentry->{dwEncryptionType} = 0; $rasentry->{dwCustomAuthKey} = 0; $rasentry->{guidID} = 0; $rasentry->{szCustomDialDll} = ""; $rasentry->{dwVpnStrategy} = 0; $rasentry->{dwfOptions2} = 0; $rasentry->{dwfOptions3} = 0; $rasentry->{szDnsSuffix} = ""; $rasentry->{dwTcpWindowSize} = 0; $rasentry->{szPrerequisitePbk} = ""; $rasentry->{szPrerequisiteEntry} = ""; $rasentry->{dwRedialCount} = 0; $rasentry->{dwRedialPause} = 0; } else { die "Can't setup RASENTRY struct. Can't find approp +riate OS version.\n"}; $Phonebook = 0; $Entry = "testtest"; $ret = RasSetEntryProperties( $Phonebook, $Entry, $rasentry, (Win32::A +PI::Struct::sizeof($rasentry), 0, 0); print ($ret); exit;
In reply to help with Win32::API (Struct and general) by mabman
| For: | Use: | ||
| & | & | ||
| < | < | ||
| > | > | ||
| [ | [ | ||
| ] | ] |