21 April 2008

Windows MobileでのRAS接続

Windows Mobile の eMbedded Visual C++ を用いて、RASによるインターネット接続

※ Connection Manager で関知しない接続方法なので、マイクロソフト製品(Pocket Internet Explorerなど)ではインターネットに接続していると認識されない。ConnMgrEstablishConnection のほうで接続すべし

20080421-ras.png

RAS接続一覧

// RAS一覧表示の更新
void CRasTestDlg::OnButtonGetRasEntry()
{
// TODO: この位置にコントロール通知ハンドラ用のコードを追加してください

LPRASENTRYNAME lpRasEntryName = NULL;
RASENTRYNAME tmpRasEntryName;
DWORD dwRasCb = 0;
DWORD dwRasEntries = 0;
DWORD dwRasRet;

int i, j;

// リストボックスをクリア
j = SendDlgItemMessage(IDC_COMBO_RASLIST, CB_GETCOUNT, 0, 0);
if(j != CB_ERR)
for(i=0; i<j;i++)
SendDlgItemMessage(IDC_COMBO_RASLIST, CB_DELETESTRING, 0, 0);

// RASエントリ数を得る(ダミーで一つ分のバッファでアクセスする)
// (dwRasCbに必要なバッファの大きさが返される)
dwRasCb = sizeof(RASENTRYNAME);
dwRasEntries = 0;
tmpRasEntryName.dwSize = sizeof(RASENTRYNAME);
RasEnumEntries(NULL, NULL, &tmpRasEntryName, &dwRasCb, &dwRasEntries);
if(dwRasEntries == 0)
return ; // RASエントリが0個の場合

// n 件分のバッファを確保 (n = dwRasCb/sizeof(RASENTRYNAME) )
lpRasEntryName = (LPRASENTRYNAME)LocalAlloc(LPTR, dwRasCb);

if(lpRasEntryName == NULL)
return; // メモリ確保失敗

lpRasEntryName->dwSize = sizeof(RASENTRYNAME); // エントリ1個のデータサイズ
//dwRasCb = dwRasCb; // エントリ全体のデータサイズ(そのまま)

// RASエントリ(全体)を得る
dwRasRet = RasEnumEntries(NULL, NULL, lpRasEntryName, &dwRasCb, &dwRasEntries);

if(dwRasRet != 0 || dwRasEntries == 0)
{ // エントリ取得に失敗(メモリ不足)または、件数ゼロのとき
LocalFree(lpRasEntryName);
return ;
}

// リストボックスに、RAS接続名をセットする
for(i=0; i<(int)dwRasEntries; i++)
SendDlgItemMessage(IDC_COMBO_RASLIST, CB_ADDSTRING, 0, (LPARAM)lpRasEntryName[i].szEntryName);

// リストボックスの1項目目を選択する
if((int)dwRasEntries > 0)
SendDlgItemMessage(IDC_COMBO_RASLIST, CB_SETCURSEL, 0, 0);

LocalFree(lpRasEntryName);

return;
}

RAS接続処理

// RAS接続
void CRasTestDlg::OnButtonRasOpen()
{
// TODO: この位置にコントロール通知ハンドラ用のコードを追加してください

RASDIALPARAMS RasParams;
HRASCONN hRas;
BOOL bPswd;

CString sTemp;

// ドロップダウンリストで選択している「RAS接続名」を取得する
RasParams.dwSize = sizeof(RASDIALPARAMS);
GetDlgItemText(IDC_COMBO_RASLIST, sTemp);
wcsncpy(RasParams.szEntryName, sTemp, RAS_MaxEntryName+1);

// RAS接続情報の取得
if(RasGetEntryDialParams(NULL, &RasParams, &bPswd) == 0)
{
// RAS接続
if(RasDial(NULL, NULL, &RasParams, NULL, NULL, &hRas) == 0)
{
MessageBox(_T("接続成功"));
}
else
{
MessageBox(_T("接続失敗"));
}
}
else
{
MessageBox(_T("ダイヤルアップ情報取得エラー"));
}

// RAS接続状態の表示更新
OnButtonRasGetip();

return;
}

RAS接続中の一覧

// 接続済みRAS一覧の更新
void CRasTestDlg::OnButtonRasGetip()
{
// TODO: この位置にコントロール通知ハンドラ用のコードを追加してください

LPRASCONN lpRasConnections = NULL;
RASCONN tmpRasConnections;
DWORD dwRasCb;
DWORD dwRasConnections;
RASPPPIP RasPppip;
DWORD dwRasRet;

TCHAR sTemp[RAS_MaxEntryName + 32]; //RAS名 + IPアドレス文字列(nnn.nnn.nnn.nnn)の長さ +α

int i, j;

// リストボックスをクリア
j = SendDlgItemMessage(IDC_COMBO_RASCONN, CB_GETCOUNT, 0, 0);
if(j != CB_ERR)
for(i=0; i<j;i++)
SendDlgItemMessage(IDC_COMBO_RASCONN, CB_DELETESTRING, 0, 0);

// コネクション数を得る(ダミーで一つ分のバッファでアクセスする)
// (dwRasCbに必要なバッファの大きさが返される)
dwRasCb = sizeof(RASCONN);
dwRasConnections = 0;
tmpRasConnections.dwSize = sizeof(RASCONN);
RasEnumConnections(&tmpRasConnections, &dwRasCb, &dwRasConnections);
if(dwRasConnections == 0)
{ // RAS接続エントリが0個の場合
wcscpy(sTemp, _T("RAS未接続"));
SendDlgItemMessage(IDC_COMBO_RASCONN, CB_ADDSTRING, 0, (LPARAM)sTemp);
// リストボックスの1項目目を選択する
SendDlgItemMessage(IDC_COMBO_RASCONN, CB_SETCURSEL, 0, 0);
return ;
}

// n 件分のバッファを確保 (n = dwRasCb/sizeof(RASCONN) )
lpRasConnections = (LPRASCONN)LocalAlloc(LPTR, dwRasCb);
if(lpRasConnections == NULL)
return; // メモリ確保失敗

lpRasConnections->dwSize = sizeof(RASCONN); // エントリ1個のデータサイズ
//dwRasCb = dwRasCb; // エントリ全体のデータサイズ(そのまま)

// RAS接続エントリ(全体)を得る
dwRasRet = RasEnumConnections(lpRasConnections, &dwRasCb, &dwRasConnections);

if(dwRasRet != 0)
{ // エントリ取得に失敗(メモリ不足)のとき
LocalFree(lpRasConnections);
return ;
}
if(dwRasConnections == 0)
{ // エントリ件数ゼロのとき
wcscpy(sTemp, _T("RAS未接続"));
SendDlgItemMessage(IDC_COMBO_RASCONN, CB_ADDSTRING, 0, (LPARAM)sTemp);
LocalFree(lpRasConnections);
// リストボックスの1項目目を選択する
SendDlgItemMessage(IDC_COMBO_RASCONN, CB_SETCURSEL, 0, 0);
return ;
}

// リストボックスに、RAS接続名をセットする
for(i=0; i<(int)dwRasConnections; i++)
{
// 0番目(最初)のコネクションのPPPIPアドレスを得る
RasPppip.dwSize = sizeof(RASPPPIP);
dwRasCb = sizeof(RASPPPIP);

// IPアドレスを取得する
RasGetProjectionInfo(lpRasConnections[i].hrasconn, RASP_PppIp, &RasPppip, &dwRasCb);

// リストボックスにセット
swprintf(sTemp, _T("%s, %s"), lpRasConnections[i].szEntryName, RasPppip.szIpAddress);
SendDlgItemMessage(IDC_COMBO_RASCONN, CB_ADDSTRING, 0, (LPARAM)sTemp);
}

// リストボックスの1項目目を選択する
SendDlgItemMessage(IDC_COMBO_RASCONN, CB_SETCURSEL, 0, 0);

LocalFree(lpRasConnections);

return;
}

RAS切断

// RAS切断
void CRasTestDlg::OnButtonRasClose()
{
// TODO: この位置にコントロール通知ハンドラ用のコードを追加してください
LPRASCONN lpRasConnections = NULL;
RASCONN tmpRasConnections;
DWORD dwRasCb;
DWORD dwRasConnections;
DWORD dwRasRet;

int nSelected;
CString sTemp;

// コネクション数を得る(ダミーで一つ分のバッファでアクセスする)
// (dwRasCbに必要なバッファの大きさが返される)
dwRasCb = sizeof(RASCONN);
dwRasConnections = 0;
tmpRasConnections.dwSize = sizeof(RASCONN);
RasEnumConnections(&tmpRasConnections, &dwRasCb, &dwRasConnections);
if(dwRasConnections == 0)
return ; // RAS接続エントリが0個の場合

// n 件分のバッファを確保 (n = dwRasCb/sizeof(RASCONN) )
lpRasConnections = (LPRASCONN)LocalAlloc(LPTR, dwRasCb);
if(lpRasConnections == NULL)
return; // メモリ確保失敗

lpRasConnections->dwSize = sizeof(RASCONN); // エントリ1個のデータサイズ
//dwRasCb = dwRasCb; // エントリ全体のデータサイズ(そのまま)

// RAS接続エントリ(全体)を得る
dwRasRet = RasEnumConnections(lpRasConnections, &dwRasCb, &dwRasConnections);

if(dwRasRet != 0 || dwRasConnections == 0)
{ // エントリ取得に失敗(メモリ不足)のとき
LocalFree(lpRasConnections);
MessageBox(_T("RAS切断エラー (未接続)"));
OnButtonRasGetip();
return ;
}

// 選択されているRAS接続(のリストボックスの番号)を取得
nSelected = SendDlgItemMessage(IDC_COMBO_RASCONN, CB_GETCURSEL, 0, 0);

if((int)dwRasConnections < nSelected+1)
{ // 選択されている番号が、RAS接続リストの最大値より大きいとき
LocalFree(lpRasConnections);
MessageBox(_T("RAS切断エラー"));
// RAS接続状態の表示
OnButtonRasGetip();
return ;
}

// RAS切断
if(RasHangUp(lpRasConnections[nSelected].hrasconn))
{
MessageBox(_T("RAS切断エラー"));
}
else
{
MessageBox(_T("RAS切断完了"));
}

LocalFree(lpRasConnections);

// RAS接続状態の表示
OnButtonRasGetip();

return;
}

参考にした記事
RAS / PPPとIPアドレス
マイクロソフト 「RasEnumEntries は、バッファサイズにもかかわらず成功を返します


Connection Manager に影響を与えない RAS接続語の後始末…

RAS切断した後の後始末

// connmgr.h をインクルード
// CellCore.lib をリンク対象

CONNMGR_CONNECTIONINFO connInfo;
HANDLE hConn;
DWORD dwIndex = 0;

ZeroMemory(&connInfo, sizeof(CONNMGR_CONNECTIONINFO));
connInfo.cbSize = sizeof(CONNMGR_CONNECTIONINFO);
// connInfo.dwParams = CONNMGR_PARAM_GUIDDESTNET;
connInfo.bDisabled = TRUE; // ここをTRUEにすると、実際に接続に行かない
// connInfo.dwPriority = CONNMGR_PRIORITY_USERINTERACTIVE;

// URLをGUIDにコンバート
ConnMgrMapURL(L"http://www.google.com", &connInfo.guidDestNet, &dwIndex);
// カラ接続(実際には接続しない)
ConnMgrEstablishConnection(&connInfo, &hConn);
// 切断:ここで、コネクションマネジャーの内部変数が再読み込みされるはず…
ConnMgrReleaseConnection(hConn, FALSE);