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 ...
随机推荐
- ASP.NET MVC使用Bootstrap系列(3)——使用Bootstrap 组件
阅读目录 Bootstrap 导航条 列表组 徽章 媒体对象 页头 路径导航 分页 输入框组 按钮式下拉菜单 警告框 进度条 小结 Bootstrap为我们提供了十几种的可复用组件,包括字体图标.下拉 ...
- iOS钥匙串
钥匙串 苹果的"生态圈",钥匙串访问,使用 AES 256 加密算法,能够保证用户密码的安全 钥匙串访问SDK,是苹果在 iOS 7.0.3 版本以后公布的 钥匙串访问的接口是纯 ...
- 【转】Flume日志收集
from:http://www.cnblogs.com/oubo/archive/2012/05/25/2517751.html Flume日志收集 一.Flume介绍 Flume是一个分布式.可 ...
- 要让div中的float不会自动显示到下一行来?
使用 高度 + hidden: 要尝试 恰当的 高度, 设置合适的 div的 height: ... 要让 float的 "最直接的" "亲生的 " " ...
- recording just for inquiry in the future
auditd审计 相关命令有: auditd, auditctl, ausearch, aureport 相关文件: /etc/audit/auditd.conf, /etc/audit/audit. ...
- objective-c与c++的差异
oc的编译指令为 clang -fobjc-arc -framework Foundation test.m -o test oc中,1表示YES,0表示NO.并不是非0值都是YES,这是因为BOOL ...
- NetBeans使用习惯:升级与保存配置
如何升级:点击 netbeans 的升级更新 ,即可升级版本:不推荐官网下载进行安装,否则会出现,以前的旧版本8.0的目录和8.0.1目录,虽然它会自动检测到以前版本的配置,提示导入... 如何备份: ...
- R语言练习(一)
b = seq(from=0, to=1, by=0.001) #一次方 l1 = function(b){ b^1 } y1 = l1(b) #二次方 l2 = function(b){ b^2 } ...
- QT共享库的创建与调用(初级)(附:UI界面不能被改变的其中一个原因)
背景: 最近在做的一个项目其中一部分既是实现PC与下位机的USB通信.windows平台下已经完成,现需移植到linux平台下. 在linux系统中,通过一段时间的工作,设备已被配置成hid类(后续再 ...
- r8 - ASC 41(俄罗斯多校)
1 今天干的俄罗斯的一场多校,被虐哭啊,就做出两题. 2 3 4 5 6 7 Gym 100496D Data Mining 8 题目讲得是给你一串数字,然后给你i,p,表示从第i开始,对这串数离散话 ...