1.什么叫RAS?
答:微软的所有Wi n d o w s平台中都有RAS客户机,它允许我们将自己的计算机与另一个地方
的远程计算机(其特色是一个远程访问服务器组件)相连,一般情况下, RAS客户机利用连
接了电话线的一个调制解调器,通过拨号的方式呼叫远程计算机。因此,有时, RAS客户机
也称作“拨号联网(DUN)客户机”。服务器这方面,必须有一项等候DUN连接的服务,
RAS客户机和服务器之间的连接建立之后,网络协议堆栈(与所用的分帧协议有关)就
通过这个RAS连接,与远程计算机通信,就象通过LAN连接的一样。当然,如今,许多调制
解调器的数据通信速率明显比直接的LAN连接慢。RAS连接通过电话簿条目中可用的选项,经过验证后,RAS便可自
动进入一台机器,登录到一个域。
2.RAS错误打印?
Raserror.h列举了相当多预先定义的错误代码。这个文件中,大家将注意到一个错误说明
字串,这个字串和RAS中所用的各错误代码关联在一起RasGetErrorString
3.平台兼容?
RAS函数所用的有些数据结构中,根据
WINVER定义的值,分别使用或不用额外的数据字段。
所以一定要定义当前的WINVER,不然就失败返回632
直接去targetver.h中看,比如XP:
/ 没有#define WINVER 0x0501
就直接加上
#ifndef WINVER #define WINVER 0x0501 #endif
4.具体函数介绍:
(1)
DWORD RasDial( __in LPRASDIALEXTENSIONS lpRasDialExtensions, __in LPCTSTR lpszPhonebook, __in LPRASDIALPARAMS lpRasDialParams, __in DWORD dwNotifierType, __in LPVOID lpvNotifier, __in LPHRASCONN lphRasConn );
lpRasDialExtensions:参数是一个可选指针,指向一个RASDIALEXTENSIONS结构,有了
这个结构,你的应用程序便可使用RasDial函数的扩展特性了, 可忽略,设为NULL
pszPhonebook:用于识别到一个电话簿文件的路径。设为NULL,表示使用当前默认电话簿文件
lpRasDialParams:定义了拨号和用户身份验证参数
dwNotifierType, lpvNotifier:可同步调用还是异步调用?
lphRasConn:
下面继续对此函数的内部结构解析:
第一个参数lpRasDialExtensions对应的结构体:
typedef struct tagRASDIALEXTENSIONS { DWORD dwSize; DWORD dwfOptions; HWND hwndParent; ULONG_PTR reserved; #if (WINVER >= 0x500) ULONG_PTR reserved1; RASEAPINFO RasEapInfo; #endif } RASDIALEXTENSIONS
dwSize:必须设为RASDIALEXTENSIONS结构的长度(按字节算)。
dwfOptions:允许你为使用RasDial扩展特性而设置位标志:如下:
RDEOPT_UsePrefixSuffix:令RasDial使用与指定拨号设备关联的前缀和后缀
RDEOPT_PausedStates:允许RasDial进入暂停操作状态,从而用户就可以重试登录、改变密码和设置回拨号码
RDEOPT_IgnoreModemSpeaker:令RasDial忽略RAS电话簿中的Modem喇叭设置
RDEOPT_SetModemSpeaker:如果设置了 RDEOPT_IgnoreModemSpeaker标志,那么利用这个标志,可以打开Modem喇叭
RDEOPT_IgnoreSoftwareCompression:令RasDial忽略软件压缩设置
RDEOPT_SetSoftwareCompression:在设置了 RDEOPT_IgnoreSoftwareCompression标志的前提下,再用这个标志,便会打开软件压缩
RDEOPT_PauseOnScript:供RasDialDlg内部使用。不能设置这个标志
RDEOPT_UseCustomScripting:2000/NT不支持
RDEOPT_CustomDial:NT不支持
hwndParent:不用,应该设为NULL
reserved:不用,设为0
reserved1:不用,设为0
RasEapInfo:NT不支持
第二个参数:电话簿文件:
电话簿不过是一个RASENTRY结构的集合,这些结构中包含了电话号码、数据速率、用户身份验证信息和其他连接信息,在2000/NT平台上,电话簿的扩展名一般是. PBK的文件中
具体结构参看window网络编程16章吧。
第三个参数:
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;
dwSize:必须设为RASDIALPARAMS;结构的长度(按字节算)。
szEntryName:一个字串,允许你标识一个电话簿条目,该条目中包含在RasDial函数的lpszPhonebook参数中列出的电话簿文件内,如为空字串(“”),RasDial就会选择系统上已安装的第一个可用的Modem,
并依据下一个参数szPhoneNumber来拨叫连接
szPhoneNumber:一个字串,代表一个电话号码,这个号码优先于szEntryName字段中指定的电话簿条目内包含的电话号码
szCallbackNumber:允许你指定一个电话号码, RAS服务器可以根据这个号码回拨。如果RAS服务器允许有一个回拨号码,它就会中断原来的连接,利用你指定的回拨号码回拨。这个特性非常不错,因为有了它
服务器就可知道连接的用户来自何处
szUserName:一个字串,标识RAS服务器上的用户进行身份验证时所用的登录名
szPassword:一个字串,标识R A S服务器上的用户进行身份验证时所用的密码
szDomain:可选。允许你指定最初的电话簿子条目拨叫一个RAS多链路连接
dwCallbackId:允许你把一个应用程序定义的值投递到一个R a s D i a l F u n c 2回拨函数中
第四个第五个参数:
如果lpvNotifier参数设为NULL,RasDial就会置入同步模式。dwNotifierType参数就会被忽略。同步调用RasDial是使用该函数的最简单的作用;美中不足的是,同步模式下不能对连接进行监视,如果lpvNotifier
参数不为NULL,就会进入异步模式, 意味着进行连接的同时,函数调用会立即返回。可以对连接进程进行监视
dwNotifierType:
0: lpvNotifier参数使用RasDialFunc函数指针管理连接事件
1: lpvNotifier参数利用RasDialFunc1函数指针管理连接事件
2: lpvNotifier参数利用RasDialFunc2函数指针管理连接事件
0xFFFFFFF: lpvNotifier参数令RasDial在连接事件期间发送一个窗口消息
分别为以下三个函数:
void CALLBACK RasDialFunc( [in] UINT unMsg, [in] RASCONNSTATE rasconnstate, [in] DWORD dwError );
unMsg:只可能为WM_RASDIALEVENT
rasconnstate:接收RasDial函数即将发生的连接活动:运行、暂停和中断
dwError: RAS错误代码
void CALLBACK RasDialFunc1( [in] HRASCONN hrasconn, [in] UINT unMsg, [in] RASCONNSTATE rascs, [in] DWORD dwError, [in] DWORD dwExtendedError );
hrasconn:指向连接的句柄
dwExtendedError:扩展错误信息
DWORD CALLBACK RasDialFunc2( [in] DWORD dwCallbackId, [in] DWORD dwSubEntry, [in] HRASCONN hrasconn, [in] UINT unMsg, [in] RASCONNSTATE rascs, [in] DWORD dwError, [in] DWORD dwExtendedError );
dwCallbackId:包含了一个应用程序定义的值,这个值最初是设在RASDIALPARAMS;结构的dwCallbackId字段中的
dwSubEntry:接收子条目电话簿索引,这个索引会再次回调RasDialFunc2函数
(2)事件通知函数
DWORD RasConnectionNotification( __in HRASCONN hrasconn, __in HANDLE hEvent, __in DWORD dwFlags );
hrasconn:RasDial返回的一个连接句柄,如为INVALID_HANDLE_VALUE(要强制转换成HRASCONN)
hEvent:CreateEvent创建
dwFlags:
RASCN_Connection:当hrasconn为INVALID_HANDLE_VALUE,任何一次RAS连接都会触发这一事件
RASCN_Disconnection:当hrasconn为INVALID_HANDLE_VALUE,任何一次RAS中止都会触发这一事件
RASCN_BandwidthAdded:在一个多链路连接上,子条目连接会触发这一事件
RASCN_BandwidthRemoved:在多链路连接上,子条目取消连接时,会触发这一事件
(3)
DWORD RasHangUp( __in HRASCONN hrasconn );
hrasconn:RasDial返回的一个连接句柄
注意:连接在利用一个调制解调器端口时,如果连接关闭,这个端口需要花时间重新设置这个连接。因此,你应该一直等下去,直到端口连接完全关闭为止。要做到这一点,在重新设置自己的连接时,可调用
R asGetConnectionStatus来判断连接是否完全关闭。
(4)
DWORD RasGetConnectStatus( __in HRASCONN hrasconn, __in_out LPRASCONNSTATUS lprasconnstatus );
hrasconn:RasDial返回的一个连接句柄
lprasconnstatus:取得当前的连接状态
typedef struct _RASCONNSTATUS { DWORD dwSize; RASCONNSTATE rasconnstate; DWORD dwError; TCHAR szDeviceType[RAS_MaxDeviceType + 1]; TCHAR szDeviceName[RAS_MaxDeviceName + 1]; #if (WINVER >= 0x401) TCHAR szPhoneNumber[ RAS_MaxPhoneNumber + 1 ]; #endif // (WINVER >= 0x401) } RASCONNSTATUS;
dwSize:必须设为RASCONNSTATUS结构的长度(按字节算)。
rasconnstate:RAS连接活动状态
dwError:若RasGetConnectStatus没有返回0,就取得一个具体的R A S错误代码
szDeviceType:取得一个字串,该字串代表连接所用的设备类型
szDeviceName:取得当前的设备名
szPhoneNumber:电话号码,如*99#之类的字符串
(5)获得所有具有R A S能力的设备名及类型
DWORD RasEnumDevices( __in LPRASDEVINFO lpRasDevInfo, __in_out LPDWORD lpcb, __out LPDWORD lpcDevices );
(6)判断名字的格式是否正确,是否已包含在电话簿中
DWORD RasValidateEntryName( __in LPCTSTR lpszPhonebook, __in LPCTSTR lpszEntry );
lpszPhonebook:用于识别到一个电话簿文件的路径。设为NULL,表示使用当前默认电话簿文件
lpszEntry:电话簿中没有这个名字,但该名字格式无误时,便返回ERROR_SUCCESS。若名字格式有错,这个函数就会失败,返回ERROR_INVALIDNAME;
如果电话簿中有这个名字,就会返回ERROR_ALREAD_YEXIST
(7)
RAS有四个函数,允许通过程序对电话簿RASENTRY结构进行管理。它们是:RasSet Entry、
RasGetEntryProperties、RasRenameEntry和RasDeleteEntry。如要建立一个新条目或对一个现
成的条目进行修改,可使用RasSetEntryProperties函数
(8)
可以用RasGetEntryDialParams和RasSetEntryDialParams函数来管理与具体电话
簿条目相关的用户安全凭据