< RAS Client, Functions & Modes | RAS Main | VPN & RAS Example >


 

 

Remote Access Service (RAS) 12 Part 2

 

 

What do we have in this chapter 12 part 2?

  1. Phonebook

  2. Adding Phonebook Entries

  3. Deleting Phonebook Entries

  4. Managing User Credentials

  5. Connection Management

 

Phonebook

 

A RAS phonebook is nothing more than a collection of RASENTRY structures (or phonebook entries) that contain phone numbers, data rates, user authentication information, VPN strategies, and other connection information. On Windows 95, Windows 98, Windows Me, and Windows CE systems, the phonebook is stored in the system Registry. On Windows NT systems, the phonebook is stored in files that typically have the file extension .PBK. A RASENTRY structure is defined as:

 

typedef struct tagRASENTRY

{

    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;

#if (WINVER >= 0x401)

    DWORD     dwSubEntries;

    DWORD     dwDialMode;

    DWORD     dwDialExtraPercent;

    DWORD     dwDialExtraSampleSeconds;

    DWORD     dwHangUpExtraPercent;

    DWORD     dwHangUpExtraSampleSeconds;

    DWORD     dwIdleDisconnectSeconds;

#endif

#if (WINVER >= 0x500)

    DWORD     dwType;

    DWORD     dwEncryptionType;

    DWORD     dwCustomAuthKey;

    GUID      guidId;

    TCHAR     szCustomDialDll[MAX_PATH];

    DWORD     dwVpnStrategy;

#endif

#if (WINVER >= 0x501)

                        DWORD     dwfOptions2;

                        DWORD     dwfOptions3;

                        WCHAR     szDnsSuffix[RAS_MaxDnsSuffix];

                        DWORD     dwTcpWindowSize;

                        WCHAR     szPrerequisitePbk[MAX_PATH];

                        WCHAR     szPrerequisiteEntry[RAS_MaxEntryName + 1];

                        DWORD     dwRedialCount;

                        DWORD     dwRedialPause;

#endif

} RASENTRY;

 

As you can see, many fields make up this structure and we will not describe them here. For a complete description of all the fields, consult the Platform SDK.

When you call any RAS API that takes a phonebook file as a parameter (lpszPhonebook), you can identify the path to a phonebook file. As we mentioned earlier, this parameter must be NULL on Windows 95, Windows 98, Windows Me, and Windows CE systems because phonebook entries are stored in the system Registry. On Windows NT systems, this can be a path to a phonebook file. Typically, this phonebook file will have the extension .PBK. Also, the system default phonebook on Windows NT systems is located under %SystemRoot%\System32\Ras\Rasphone.pbk. If you specify NULL as the phonebook, you will use the system default phonebook file. For Windows XP Pro you can find it in the C:\Documents and Settings\All Users\Application Data\Microsoft\Network\Connections\Pbk folder.

 

 

 

 

 

Adding Phonebook Entries

 

RAS provides four functions that allow you to programmatically manage phonebook RASENTRY structures: RasSetEntryProperties(), RasGetEntryProperties(), RasRenameEntry(), and RasDeleteEntry(). You can use the RasSetEntryProperties() function to create a new entry or modify an existing entry. This function is defined as:

 

DWORD RasSetEntryProperties(

    LPCTSTR lpszPhonebook,

    LPCTSTR lpszEntry,

    LPRASENTRY lpRasEntry,

    DWORD dwEntryInfoSize,

    LPBYTE lpbDeviceInfo,

    DWORD dwDeviceInfoSize

);

 

The lpszPhonebook parameter is a pointer to a phonebook file name. The lpszEntry parameter is a pointer to a string used to identify an existing or new entry. If a RASENTRY structure exists with this name, the properties are modified; otherwise, a new entry is created in the phonebook. The lpRasEntry parameter is a pointer to a RASENTRY structure. You can place a list of null-terminated strings after the RASENTRY structure defining alternate phone numbers. The last string is terminated by two consecutive null characters. The dwEntryInfoSize parameter is the size (in bytes) of the structure in the lpRasEntry parameter. The lpbDeviceInfo parameter is a pointer to a buffer that contains TAPI device configuration information. On Windows 2000 and Windows NT, this parameter is not used and should be set to NULL. The final parameter, dwDeviceInfoSize, represents the size (in bytes) of the lpbDeviceInfo buffer.

The RasGetEntryProperties() function, defined below, can be used to retrieve the properties of an existing phonebook entry or the default values for a new phonebook entry.

 

DWORD RasGetEntryProperties(

    LPCTSTR lpszPhonebook,

    LPCTSTR lpszEntry,

    LPRASENTRY lpRasEntry,

    LPDWORD lpdwEntryInfoSize,

    LPBYTE lpbDeviceInfo,

    LPDWORD lpdwDeviceInfoSize

);

 

The lpszPhonebook parameter is a pointer to the name of a phonebook file. The lpszEntry parameter is a pointer to a string identifying an existing phonebook entry. If you set this parameter to NULL, the lpRasEntry and lpbDeviceInfo parameters will receive default values of a phonebook entry. Retrieving the default values is quite useful: when you need to create a new RAS phonebook entry, you can populate the lpRasEntry and lpbDeviceInfo fields with correct information about your system before you call the RasSetEntryProperties() function.

The lpRasEntry parameter is a pointer to a buffer that your application supplies to receive a RASENTRY structure. As we described in our discussion of the RasSetEntryProperties() function, this structure can be followed by an array of null-terminated strings identifying alternate phone numbers for the requested phonebook entry. Therefore, the size of your receiving buffer should be larger than a RASENTRY structure. If you pass a NULL pointer, the lpdwEntryInfoSize parameter will receive the total number of bytes needed to store all the elements of a RASENTRY structure plus any alternate phone numbers. The lpdwEntryInfoSize parameter is a pointer to a DWORD containing the number of bytes that are in the receiving buffer your application supplies to the lpRasEntry parameter. When this function completes, it will update lpdwEntryInfoSize to the number of bytes actually received in lpRasEntry. We highly recommend calling this function with lpRasEntry set to NULL and lpdwEntryInfoSize set to 0 to obtain buffer sizing information. Once you have the appropriate size, you can call this function again and retrieve all the information without error.

The lpbDeviceInfo parameter is a pointer to an application-supplied buffer that receives TAPI device specific information for this phonebook entry. If this parameter is set to NULL, the lpdwDeviceInfoSize parameter will receive the number of bytes needed to retrieve this information. If you are using Windows 2000, Windows NT, or Windows XP, lpbDeviceInfo should be set to NULL. The final parameter, lpdwDeviceInfoSize, is a pointer to a DWORD that should be set to the number of bytes contained in the buffer supplied to lpbDeviceInfo. When RasGetEntryProperties() returns, lpdwDeviceInfoSize will return the number of bytes that are returned in the lpbDeviceInfo buffer.

The following code sample demonstrates how an application should use RasGetEntryProperties() and RasSetEntryProperties() to create a new phonebook entry:

 

#include <windows.h>

// Link to rasapi32.lib

#include <ras.h>

#include <raserror.h>

#include <stdio.h>

 

void main(void)

{

    DWORD EntryInfoSize = 0;

    DWORD DeviceInfoSize = 0;

    DWORD Ret;

    LPRASENTRY lpRasEntry;

    LPBYTE lpDeviceInfo;

 

    // Get buffer sizing information for a default phonebook entry

    if ((Ret = RasGetEntryProperties(NULL, "", NULL, &EntryInfoSize, NULL, &DeviceInfoSize)) != 0)

    {

        if (Ret != ERROR_BUFFER_TOO_SMALL)

        {

            printf("RasGetEntryProperties sizing failed with error %d\n", Ret);

            return;

        }

    }

 

    lpRasEntry = (LPRASENTRY) GlobalAlloc(GPTR, EntryInfoSize);

 

    if (DeviceInfoSize == 0)

        lpDeviceInfo = NULL;

    else

        lpDeviceInfo = (LPBYTE) GlobalAlloc(GPTR, DeviceInfoSize);

 

    // Get default phonebook entry

    lpRasEntry->dwSize = sizeof(RASENTRY);

 

    if ((Ret = RasGetEntryProperties(NULL, "", lpRasEntry, &EntryInfoSize, lpDeviceInfo, &DeviceInfoSize)) != 0)

    {

        printf("RasGetEntryProperties failed with error %d\n", Ret);

        return;

    }

 

    // Validate new phonebook name "Testentry"

    if ((Ret = RasValidateEntryName(NULL, "Testentry")) != ERROR_SUCCESS)

    {

        printf("RasValidateEntryName failed with error %d\n", Ret);

        return;

    }

 

    // Install a new phonebook entry, "Testentry", using default properties

    if ((Ret = RasSetEntryProperties(NULL, "Testentry", lpRasEntry, EntryInfoSize, lpDeviceInfo, DeviceInfoSize)) != 0)

    {

        printf("RasSetEntryProperties failed with error %d\n", Ret);

        return;

    }

}

Deleting Phonebook Entries

 

Deleting phonebook entries is easy. To do so, you simply call the RasDeleteEntry() function, which is defined as:

 

DWORD RasDeleteEntry(LPCTSTR lpszPhonebook, LPCTSTR lpszEntry);

 

The lpszPhonebook parameter is a pointer to a phonebook file name. The lpszEntry parameter is a string representing an existing phonebook entry. If this function succeeds, it returns ERROR_SUCCESS; otherwise, it returns ERROR_ INVALID_NAME.

 

Managing User Credentials

 

When a RAS client makes a connection using a phonebook entry through RasDial(), it can save the user's security credentials and associates them with the phonebook entry. The functions RasGetCredentials(), RasSetCredentials(), RasGetEntryDialParams(), and RasSetEntryDialParams() allow you to man- age user security credentials associated with a phonebook entry. The RasGetCredentials() and RasSetCredentials() functions were introduced in Windows NT 4. (They are also available on all Windows NT systems.) These two functions supersede RasGetEntryDialParams() and RasSetEntryDialParams(). Because RasGetCredentials() and RasSetCredentials() are not available on Windows 95, Windows 98, Windows Me, and Windows CE systems, you can use RasGetEntryDialParams() and RasSetEntryDialParams() for this purpose on all platforms. The RasGetCredentials() function retrieves user credentials associated with a phonebook entry and is defined as:

 

DWORD RasGetCredentials(

    LPCTSTR lpszPhonebook,

    LPCTSTR lpszEntry,

    LPRASCREDENTIALS lpCredentials

);

 

The lpszPhonebook parameter is a pointer to a phonebook filename. The lpszEntry parameter is a string representing an existing phonebook entry. The lpCredentials parameter, defined below, is a pointer to a RASCREDENTIALS structure that can receive the user name, password, and domain associated with the phonebook entry:

 

typedef struct {

    DWORD dwSize;

    DWORD dwMask;

    TCHAR szUserName[UNLEN + 1];

    TCHAR szPassword[PWLEN + 1];

    TCHAR szDomain[DNLEN + 1];

} RASCREDENTIALS, *LPRASCREDENTIALS;

 

The fields of this structure are defined as:

 

  1. dwSize: Specifies the size (in bytes) of a RASCREDENTIALS structure. You should always set this field to the structure size.
  2. dwMask: Is a bitmask field that identifies which of the next three fields in the structure are valid by using predefined flags. The flag RASCM_UserName applies to szUserName, RASCM_Password applies to szPassword, and RASCM_Domain applies to szDomain. There are more dwMask flags, but we will not describe them here.
  3. szUserName: Is a null-terminated string that contains a user's logon name.
  4. szPassword: Is a null-terminated string that contains a user's password.
  5. szDomain: Is a null-terminated string that contains a user's logon domain.

 

If RasGetCredentials() succeeds, it returns 0. Your application can determine which security credentials are set based on the flags set in the dwMask field of the lpCredentials structure.

The RasSetCredentials() function is similar to RasGetCredentials() except that it lets you change security credentials associated with a phonebook entry. The parameters are the same except that RasSetCredentials() features an additional parameter: fClearCredentials. RasSetCredentials is defined as:

 

DWORD RasSetCredentials(

    LPCTSTR lpszPhonebook,

    LPCTSTR lpszEntry,

    LPRASCREDENTIALS lpCredentials,

    BOOL fClearCredentials

);

 

The fClearCredentials parameter is a Boolean operator that, if set to TRUE, causes RasSetCredentials() to change credentials identified in the dwMask field of the lpCredentials structure to an empty string (“”) value. For example, if dwMask contains the RASCM_Password flag, the password stored is replaced with an empty string. If the RasSetCredentials() function succeeds, it returns 0.

You can also use RasGetEntryDialParams() and RasSetEntryDialParams() to manage user security credentials associated with phonebook entries. RasGetEntryDialParams() is defined as:

 

DWORD RasGetEntryDialParams(

    LPCTSTR lpszPhonebook,

    LPRASDIALPARAMS lprasdialparams,

    LPBOOL lpfPassword

);

 

The lpszPhonebook parameter is a pointer to a phonebook file name. The lprasdialparams parameter is a pointer to a RASDIALPARAMS structure. The lpfPassword parameter is a Boolean flag that returns TRUE if the user's password was retrieved in the lprasdialparams structure.

The RasSetEntryDialParams() function changes the connection information that was last set by the RasDial() call on a particular phonebook entry. RasSetEntryDialParams() is defined as:

 

DWORD RasSetEntryDialParams(

    LPCTSTR lpszPhonebook,

    LPRASDIALPARAMS lprasdialparams,

    BOOL fRemovePassword

);

 

The lpszPhonebook and lprasdialparams parameters are exactly the same as the first two parameters in RasGetEntryDialParams(). The fRemovePassword parameter is a Boolean flag that, if set to TRUE, tells RasSetEntryDialParams() to remove the password associated with the phonebook entry identified in the lprasdialparams structure.

 

 

 

 

Connection Management

 

RAS has two useful functions that allow you to retrieve the properties of connections established on your system: RasEnumConnections() and RasGetProjectionInfo(). RasEnumConnections() can retrieve all the available active RAS connections on your system. This is useful when you need to obtain connection specific information about a RAS connection on your system using RasGetProjectionInfo(), as you will see later in this chapter. The RasEnumConnections() is defined as:

 

DWORD RasEnumConnections(

    LPRASCONN lprasconn,

    LPDWORD lpcb,

    LPDWORD lpcConnections

);

 

The lprasconn parameter is an application buffer that will receive an array of RASCONN structures. A RASCONN structure is defined as:

 

typedef struct _RASCONN

{

    DWORD dwSize;

    HRASCONN hrasconn;

    TCHAR szEntryName[RAS_MaxEntryName + 1];

#if (WINVER >= 0x400)

    TCHAR szDeviceType[RAS_MaxDeviceType + 1];

    TCHAR szDeviceName[RAS_MaxDeviceName + 1];

#endif

#if (WINVER >= 0x401)

    TCHAR szPhonebook[MAX_PATH];

    DWORD dwSubEntry;

#endif

#if (WINVER >= 0x500)

    GUID guidEntry;

#endif

#if (WINVER >= 0x501)

    DWORD dwSessionId;

    DWORD dwFlags;

    LUID luid;

#endif

} RASCONN;

 

The most useful field in the RASCONN structure is the hrasconn, which receives the connection handle that RasDial() originally created. You can use this handle to retrieve more connection information from RasGetProjectionInfo(), which is described later. You need to pass to RasEnumConnections() a large enough buffer to hold several RASCONN structures; otherwise, this function will fail with the error ERROR_BUFFER_TOO_SMALL. Also, the first RASCONN structure in your buffer must have the dwSize field set to the byte size of a RASCONN structure. The next parameter, lpcb, is a pointer to a variable that you must set to the size (in bytes) of your lprasconn array. When this function returns, lpcb will contain the number of bytes required to enumerate all connections. If you don't supply a large enough buffer, you can always try again with the correct buffer size returned in lpcb. The lpcConnections parameter is a pointer to a variable that receives a count of the number of RASCONN structures written to lprasconn.

With the RAS connection handles you receive from RasEnumConnections(), you can obtain network protocol–specific information that is used over an established RAS connection. This is known as projection information. A remote access server uses projection information to represent a remote client on the network. For example, when you make a RAS connection that uses IP over a framing protocol, IP configuration information (such as an assigned IP address) is established from the RAS to your client. You can retrieve projection information for the protocols that travel over the PPP framing protocol by calling the RasGetProjectionInfo() function, which is defined as:

 

DWORD RasGetProjectionInfo(

    HRASCONN hrasconn,

    RASPROJECTION rasprojection,

    LPVOID lpprojection,

    LPDWORD lpcb

);

 

The hrasconn parameter is a RAS connection handle. The rasprojection parameter is a RASPROJECTION enumeration type that allows you to specify a protocol to receive connection information for. The lpprojection parameter receives a data structure that is associated with the enumeration type specified in rasprojection. The final parameter, lpcb, is a pointer to a variable that you must set to the size of your lpprojection structure. When this function completes, this variable will contain the size of the buffer needed to obtain the projection information.

The following RASPROJECTION enumeration types allow you to receive connection information:

 

  1. RASP_Amb.
  2. RASP_PppCcp.
  3. RASP_PppNbf.
  4. RASP_PppIp.
  5. RASP_PppIpx.
  6. RASP_PppLcp.
  7. RASP_Slip.

 

To retrieve IP address information for a PPP framing protocol connection, you must specify the RASP_PppIp enumeration type. When you specify a RASP_PppIp, you will receive a RASPPPIP structure that is defined as:

 

typedef  struct  _RASPPPIP {

  DWORD    dwSize;

  DWORD    dwError;

  TCHAR    szIpAddress[ RAS_MaxIpAddress + 1 ];

#ifndef WINNT35COMPATIBLE

  TCHAR    szServerIpAddress[ RAS_MaxIpAddress + 1 ];

#endif

#if (WINVER >= 0x500)

  DWORD    dwOptions;

  DWORD    dwServerOptions;

#endif

} RASPPPIP;

 

The fields are defined as:

 

  1. dwSize: Should be set to the size (in bytes) of a RASPPPIP structure.
  2. dwError: Receives an error code from the PPP negotiation process.
  3. szIpAddress: Receives a string representing the client's IP address.
  4. szServerIpAddress: Receives a string representing the server's IP address.
  5. dwOptions: Compression options for the local host.
  6. dwServerOptions: Compression options for the remote host.

 

The following code demonstrates how to call RasGetProjectionInfo() to retrieve the IP addresses assigned to a client when a PPP connection is made over RAS:

 

lpProjection = (RASPPPIP *) GlobalAlloc(GPTR, cb);

lpProjection->dwSize = sizeof(RASPPPIP);

cb = sizeof(RASPPPIP);

 

Ret = RasGetProjectionInfo(hRasConn, RASP_PppIp, lpProjection, &cb);

 

if (Ret != ERROR_SUCCESS)

{

    printf("RasGetProjectionInfo failed with error %d", Ret);

    return;

}

 else

{

    printf("\nRas Client IP address: %s\n", lpProjection->szIpAddress);

    printf("Ras Server IP address: %s\n", lpProjection->szServerIpAddress);

}

 

 

 

Useful References

  1. RASPHONE and RASDIAL: Tips and Differences

  2. Routing and Remote Access Error Codes

  3. MSDN Routing and Remote Access Service References

 


< RAS Client, Functions & Modes | RAS Main | VPN & RAS Example >