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);