C++实现VPN工具之常用API函数
RAS是Remote Access Service的缩写,意为:远程访问服务,主要用来配置企业的远程用户对企业内部网络访问,包括拨号访问和vpn方式。微软的所有Windows平台中都有RAS客户机,它允许我们将自己的计算机与另一个地方的远程计算机(其特色是一个远程访问服务器组件)相连,一般情况下, RAS客户机利用连接了电话线的一个调制解调器,通过拨号的方式呼叫远程计算机。服务器这方面,必须有一项等候DUN连接的服务,RAS客户机和服务器之间的连接建立之后,网络协议堆栈(与所用的分帧协议有关)就通过这个RAS连接,与远程计算机通信,就象通过LAN连接的一样。如今,许多调制解调器的数据通信速率明显比直接的LAN连接慢。RAS连接通过电话簿条目中可用的选项,经过验证后,RAS便可自动进入一台机器,登录到一个域。
VPN开发经常使用的API
RAS有四个函数,允许通过程序对电话簿RASENTRY结构进行管理。它们是:RasSet Entry、RasGetEntryProperties、RasRenameEntry和RasDeleteEntry。如要建立一个新条目或对一个现成的条目进行修改,可使用RasSetEntryProperties函数
RasGetEntryProperties 此函数检索并返回一个电话簿条目的属性
RasSetEntryProperties 修改或者创建一个电话本中的链接条目信息,通俗的说就是修改或创建一个VPN链接属性。
DWORD RasGetEntryProperties(
LPWSTR lpszPhoneBook,
LPWSTR szEntry,
LPRASENTRY lpbEntry,
LPDWORD lpdwEntrySize,
LPBYTE lpb,
LPDWORD lpdwSize
);
lpszPhoneBook:常被忽略并被设置为空值,电话薄条目存储在注册表中,而不是在电话本中。
szEntry:一个包含条目名称,空字符结尾字符串的指针。如果指定一个空字符串,该函数返回的默认值在lpbEntry 和 lpb 参数指向的缓冲区。
RasDeleteEntry
删除电话薄中条目,一般用来删除VPN连接
RasDial:拨号API
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
第三个参数lpRasDialParams
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;
第四个第五个参数:
如果lpvNotifier参数设为NULL,RasDial就会置入同步模式。dwNotifierType参数就会被忽略。同步调用RasDial是使用该函数的最简单的作用;美中不足的是,同步模式下不能对连接进行监视,如果lpvNotifier
参数不为NULL,就会进入异步模式,
意味着进行连接的同时,函数调用会立即返回。可以对连接进程进行监视
dwNotifierType:
0: lpvNotifier参数使用RasDialFunc函数指针管理连接事件
1: lpvNotifier参数利用RasDialFunc1函数指针管理连接事件
2: lpvNotifier参数利用RasDialFunc2函数指针管理连接事件
0xFFFFFFF: lpvNotifier参数令RasDial在连接事件期间发送一个窗口消息
RasHangUp挂断VPN
DWORD RasHangUp(
__in
HRASCONN hrasconn
);
hrasconn:RasDial返回的一个连接句柄
注意:连接在利用一个调制解调器端口时,如果连接关闭,这个端口需要花时间重新设置这个连接。因此,你应该一直等下去,直到端口连接完全关闭为止。要做到这一点,在重新设置自己的连接时,可调用
RasGetConnectionStatus:获取VPN链接状态来判断连接是否完全关闭。
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#之类的字符串
RasEnumDevices:获得所有具有RAS能力的设备名及类型
DWORD RasEnumDevices(
__in
LPRASDEVINFO lpRasDevInfo,
__in_out
LPDWORD lpcb,
__out
LPDWORD lpcDevices
);
RasValidateEntryName:判断名字的格式是否正确,是否已包含在电话簿中
DWORD
RasValidateEntryName(
__in
LPCTSTR lpszPhonebook,
__in
LPCTSTR lpszEntry
);
lpszPhonebook:用于识别到一个电话簿文件的路径。设为NULL,表示使用当前默认电话簿文件
lpszEntry:电话簿中没有这个名字,但该名字格式无误时,便返回ERROR_SUCCESS。若名字格式有错,这个函数就会失败,返回ERROR_INVALIDNAME;
如果电话簿中有这个名字,就会返回ERROR_ALREAD_YEXIST
可以用RasGetEntryDialParams和RasSetEntryDialParams函数来管理与具体电话簿条目相关的用户安全凭据
通过对RasDial的成功调用,本函数调用后返回连接信息被保存为电话簿入口。
RasEnumConnections:返回一个RASCONN结构数组的缓存的长指针,指向每一个RAS连接。
在调用本函数之前,必须设置缓存中RASCONN结构的第一个成员dwSize的值,即RASCONN的大小,为了在不同系统版本中通过,请用sizeof(RASCONN)取得大小。
本函数列出所有活动RAS连接,返回每一个连接句柄和电话簿入口名
函数原型:
DWORD
RasEnumConnections(
LPRASCONN
lprasconn,
LPDWORD
lpcb,
LPDWORD
lpcConnections
);
下面我们来了解一个很重要的数据结构RASENTRY
typedef_struct_RASENTRY
{
DWORD dwSize;
DWORD dwfOptions;
DWORD dwCountryID;
DWORD dwCountryCode;
TCHAR szAreaCode[ RAS_MaxAreaCode + 1
];
TCHAR szLocalPhoneNumber[
RAS_MaxPhoneNumber + 1 ];
DWORD dwAlternatesOffset;
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;
DWORD dwCustomAuthKey;
} RASENTRY;
RASENTRY 赋值:
RasOptions =
RASEO_SpecificNameServers | RASEO_RemoteDefaultGateway;
//RASEO_UseCountryAndAreaCodes (是否使用区号与拨号属性)
//RASEO_SpecificIpAddr (服务类型-> TCP/IP设置-> 是否指定IP地址项)
//RASEO_SpecificNameServers (设置DNS是否选用)
//RASEO_IpHeaderCompression (是否选用IP头指针压缩)
//RASEO_RemoteDefaultGateway (是否选用远程网上默认网关)
//RASEO_DisableLcpExtensions (是否决定在PPP里不使用LCP,一般不使用这个选项)
//RASEO_TerminalAfterDial (是否拨号后出现终端窗口 <常规-> 连接方式-> 设置-> 选项-> 连接控制> )
//RASEO_ModemLights (此选项只对WIN2K有效,选用后在任务栏出现一个状态监测器)
//RASEO_SwCompression (是否选用软件压缩 <服务器类型-> 高级选项> )
//RASEO_RequireEncryptedPw (是否选用需要加密的密码 <作用是PPP使用PAP明文> )
//RASEO_RequireMsEncryptedPw (是否选用需要微软加密的密码)
//RASEO_RequireDataEncryption (是否选用需要数据加密)
//RASEO_NetworkLogon (此选项对NT/2K没有影响,是否选用登陆网络)
//RASEO_UseLogonCredentials (是否当前用户采用用户名、密码、域等信息进行拨号连接)
//RASEO_PromoteAlternates (是否选用交替号码)
VpnStrategy = VS_Default;
strcpy(mName , "GPRSHY ");
// rasEntry Num
values
rasEntry.dwSize = sizeof
(RASENTRY);
rasEntry.dwfOptions = RasOptions;
rasEntry.dwAlternateOffset = 0;
rasEntry.dwCountryID = 86;//china
rasEntry.dwCountryCode = 86;//china
rasEntry.dwFrameSize = 0;
rasEntry.dwfNetProtocols = RASNP_Ip;
// TCP/IP
rasEntry.dwFramingProtocol =
RASFP_Ppp; //PPP
rasEntry.dwChannels = 0;
rasEntry.dwReserved1 = 0;
rasEntry.dwReserved2 = 0;
if(WINVER > = 0X400)//
WIN98系统
{
rasEntry.dwDialMode =
RASEDM_DialAsNeeded;
rasEntry.dwIdleDisconnectSeconds=0;
rasEntry.dwSubEntries=0;
rasEntry.dwDialExtraPercent=0;
rasEntry.dwDialExtraSampleSeconds=0;
rasEntry.dwHangUpExtraPercent=0;
rasEntry.dwHangUpExtraSampleSeconds=0;
if(WINVER > = 0x500)//
WIN2K系统
{
rasEntry.dwType
= RASET_Vpn;
rasEntry.dwVpnStrategy=VpnStrategy;
rasEntry.dwCustomAuthKey=600;
GUID guid;
CoCreateGuid(&guid);
rasEntry.guidId=guid;
rasEntry.dwEncryptionType=0;
strcpy(rasEntry.szCustomDialDll,
" ");
//
rasEntry.dwfOptions2=0;
//
rasEntry.dwfOptions3=0;
if(WINVER > = 0x501)
{
//
rasEntry.dwfOptions2=0;
//
rasEntry.dwfOptions3=0;
}
}
}
// Strings values
char strPhoneNumber[20];
char strDevType[50];
char strDevName[50];
strcpy (strPhoneNumber,
"*99***1# ");
strcpy (strDevType,
"RASDT_Modem ");
strcpy (strDevName,
"Hawsna Wireless Modem ");
strcpy (rasEntry.szAreaCode,
" ");
strcpy (rasEntry.szLocalPhoneNumber,
strPhoneNumber);
strcpy (rasEntry.szScript,
" ");
strcpy (rasEntry.szAutodialDll,
" ");
strcpy (rasEntry.szAutodialFunc,
" ");
strcpy (rasEntry.szX25PadType,
" ");
strcpy (rasEntry.szX25Address,
" ");
strcpy (rasEntry.szX25Facilities,
" ");
strcpy (rasEntry.szX25UserData,
" ");
strcpy (rasEntry.szDeviceType,
strDevType);
strcpy (rasEntry.szDeviceName,
strDevName);
// IP addresses
RASIPADDR
struipaddrDns,struipaddrDnsAlt,struipaddrWins,struipaddrWinsAlt;
struipaddrDns.a = 211;
struipaddrDns.b = 136;
struipaddrDns.c = 20;
struipaddrDns.d = 203;
struipaddrDnsAlt.a = 202;
struipaddrDnsAlt.b = 96;
struipaddrDnsAlt.c = 128;
struipaddrDnsAlt.d = 68;
struipaddrWins.a = 0;
struipaddrWins.b = 0;
struipaddrWins.c = 0;
struipaddrWins.d = 0;
struipaddrWinsAlt.a = 0;
struipaddrWinsAlt.b = 0;
struipaddrWinsAlt.c = 0;
struipaddrWinsAlt.d = 0;
rasEntry.ipaddrDns =
struipaddrDns;
rasEntry.ipaddrDnsAlt =
struipaddrDnsAlt;
rasEntry.ipaddrWins =
struipaddrWins;
rasEntry.ipaddrWinsAlt =
struipaddrWinsAlt;
一个简单的示例:
// Call RAS
DWORD dwRet=RasSetEntryProperties (NULL, mName, &rasEntry, sizeof(RASENTRY), NULL, 0);
if (dwRet)//ERROR_INVALID_PARAMETER == dwRet)
{
CString str;
str.Format( "RasSetEntryProperties failed %s\n The error code: %d\n ", mName,dwRet);
AfxMessageBox(str);
// return FALSE;
}
C++实现VPN工具之常用API函数的更多相关文章
- Delphi 常用API 函数
Delphi 常用API 函数 AdjustWindowRect 给定一种窗口样式,计算获得目标客户区矩形所需的窗口大小 AnyPopup 判断屏幕上是否存在任何弹出式窗口 ArrangeIconic ...
- C语言实现单链表,并完成链表常用API函数
C语言实现单链表,并完成链表常用API函数: 1.链表增.删.改.查. 2.打印链表.反转打印.打印环形链表. 3.链表排序.链表冒泡排序.链表快速排序. 4.求链表节点个数(普通方法.递归方法). ...
- Delphi 常用API 函数列表
Delphi 常用API 函数 AdjustWindowRect 给定一种窗口样式,计算获得目标客户区矩形所需的窗口大小AnyPopup 判断屏幕上是否存在任何弹出式窗口ArrangeIconicWi ...
- C# 窗体常用API函数 应用程序窗体查找
常用的处理窗体的API函数如下(注意:API函数必须放在窗体中...): 使用C#语言,要引用DllImport,必须要添加using System.Runtime.InteropServices命名 ...
- C#常用 API函数大全
常用Windows API1. API之网络函数WNetAddConnection 创建同一个网络资源的永久性连接WNetAddConnection2 创建同一个网络资源的连接WNetAddConne ...
- Delphi 常用API 函数(好多都没见过)
AdjustWindowRect 给定一种窗口样式,计算获得目标客户区矩形所需的窗口大小AnyPopup 判断屏幕上是否存在任何弹出式窗口ArrangeIconicWindows 排列一个父窗口的最小 ...
- Quartz 2D(常用API函数、绘制图形、点线模式)
Quzrtz 2D 绘图的核心 API 是 CGContextRef ,它专门用于绘制各种图形. 绘制图形关键是两步: 1.获取 CGContextRef ; 2.调用 CGContextRef 的方 ...
- 【总结】设备树语法及常用API函数【转】
本文转载自:http://blog.csdn.net/fengyuwuzu0519/article/details/74352188 一.DTS编写语法 二.常用函数 设备树函数思路是:uboot ...
- StringUtils工具类常用api <转>
该工具类是用于操作Java.lang.String类的. StringUtils类与String类的区别在于:此类是null安全的,即如果输入参数String为null,则不会抛出NullPointe ...
随机推荐
- Python操作 RabbitMQ、Redis、Memcache、SQLAlchemy
Memcached Memcached 是一个高性能的分布式内存对象缓存系统,用于动态Web应用以减轻数据库负载.它通过在内存中缓存数据和对象来减少读取数据库的次数,从而提高动态.数据库驱动网站的速度 ...
- Java读取txt文件,计算2011年9月份的通话时间
public class test2 { /** * @param args * @throws IOException */ public static void main(String[] arg ...
- Cucumber命令行接口
1. cucumber的命令行选项 首先查看命令行选项.和其它命令行工具一样,cucumber提供了—help选项.下面是cucumber帮助的一个缩减版本: $ cucumber --help -r ...
- 网上搜的一个shell中 中文设置的一个样例;
from:http://www.cnblogs.com/52linux/archive/2012/03/24/2415082.html SSH Secure Shell Client中文乱码的解决方法 ...
- thinkphp单入口和多入口的访问方法
完全是参考thinkphp的官网资料 现在, 基本上都是 用 单入口 的方式来做的! thinkphp可创建多入口和单入口两种模式,本文主要讲解创建方法和两者的区别. TP版本:3.1.3 前端:Ho ...
- 别老扯什么Hadoop了,你的数据根本不够大
本文原名“Don't use Hadoop when your data isn't that big ”,出自有着多年从业经验的数据科学家Chris Stucchio,纽约大学柯朗研究所博士后,搞过 ...
- 《UIP在NIOS上的移植》
移植环境:Cyclone IV 开发板,网卡芯片为ENC28J60,浏览器(Firefox_24.0.0.5001a) 首先,需要了解网卡芯片ENC28J60,有中文版的说明书:http://wenk ...
- JQ分页功能
HTML <div id='page'></div> <div id='con'></div> CSS span{width: 60px;height: ...
- 大熊君大话NodeJS之------FS文件模块
一,开篇分析 文件系统模块是一个简单包装的标准 POSIX 文件 I/O 操作方法集.可以通过调用 require("fs") 来获取该模块.文件系统模块中的所有方法均有异步和同步 ...
- SQL获取日期格式
) + ' ' + CONVERT(VARCHAR, DATEPART(hh, GetDate())) + ':' + ) AS Date ),) ),) ),) as DateTime) as [D ...