3 Attachment(s)
[RESOLVED] Convert RAS APIs from ANSI to Unicode
hi,
i need to to convert the following RAS APIs from ANSI (A) to the Unicode (W) version:
Code:
RasEnumEntries (done!)
RasEnumConnections (done!)
RasDial
RasGetEntryDialParams (not needed anymore)
RasHangUp (done!)
Does anyone already converted these APIs to Unicode?
Im already converted "RasEnumEntries" and it works now with VPN connections with unicode characters in the name:
Attachment 182035
I also converted "RasEnumConnections" and "RasHangUp" to close a connection.
Now i need some help with "RasDial"...
I have attached a example project to play around with the APIs & declarations:
Attachment 182036
The "ANSI"-buttons are using the ANSI version of the APIs and they are all working.
You can connect/disonnect and check the status of a connection.
The "UNICODE"-buttons are using the UNICODE version of the APIs.
Re: Convert RAS APIs from ANSI to Unicode
i found the correct size for the RASCONN95_W structure with this code:
Code:
For I = 412 To 999
lpRasconn(0).dwSize = I
lpCb = lpRasconn(0).dwSize * 256
lErr = RasEnumConnectionsWide(lpRasconn(0), lpCb, lConnections)
If lErr = 0 Then Stop
Next I
The correct size is 816.
Re: Convert RAS APIs from ANSI to Unicode
JFYI, here is the struct definition in the SDK
Code:
/* Identifies an active RAS connection. (See RasEnumConnections)
*/
#define RASCONNW struct tagRASCONNW
RASCONNW
{
DWORD dwSize;
HRASCONN hrasconn;
WCHAR szEntryName[ RAS_MaxEntryName + 1 ];
#if (WINVER >= 0x400)
WCHAR szDeviceType[ RAS_MaxDeviceType + 1 ];
WCHAR szDeviceName[ RAS_MaxDeviceName + 1 ];
#endif
#if (WINVER >= 0x401)
WCHAR szPhonebook [ MAX_PATH ];
DWORD dwSubEntry;
#endif
#if (WINVER >= 0x500)
GUID guidEntry;
#endif
#if (WINVER >= 0x501)
DWORD dwFlags;
LUID luid;
#endif
#if (WINVER >= 0x600)
GUID guidCorrelationId;
#endif
};
. . . which can be trimmed down to match your VB6 declare to something like this
Code:
#define RASCONN95 struct tagRASCONN95
RASCONN95
{
DWORD dwSize;
HRASCONN hrasconn;
WCHAR szEntryName[ RAS_MaxEntryName + 1 ];
#if (WINVER >= 0x400)
WCHAR szDeviceType[ RAS_MaxDeviceType + 1 ];
WCHAR szDeviceName[ RAS_MaxDeviceName + 1 ];
#endif
};
. . . and then using some code like this
Code:
printf("sizeof(RASCONN95)=%d\n", sizeof(RASCONN95));
. . . delivers another value
Code:
sizeof(RASCONN95)=814
cheers,
</wqw>
Re: Convert RAS APIs from ANSI to Unicode
Quote:
Originally Posted by
wqweto
J
Code:
printf("sizeof(RASCONN95)=%d\n", sizeof(RASCONN95));
. . . delivers another value
Code:
sizeof(RASCONN95)=814
cheers,
</wqw>
Strange, the API RasEnumConnectionsWide works only with a size of 816...see my post #2
Re: Convert RAS APIs from ANSI to Unicode
btw, i simplified the ANSI-function to dial the connection.
now i use the type structure RASDIALPARAMS directly with the API RasDial:
Code:
Private Const RAS_MaxEntryName = 256
Private Const RAS_MaxPhoneNumber = 128
Private Const RAS_MaxCallbackNumber = RAS_MaxPhoneNumber
Private Const UNLEN = 256
Private Const PWLEN = 256
Private Const DNLEN = 12
Private Type RASDIALPARAMS
dwSize As Long
szEntryName(RAS_MaxEntryName) As Byte
szPhoneNumber(RAS_MaxPhoneNumber) As Byte
szCallbackNumber(RAS_MaxCallbackNumber) As Byte
szUserName(UNLEN) As Byte
szPassword(PWLEN) As Byte
szDomain(DNLEN) As Byte
End Type
Private Declare Function RasDial Lib "rasapi32.dll" Alias "RasDialA" _
(lpRasDialExtensions As Any, _
ByVal lpszPhonebook As String, _
lpRasDialParams As Any, _
ByVal dwNotifierType As Long, _
ByVal hwndNotifier As Long, _
lphRasConn As Long) As Long
Private Sub RAS_Connect()
Dim lErr As Long
Dim lngHConn As Long
Dim sConnectionName As String
Dim rp As RASDIALPARAMS
sConnectionName = cboRAS.List(cboRAS.ListIndex)
CopyStringToByte rp.szEntryName(0), sConnectionName, Len(sConnectionName)
rp.dwSize = Len(rp) + 6 '1052
lErr = RasDial(ByVal 0&, vbNullString, rp, 0&, 0&, lngHConn)
If lErr <> 0 Then
MsgBox "RasDial: " & GetRasErrorMsg(lErr), vbExclamation
Exit Sub
Else
MsgBox "'" & sConnectionName & "' connected!", vbInformation
End If
End Sub
i tried to convert the code above to UNICODE but the API RasDialWide always returns 632 "ERROR_INVALID_SIZE":
Code:
Private Type RASDIALPARAMS_W
dwSize As Long
szEntryName(RAS_MaxEntryName * 2) As Byte
szPhoneNumber(RAS_MaxPhoneNumber * 2) As Byte
szCallbackNumber(RAS_MaxCallbackNumber * 2) As Byte
szUserName(UNLEN * 2) As Byte
szPassword(PWLEN * 2) As Byte
szDomain(DNLEN * 2) As Byte
End Type
Private Declare Function RasDialWide Lib "rasapi32.dll" Alias "RasDialW" _
(lpRasDialExtensions As Any, _
ByVal lpszPhonebook As Long, _
lpRasDialParams As Any, _
ByVal dwNotifierType As Long, _
ByVal hwndNotifier As Long, _
lphRasConn As Long) As Long
Private Sub RAS_Connect_UNICODE()
Dim lErr As Long
Dim lngHConn As Long
Dim sConnectionName As String
Dim rp As RASDIALPARAMS_W
Dim I As Long
sConnectionName = cboRAS.List(cboRAS.ListIndex)
CopyStringToByte rp.szEntryName(0), sConnectionName, Len(sConnectionName)
rp.dwSize = LenB(rp) + 6 '1052
lErr = RasDialWide(ByVal 0&, StrPtr(vbNullString), rp, 0&, 0&, lngHConn)
If lErr <> 0 Then
MsgBox "RasDial: " & GetRasErrorMsg(lErr), vbExclamation
Exit Sub
Else
MsgBox "'" & sConnectionName & "' connected!", vbInformation
End If
End Sub
I tried to catch the correct size with a For-Next-Loop but i dont get the correct size:
Code:
For I = 500 To 4000
rp.dwSize = I
lErr = RasDialWide(ByVal 0&, StrPtr(vbNullString), rp, 0&, 0&, lngHConn)
If lErr = 0 Then Stop
Next I
Maybe the type structure is wrong or the API declaration?
Re: Convert RAS APIs from ANSI to Unicode
Your string buffers sizes are off-by-one -- should be sized to RAS_MaxEntryName + 1, RAS_MaxDeviceType + 1 and RAS_MaxDeviceName + 1 to match array sizes in SDK struct.
Here is a somewhat more convenient fixed-string equivalent of the UDT in VB6
Code:
Private Type RASCONN95_W
dwSize As Long
hRasConn As Long
szEntryName As String * 257 ' (RAS_MaxEntryName+1)
szDeviceType As String * 17 ' (RAS_MaxDeviceType+1)
szDeviceName As String * 129 ' (RAS_MaxDeviceName+1)
End Type
This way LenB(RASCONN95_W) = 816 in VB6 which is correct because it is 814 from above C/C++ code *padded* to DWORD boundary. Btw, C/C++ is using padded size for array of RASCONN95_W too.
The only thing to heed is that you have to use ByVal VarPtr at callsite to prevent Unicode<->ANSI converstion with fixed-length strings, so the original code should work now
Code:
lpRasconn(0).dwSize = LenB(lpRasconn(0)) '=816
lpCb = lpRasconn(0).dwSize * (UBound(lpRasconn) + 1) '=816*256=208896
lErr = RasEnumConnectionsWide(ByVal VarPtr(lpRasconn(0)), lpCb, lConnections)
Not tested as I don't have any RAS (dial-up/VPN) connections setup.
cheers,
</wqw>
Re: Convert RAS APIs from ANSI to Unicode
Quote:
Originally Posted by
wqweto
Your string buffers sizes are off-by-one -- should be sized to RAS_MaxEntryName + 1, RAS_MaxDeviceType + 1 and RAS_MaxDeviceName + 1 to match array sizes in SDK struct.
No need for "+1". I don't use strings at the type struct:
Code:
Private Type RASCONN95
dwSize As Long
hRasConn As Long
szEntryName(RAS_MaxEntryName) As Byte
szDeviceType(RAS_MaxDeviceType) As Byte
szDeviceName(RAS_MaxDeviceName) As Byte
End Type
The ANSI & UNICODE version of RasEnumConnections already works fine!
I have problems to convert the ANSI Type RASDIALPARAMS and the API RasDial:
Code:
Private Type RASDIALPARAMS
dwSize As Long
szEntryName(RAS_MaxEntryName) As Byte
szPhoneNumber(RAS_MaxPhoneNumber) As Byte
szCallbackNumber(RAS_MaxCallbackNumber) As Byte
szUserName(UNLEN) As Byte
szPassword(PWLEN) As Byte
szDomain(DNLEN) As Byte
End Type
Private Declare Function RasDial Lib "rasapi32.dll" Alias "RasDialA" _
(lpRasDialExtensions As Any, _
ByVal lpszPhonebook As String, _
lpRasDialParams As Any, _
ByVal dwNotifierType As Long, _
ByVal hwndNotifier As Long, _
lphRasConn As Long) As Long
My unicode version looks like this:
Code:
Private Type RASDIALPARAMS_W
dwSize As Long
szEntryName(RAS_MaxEntryName * 2) As Byte
szPhoneNumber(RAS_MaxPhoneNumber * 2) As Byte
szCallbackNumber(RAS_MaxCallbackNumber * 2) As Byte
szUserName(UNLEN * 2) As Byte
szPassword(PWLEN * 2) As Byte
szDomain(DNLEN * 2) As Byte
End Type
Private Declare Function RasDialWide Lib "rasapi32.dll" Alias "RasDialW" _
(lpRasDialExtensions As Any, _
ByVal lpszPhonebook As Long, _
lpRasDialParams As Any, _
ByVal dwNotifierType As Long, _
ByVal hwndNotifier As Long, _
lphRasConn As Long) As Long
Calling the API RasDialWide always returns the error 632 "ERROR_INVALID_SIZE" and i dont know whats wrong: the API declaration? the struct declaration? or the calculated size for the struct?
Re: Convert RAS APIs from ANSI to Unicode
Here is the RASDIALPARAMSW
Code:
/* Describes connection establishment parameters. (See RasDial)
*/
#define RASDIALPARAMSW struct tagRASDIALPARAMSW
RASDIALPARAMSW
{
DWORD dwSize;
WCHAR szEntryName[ RAS_MaxEntryName + 1 ];
WCHAR szPhoneNumber[ RAS_MaxPhoneNumber + 1 ];
WCHAR szCallbackNumber[ RAS_MaxCallbackNumber + 1 ];
WCHAR szUserName[ UNLEN + 1 ];
WCHAR szPassword[ PWLEN + 1 ];
WCHAR szDomain[ DNLEN + 1 ];
#if (WINVER >= 0x401)
DWORD dwSubEntry;
ULONG_PTR dwCallbackId;
#endif
#if (WINVER >= 0x601)
DWORD dwIfIndex;
#endif
#if (WINVER >= 0x602)
LPWSTR szEncPassword;
#endif
};
You cannot just leave the arrays in VB6 type with smaller sizes. You have to declare these with correct size i.e. szEntryName(RAS_MaxEntryName * 2 + 2) As Byte, etc.
Btw, C/C++ compiled code against Windows SDK gives this
Code:
sizeof(RASDIALPARAMS95)=2094
cheers,
</wqw>
Re: Convert RAS APIs from ANSI to Unicode
i got it now!
the correct type declaration is:
Code:
Private Type RASDIALPARAMS_W
dwSize As Long
szEntryName(RAS_MaxEntryName * 2 + 1) As Byte
szPhoneNumber(RAS_MaxPhoneNumber * 2 + 1) As Byte
szCallbackNumber(RAS_MaxCallbackNumber * 2 + 1) As Byte
szUserName(UNLEN * 2 + 1) As Byte
szPassword(PWLEN * 2 + 1) As Byte
szDomain(DNLEN * 2 + 1) As Byte
End Type
i only need +1 because the Array starts with Zero!
...and the correct size for the API call is 2096 !
Now everything works!
Thanks you for your help to point me in the right direction!
Re: Convert RAS APIs from ANSI to Unicode
My bad! Arrays in VB6 should be dimensionsed 0 to Size - 1 -- doh!
Final 2096 size must be 2094 with DWORD padding.
cheers,
</wqw>