RAS Revisited

T

Tibby

I've gotten RAS to work with a C++ dll, but due to my limited
knowledge of C++, I'm running into some memory problems. So, I'm
giving this another shot using VB.NET, since I have a greater
understanding of how the RAS API actually works, and a greater
appreciation for it.

Anyway, I'm stuck on the RasDial function, which is returning error
632, "The Structure Size is incorrect". Now, here' s the C++
Prototype of the RasDialParams Structure:

typedef struct _RASDIALPARAMS {
DWORD dwSize;
TCHAR szEntryName[RAS_MaxEntryName + 1];
TCHAR szPhoneNumber[RAS_MaxPhoneNumber + 1];
TCHAR szCallbackNumber[RAS_MaxCallbackNumber + 1];
TCHAR szUserName[UNLEN + 1];
TCHAR szPassword[PWLEN + 1];
TCHAR szDomain[DNLEN + 1] ;
#if (WINVER >= 0x401)
DWORD dwSubEntry;
ULONG_PTR dwCallbackId;
#endif
} RASDIALPARAMS;

Here's my decleration of the structure:

<StructLayout(LayoutKind.Sequential, CharSet:=CharSet.Auto)> _
Public Structure RASDIALPARAMS
Public dwSize As Int32
Public szEntryName As String
Public szPhoneNumber As String
Public szCallbackNumber As String
Public szUserName As String
Public szPassword As String
Public szDomain As String
Public swSubEntry As Int32
Public dwCallbackId As Int32
End Structure

And here's the C++ way of setting/defining the structure:

rdParams.dwSize = sizeof(RASDIALPARAMS);
rdParams.szEntryName[0]= '\0';
rdParams.szCallbackNumber[0] = '\0';
rdParams.szPhoneNumber[0]= '\0';
rdParams.szUserName[0]= '\0';
rdParams.szPassword[0]= '\0';
rdParams.szDomain[0] = '\0';

and here's mine:

With rdParams
.dwSize = Marshal.SizeOf(rdParams)
.szEntryName = Nothing
.szCallbackNumber = Nothing
.szDomain = Nothing
.szPhoneNumber = PhoneNumber
.szPassword = Password
.szUserName = userName
End With

So, how do I get mine to not return the error 632? I've have searched
hihg and low for this, and can't seem to figure it out, and here, if
this helps, I have a C# decleration of the structure, and before
anyone comments, Loederz .Net Reflector is out of the question, the
zip file is goofed.

[StructLayout(LayoutKind.Sequential,CharSet=CharSet.Auto)]
internal class RASDIALPARAMS
{
public int
dwSize=Marshal.SizeOf(typeof(RASDIALPARAMS));

[MarshalAs(UnmanagedType.ByValTStr,SizeConst=(int)RasFieldSizeConstants.RAS_MaxEntryName+1)]
public string szEntryName=null;

[MarshalAs(UnmanagedType.ByValTStr,SizeConst=(int)RasFieldSizeConstants.RAS_MaxPhoneNumber+1)]
public string szPhoneNumber=null;

[MarshalAs(UnmanagedType.ByValTStr,SizeConst=(int)RasFieldSizeConstants.RAS_MaxCallbackNumber+1)]
public string szCallbackNumber=null;

[MarshalAs(UnmanagedType.ByValTStr,SizeConst=(int)RasFieldSizeConstants.UNLEN+1)]
public string szUserName=null;

[MarshalAs(UnmanagedType.ByValTStr,SizeConst=(int)RasFieldSizeConstants.PWLEN+1)]
public string szPassword=null;

[MarshalAs(UnmanagedType.ByValTStr,SizeConst=(int)RasFieldSizeConstants.DNLEN+1)]
public string szDomain=null;
public int dwSubEntry=0;
public int dwCallbackId=0;
}

And here the Constants to go with it:

internal enum RasFieldSizeConstants
{
RAS_MaxDeviceType =16,
RAS_MaxPhoneNumber =128,
RAS_MaxIpAddress =15,
RAS_MaxIpxAddress =21,
#if WINVER4
RAS_MaxEntryName =256,
RAS_MaxDeviceName =128,
RAS_MaxCallbackNumber =RAS_MaxPhoneNumber,
#else
RAS_MaxEntryName =20,
RAS_MaxDeviceName =32,
RAS_MaxCallbackNumber =48,
#endif

RAS_MaxAreaCode =10,
RAS_MaxPadType =32,
RAS_MaxX25Address =200,
RAS_MaxFacilities =200,
RAS_MaxUserData =200,
RAS_MaxReplyMessage =1024,
RAS_MaxDnsSuffix =256,
UNLEN =256,
PWLEN =256,
DNLEN =15
}

Now, i;ve noticed it's declared here as a class, and I'm wondering if
I do the same in VB will it work correctly?

Here's my modified Code:

<StructLayout(LayoutKind.Sequential, CharSet:=CharSet.Auto)> _
Public Class RASDIALPARAMS
Public dwSize As Int32
<MarshalAs(UnmanagedType.ByValTStr, _
SizeConst:=CInt(RasFieldSizeConstants.RAS_MaxEntryName) + 1)>
_
Public szEntryName As String = Nothing
<MarshalAs(UnmanagedType.ByValTStr, _
SizeConst:=CInt(RasFieldSizeConstants.RAS_MaxPhoneNumber) +
1)> _
Public szPhoneNumber As String = Nothing
<MarshalAs(UnmanagedType.ByValTStr, _
SizeConst:=CInt(RasFieldSizeConstants.RAS_MaxCallbackNumber) +
1)> _
Public szCallbackNumber As String = Nothing
<MarshalAs(UnmanagedType.ByValTStr, _
SizeConst:=CInt(RasFieldSizeConstants.UNLEN) + 1)> _
Public szUserName As String = Nothing
<MarshalAs(UnmanagedType.ByValTStr, _
SizeConst:=CInt(RasFieldSizeConstants.PWLEN) + 1)> _
Public szPassword As String = Nothing
<MarshalAs(UnmanagedType.ByValTStr, _
SizeConst:=CInt(RasFieldSizeConstants.DNLEN) + 1)> _
Public szDomain As String = Nothing
Public swSubEntry As Int32 = 0
Public dwCallbackId As Int32 = 0
End Class

Nope, it returns error code 87. Very strange indeed, so, let me
layout some more code and prototypes for you...

I've included the above enum of constants, FYI
Prototype for RasDial in C++:

DWORD RasDial(
LPRASDIALEXTENSIONS lpRasDialExtensions,
// pointer to function extensions data
LPCTSTR lpszPhonebook, // pointer to full path and file
// name of phone-book file
LPRASDIALPARAMS lpRasDialParams,
// pointer to calling parameters data
DWORD dwNotifierType, // specifies type of RasDial event handler
LPVOID lpvNotifier, // specifies a handler for RasDial events
LPHRASCONN lphRasConn // pointer to variable to receive
// connection handle
);

My P/invoke Declare:

<DllImport("rasapi32.dll")> Public Shared Function RasDial(ByVal
lpRasDialExtensions As IntPtr, ByVal lpszPhonebook As IntPtr, ByRef
lpRasDialParams As RASDIALPARAMS, ByVal dwNotifierType As Int32, ByVal
lpvNotifier As Object, ByRef lphRasConn As IntPtr) As Int32
End Function

Now, I have a delegate for lpvNotifier Callback, which is for
RasDialFunc1:

Public Delegate Sub RasDialFunc1(ByVal hrasconn As IntPtr, ByVal
unMsg As UInt32, ByVal rascs As RASCONNSTATE, ByVal dwError As Int32,
ByVal dwExtendedError As Int32)

And here's my calling of RasDial:
Dim retval As Int32 = RasDial(IntPtr.Zero, IntPtr.Zero, rdParams, 1,
New RasDialFunc1(AddressOf CallBack), Handle)

And Retval always returns 87 with the modified code, guess I got the
SizeOf structure crap figured out.

Now, in looking up RAS Error 87 on google, here's what I found:

A function call to the RasDial() API from a 16-bit Windows-based
application that is running
in Windows 95 fails with error 87 in Windows 95 if the
hWndNotifier parameter of the RasDial()
API is initialized to a NULL value. An application should always
provide a window handle for
this parameter even if it will not be processing the messages
posted by the RAS DLLs to this
window. Specifying a NULL value for window handle in the
RasDial() API call is common for a
Visual Basic application. In such a scenario, the application
makes repetitive calls to
RasGetConnectStatus() to get the status of the connection.
However, calling RasDial() in this
fashion causes it to fail on Windows 95 with error 87. Microsoft
has confirmed this to be a bug
in the Microsoft products listed at the beginning of this
article. Microsoft is researching this
problem and will post new information in the Microsoft Knowledge
Base as it becomes available.
Doesn't make too much sense to me since I'm developing this for
2000/XP, but, after a little more searching, nothing even close. So,
I'm at an impass, and after all this babbling, maybe a bone could be
thrown my way, and god knows I'm not the only person out here that
could use this code :)

Thanks again,
Tibby
 
A

Andrew Baker

I found this on the Internet and made it work for VB. Works fine.



Andrew

----------------------------------------------------------------------------
-----------------------------------

Imports System

Imports System.Runtime.InteropServices





Public Class RASDialup

Private Declare Auto Function InternetDial Lib "wininet" _

(ByVal hwndParent As IntPtr, _

ByVal lpszConnection As String, _

ByVal dwFlags As Integer, _

ByRef lpdwConnection As Integer, _

ByVal dwReserved As Integer) As Integer



Public Declare Auto Function InternetHangUp Lib "wininet.dll" (ByVal
lpdwConnection As Integer, ByVal dwReserved As Long) As Integer



Public Enum DialUpOptions

INTERNET_AUTODIAL_FORCE_ONLINE = &H1

INTERNET_AUTODIAL_FORCE_UNATTENDED = &H2

INTERNET_DIAL_FORCE_PROMPT = &H2000

INTERNET_DIAL_SHOW_OFFLINE = &H4000

INTERNET_DIAL_UNATTENDED = &H8000

End Enum 'DialUpOptions

'INTERNET_AUTODIAL_FORCE_ONLINE Forces an online connection.

'

'INTERNET_AUTODIAL_FORCE_UNATTENDED Forces an unattended Internet dial-up.
If

'user intervention is required, the function will fail.

'

'INTERNET_DIAL_FORCE_PROMPT Ignores the "dial automatically" setting and

'forces the dialing user interface to be displayed.

'

'INTERNET_DIAL_UNATTENDED Connects to the Internet through a modem, without

'displaying a user interface, if possible. Otherwise, the function will wait

'for user input.

'

'INTERNET_DIAL_SHOW_OFFLINE

'

Private m_connectionnumber As Integer



Public ReadOnly Property ConnectionNumber() As Integer

Get

Return m_connectionnumber

End Get

End Property



Public Function Connect(ByVal m_ConnectionName As String) As Integer

Dim retVal As Integer

retVal = InternetDial(IntPtr.Zero, m_ConnectionName, &H8000,
m_connectionnumber, 0)

Return retVal

End Function 'Connect



Public Sub Disconnect()



InternetHangUp(m_connectionnumber, 0)

End Sub 'Disconnect

End Class 'RASDialup
 
T

Tibby

<SNIP>

I've had issues with the wininet.dll in the past, using it for other
functionality, that's why I'm wanting to stick with the low-level
RASAPI32 functions, which is what wininet.dll wraps, oddly enough.

I will try the code again though, definatly want to check the
stability of it.

Thanks,
Tibby
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top