The RASEnumEntries function will return a list of all dial up networking entries. From the PlatformSDK, the function is declared as follows:
Declare Function RasEnumEntries _ Lib "rasapi32.dll" Alias "RasEnumEntriesA" ( _ ByVal lpStrNull As String, _ ByVal lpszPhonebook As String, _ lprasentryname As RASENTRYNAME, _ lpCb As Long, _ lpCEntries As Long) _ As Long
The RASENTRYNAME structure is different depending on the version of windows. In the Platform SDK the RASENTRYNAME structure is as follows:
typedef struct _RASENTRYNAME { DWORD dwSize; TCHAR szEntryName[RAS_MaxEntryName + 1]; #if (WINVER >= 0x500) DWORD dwFlags; CHAR szPhonebookPath[MAX_PATH + 1]; #endif } RASENTRYNAME;
Note how it has two extra members if the Windows Version is &H500 or greater (win2000). Also the RAS_MaxEntryName constant is different for different platforms. For windows 95/98 and NT4 or later, it's value is 256. For earlier versions of NT it's value is 20. This gives us a possible 3 different sized structures for the RASENTRYNAME structure.
A common approach to this problem is to declare 3 different structures, check the windows version by calling the GetVersionEX() API function, then pass our values to and from the appropriate structure. I call this the SDKtoVB approach. The problem with that approach is it is difficult to update in the future, and the structures themselves are not really VB friendly - strings are stored as fixed length byte arrays , etc.
Another approach, is to start from the VB end and work towards the SDK format. I call this the VBtoSDK approach. The first step in this approach is to define the information we want as we would handle it in VB. For the RASENTRYNAME structure, our VB declaration would be as follows:
Public Type VBRasEntryName entryname As String Win2000_SystemPhonebook As Boolean PhonebookPath As String End Type
In our structure above, note how we have declared the strings as variable length strings (the" VB way") and we have a member called Win2000_SystemPhonebook which will return true if the phonebook is in the AllUsers profile for Windows 2000.
The next step is to find a way to pass our VB structure to the RASAPI32.dll. Well, it really is quite simple. The RASAPI is only looking for a consecutive series of bytes for the structure, so we can use a dynamic byte array to pass to the RASAPI, and use the CopyMemory API to pass values to and from our VB structure to the byte array. The only thing we need to know is the size of the byte array or the size of the structure the RASAPI is expecting. From the definitions in the Ras.h header file, we find the possible sizes for the RASENTRYNAME structure are 528, 264 or 28 bytes (rounded up to the nearest multiple of 4)
Finally we have to work out how to set the appropriate size of our byte array. The RasEnumEntries function performs differently depending on the windows platform. On windows 95/98 it will tell us the appropriate size even if we don't set the first four bytes of our byte array to the appropriate value. It will return an error value of 603 (ERROR_BUFFER_TOO_SMALL) and also return two useful variables to us, being lpCb which is the count of bytes needed to store all the RASENTRYNAMEs , and lpCEntries which is the count of the number of entries. On NT4, we need to set the first four bytes of our byte array to the appropriate value, otherwise it will return an error value of 632 and tell us nothing about the size needed.
This following sample function demonstrates using RASEnumEntries. To use it, you would declare a dynamic array of type VBRasEntryName and pass it to the function VBRasGetAllEntries which would populate the array and return the number of entries as a long. eg:
Dim myEntries() as VBRasEntryName
Dim lngCount as long
lngCount = VBRasGetAllEntries(myEntries)
Note: On NT you can also use the strPhoneBook variable to specify the full path and file name of a phonebook to use. If not specified, the default phonebook is used.
Public Type VBRasEntryName entryname As String Win2000_SystemPhonebook As Boolean PhonebookPath As String End Type Public Declare Function RasEnumEntries _ Lib "rasapi32.dll" Alias "RasEnumEntriesA" _ (ByVal lpStrNull As String, ByVal lpszPhonebook As String, _ lpRasEntryName As Any, lpCb As Long, lpCEntries As Long) As Long Public Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" _ (Destination As Any, Source As Any, ByVal Length As Long) '_____________________________________________________________________ Function VBRasGetAllEntries(clsRasEntryName() As VBRasEntryName, _ Optional strPhoneBook As String) As Long Dim rtn As Long, i As Long Dim lpCb As Long 'count of bytes Dim lpCEntries As Long 'count of entries Dim b() As Byte Dim strTemp As String Dim dwSize As Long 'size of each entry Dim lngLen As Long Dim lngBLen As Variant ReDim b(3) 'determine appropiate size for b() lngBLen = Array(532&, 264&, 28&) For i = 0 To 2 CopyMemory b(0), CLng(lngBLen(i)), 4 rtn = RasEnumEntries(vbNullString, strPhoneBook, _ b(0), lpCb, lpCEntries) If rtn <> 632 Then Exit For Next i VBRasGetAllEntries = lpCEntries If lpCEntries = 0 Then Exit Function dwSize = lpCb \ lpCEntries ReDim b(lpCb - 1) CopyMemory b(0), dwSize, 4 rtn = RasEnumEntries(vbNullString, strPhoneBook, _ b(0), lpCb, lpCEntries) If rtn <> 0 Then MsgBox VBRASErrorHandler(rtn) strTemp = String(dwSize - 4, 0) ReDim clsRasEntryName(lpCEntries - 1) If dwSize = 28 Then lngLen = 21 Else lngLen = 257 For i = 0 To lpCEntries - 1 CopyMemory ByVal strTemp, b((i * dwSize) + 4), lngLen clsRasEntryName(i).entryname = _ Left(strTemp, InStr(strTemp, Chr$(0)) - 1) Next i If dwSize > 264 Then For i = 0 To lpCEntries - 1 CopyMemory clsRasEntryName(i).Win2000_SystemPhonebook, _ b((i * dwSize) + 264), 2& CopyMemory ByVal strTemp, b((i * dwSize) + 268), 260& clsRasEntryName(i).PhonebookPath = _ Left(strTemp, InStr(strTemp, Chr$(0)) - 1) Next i Else For i = 0 To lpCEntries - 1 clsRasEntryName(i).PhonebookPath = strPhoneBook Next i End If End Function
See Also: Contents, Introduction, RasErrorHandler.