RAS拔号上网

来源:互联网 发布:淘宝助理5.6.9.0下载 编辑:程序博客网 时间:2024/04/27 19:21

这两天把CE板儿上的拔号程序初步完成,第一个是CE板儿上自带的MODEM无法使用,最终还是从网上看到一个牛人说改注册表然后映射到COM2口上,很简单的事情,有些时候儿没有弄过就会不知道如何下手。软件倒是费了些周章,从网上找了一个RAS的拔号软件,但他那个有点儿小问题,经过同事的指点,直接调用设置好的连接即可。比如你在CE板儿上建立了一个“我的连接”,直接把这个名字传到RASDIALPARAMS 变量里,

如下:
 RASDIALPARAMS rdParams;
 HRASCONN m_hRasConn = NULL;
 //初始化变量
 rdParams.dwSize = sizeof(RASDIALPARAMS);
 wcscpy(rdParams.szEntryName,lpszName);//_T("我的连接") wcscpy(rdParams.szPhoneNumber,_T("*99***1#"));
 wcscpy(rdParams.szCallbackNumber,_T(""));
 wcscpy(rdParams.szUserName,_T(""));
 wcscpy(rdParams.szPassword,_T(""));
 wcscpy(rdParams.szDomain,_T(""));

然后直接 RasDial(NULL,NULL,&rdParams,0L,NULL,&m_hRasConn);就可以了。

在网上找到一牛人的博客,发现这牛人真牛,不但C++的写好,还顺带搞了C#的,而且还用了TAPI的方法,很是厉害。用Connection Manager

Functions系列的API又写了一个,我觉得他应该封装起来,做一个父类,然后别人就可以自由使用了,有时间自己封装一下。
接着谈RAS,这个连接当然的我们可以自己在代码里创建,如下:

 LPWSTR lpszAPN = L"cmnet";
 LPWSTR lpszName = L"测试连接2";
 DWORD dwSize,
  dwError;
 TCHAR szError[100];
 BYTE  lpb[436];
 unsigned long lpbSize = sizeof(lpb);
 RASENTRY RasEntry;
 
 dwSize = sizeof (RASENTRY);
 memset (&RasEntry, 0, dwSize);
 memset(lpb,0,lpbSize);
 RasEntry.dwSize = dwSize;
 
 //对应WM中的选择调制解调器与调制解调器类型
 wcscpy(RasEntry.szDeviceName,L"Cellular Line");//移动线路(GPRS)
 wcscpy(RasEntry.szDeviceType,L"modem");

 TCHAR szLocalPhoneNumber[RAS_MaxPhoneNumber + 1] = {0};
 wsprintf(szLocalPhoneNumber,L"~GPRS!%s",lpszAPN);
 wcscpy(RasEntry.szLocalPhoneNumber,szLocalPhoneNumber );
 RasEntry.dwfOptions = 4194304;
 RasEntry.dwfNetProtocols = 4;
 RasEntry.dwFramingProtocol = 1;
如果没有下面的部分,你的程序无法打开连接。注意。 

//设置lpb
 //Pointer to a buffer that contains device-specific configuration information.
 //This is opaque TAPI device configuration information
 lpb[0]=180;
 lpb[1]=1;
 lpb[4]=180;
 lpb[5]=1;
 lpb[8]=180;
 lpb[9]=1;
 lpb[12]=1;
 lpb[16]=15;
 lpb[20]=1;
 lpb[24]=2;
 lpb[76]=1;
 lpb[80]=2;
 lpb[84]=2;
 //从D88位开始设置APN指令
 for(int i=0,step=0;i<wcslen(lpszAPN);i++,step+=2)
 {
  *(lpb + 88 + step)=(BYTE)*(lpszAPN+i);
 }
 lpb[344]=1;
 lpb[348]=1;

 if (dwError = RasSetEntryProperties (NULL, lpszName,
  &RasEntry, sizeof (RASENTRY),lpb, lpbSize))
 {
  wsprintf (szError, TEXT("Unable to create the phonebook entry.")
   TEXT(" Error %ld"), dwError);

 }

 TCHAR buffer[256]={0};
 LPWSTR key=buffer;
 wcscat(key,_T("Comm\\ConnMgr\\Providers\\{7C4B7A38-5FF7-4bc1-80F6-5DA7870BB1AA}\\Connections"));//RIL_KEY
 wcscat(key,L"\\");
 wcscat(key,lpszName);
 unsigned long val1 = 0;
 unsigned long val2 = 1;
 unsigned long val3 = 2;
 SetRegistryDWORD(HKEY_LOCAL_MACHINE, key,_T("RequirePW") , val1);    //是否需要密码RIL_REQ_PE
 SetRegistryDWORD(HKEY_LOCAL_MACHINE, key,_T("Enabled") , val2);    //是否为默认连接RIL_ENABLED
 SetRegistryDWORD(HKEY_LOCAL_MACHINE, key,_T("EntryType") , val3);//RIL_ENT_TYPE

 SetRegistrySZ(HKEY_LOCAL_MACHINE, key, _T("DestId"),
  _T("{ADB0B001-10B5-3F39-27C6-9742E785FCD4}"));    //一般是Internet设置;RIL_DES_ID  RIL_CONN_ID
 //ConnectionGUID,可以生成一个GUID;
 SetRegistrySZ(HKEY_LOCAL_MACHINE, key,_T("ConnectionGUID") ,
  NewGUID());

为了测试进行了简单改写,但基本还是符合原程序的,希望原作者不要介意。

如果你想在拔号时获得当前状态,可以这样:
在你的实现代码里加上这句,
const   UINT   WM_RASEVENT   =   ::RegisterWindowMessageA(RASDIALEVENT);
然后添加消息映射:

BEGIN_MESSAGE_MAP(CtestGprsDlg, CDialog)
  ......................
 ON_REGISTERED_MESSAGE(WM_RASEVENT,   &CtestGprsDlg::OnRasDialEvent)
 //}}AFX_MSG_MAP
  ..........................
END_MESSAGE_MAP()
然后添加一个消息映射函数:

LRESULT OnRasDialEvent(WPARAM wp,LPARAM lp);
并实现之:

LRESULT CtestGprsDlg::OnRasDialEvent(WPARAM wp,LPARAM lp)
{
 RASCONNSTATE   rasstate =   (RASCONNSTATE)wp;  
 switch(rasstate)  
 {  
 case   RASCS_OpenPort:   
    break;  
 case   RASCS_PortOpened:  
         //在此处添加你的工作代码
     break;  
 case   RASCS_ConnectDevice:  

     break;  
 case   RASCS_DeviceConnected:  

     break;  
    case   RASCS_Authenticate:  

     break;  
    case   RASCS_Authenticated:  

     break;  
 case   RASCS_Connected:  
 
     break;  
 case   RASCS_Disconnected:   
     break;  
 default:  
     return   (LRESULT)0;  
 }  
    return   (LRESULT)0;
}
这样基本就OK,该吃饭了,回头接着写。

 

在CE里回调和事件消息均无法截获,但在PC上是没有问题,已经过了测试,后来在CSDN上提问,有牛人指点拦截

PreTranslateMessage这个消息事件,截获WM_RASDIALEVENT消息即可达到目的,经过测试OK了,代码如下

BOOL CGprsStateDlg::PreTranslateMessage(MSG* pMsg)
{
 // TODO: 在此添加专用代码和/或调用基类
    if(pMsg->message == WM_RASDIALEVENT)
 {
  switch(pMsg->wParam)
  {
 case   RASCS_OpenPort:
    //cs.m_s  = _T("打开端口……");
    break;  
 case   RASCS_PortOpened: 
  //cs.m_s  = _T("端口已打开……");
     break;  
 case   RASCS_ConnectDevice:   
     break;  
 case   RASCS_DeviceConnected:
  AfxGetApp()->GetMainWnd()->GetDlgItem(IDC_STATIC_STATE)->SetWindowTextW(_T("设备已连接.…"));
     break;  
    case   RASCS_Authenticate: 
  //cs.m_s  = _T("验证用户及密码……");
     break;  
    case   RASCS_Authenticated:   

     break;  
 case   RASCS_Connected:
  //cs.m_s  = _T("已连接");
     break;  
 case   RASCS_Disconnected:   

     break;  
 default:  
     return   (LRESULT)0;
  }
 }
 return CDialog::PreTranslateMessage(pMsg);
}
另外要注意的是:RAS拨号的同步和异步问题,如果这个问题不搞清楚,就谈不上消息的截获和同步的线程监视。

 dwRet = RasDial(NULL,NULL,&rdParams,0L,NULL,&m_hRasConn);//同步
 dwRet = RasDial(NULL,NULL,&rdParams,0L,RasDialFunc,&m_hRasConn);//异步回调 --只支持在PC
 dwRet = RasDial(NULL,NULL,&rdParams,0xFFFFFFFF,this->m_hWnd,&m_hRasConn); //异步消息--支持PC、CE

如果同步,可用线程监视同步过程,但没有取得成功,不过网上有人说成功过。后两者我都在PC上成功,CE均未成功。只在使用了PreTranslateMessage才成功。

谢谢那位高手。你的无私指点是我进步的动力。

原创粉丝点击