Results 1 to 10 of 10

Thread: [RESOLVED] Convert RAS APIs from ANSI to Unicode

  1. #1

    Thread Starter
    Fanatic Member Mith's Avatar
    Join Date
    Jul 2017
    Location
    Thailand
    Posts
    540

    Resolved [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:

    Name:  Screenshot - 09.08.2021 , 14_24_05.png
Views: 465
Size:  4.2 KB

    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:

    Name:  Screenshot - 09.08.2021 , 14_37_09.jpg
Views: 413
Size:  18.2 KB

    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.
    Attached Files Attached Files
    Last edited by Mith; Aug 9th, 2021 at 04:16 AM. Reason: new infos, project update

  2. #2

    Thread Starter
    Fanatic Member Mith's Avatar
    Join Date
    Jul 2017
    Location
    Thailand
    Posts
    540

    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.

  3. #3
    PowerPoster wqweto's Avatar
    Join Date
    May 2011
    Location
    Sofia, Bulgaria
    Posts
    6,167

    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>

  4. #4

    Thread Starter
    Fanatic Member Mith's Avatar
    Join Date
    Jul 2017
    Location
    Thailand
    Posts
    540

    Re: Convert RAS APIs from ANSI to Unicode

    Quote Originally Posted by wqweto View Post
    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

  5. #5

    Thread Starter
    Fanatic Member Mith's Avatar
    Join Date
    Jul 2017
    Location
    Thailand
    Posts
    540

    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?

  6. #6
    PowerPoster wqweto's Avatar
    Join Date
    May 2011
    Location
    Sofia, Bulgaria
    Posts
    6,167

    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>

  7. #7

    Thread Starter
    Fanatic Member Mith's Avatar
    Join Date
    Jul 2017
    Location
    Thailand
    Posts
    540

    Re: Convert RAS APIs from ANSI to Unicode

    Quote Originally Posted by wqweto View Post
    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?

  8. #8
    PowerPoster wqweto's Avatar
    Join Date
    May 2011
    Location
    Sofia, Bulgaria
    Posts
    6,167

    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>

  9. #9

    Thread Starter
    Fanatic Member Mith's Avatar
    Join Date
    Jul 2017
    Location
    Thailand
    Posts
    540

    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!

  10. #10
    PowerPoster wqweto's Avatar
    Join Date
    May 2011
    Location
    Sofia, Bulgaria
    Posts
    6,167

    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>

Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width