现在的位置: 首页 > 综合 > 正文

Windows下ADSL的操作编程 — 枚举ADSL连接、拨号、挂断

2012年04月06日 ⁄ 综合 ⁄ 共 11286字 ⁄ 字号 评论关闭
最后面有完整的源代码,在Schedule Download项目中使用。这里描述几个关键点:

1. 不能参考网上的文章,说的都很片面而且版本过老。请参考MSDN:Win32 and COM development -> Networking -> Network communication -> Routing and Remove Access Service -> SDK Document -> Routing and Remote Access Service下的内容。事实上,对于win32的编程开发,第一参考资料始终是MSDN,如果MSDN上的内容有些过于浅显,再google。
2. 根据MSDN上的说法,请不要用隐式链接的方式来调用rasapi32.dll中的函数,用LoadLibrary & GetProcAddress这种显式的方法。看下面代码一开头的注释。
3. 枚举本地ADSL连接的时候,老办法,首先用空的buffer传入,得到一共有多少个连接,然后再分配内存再次调用枚举方法。
4. RASDIALPARAMS是一个关键的数据结构,保存了一个ADSL连接的信息。windows中这种RAS连接都有phonebook和entry的 概念,所谓phonebook就是保存了RAS连接的一个文本文件,其中可以包含多个entry,每个entry就是一个RAS连接。所以,将来拨号的时 候要给定phonebook和entry的。
5. ScheduleDownload的SDClient中,要能自动拨号ADSL。这里有个问题就是,该连接一定要是自动保存了密码的那种。否则就无法自动 拨号了。为了查询指定的RAS连接是否自动保存了密码,使用了RasGetEntryDialParams这个函数,这个函数会给出指定连接是否保存了密 码。
6. 使用RasDial函数就可以实现无界面的拨号,MSDN中提供了相关信息,可以出现带有界面的拨号。拨号成功,函数会给出一个HRASCONN的句柄。 使用这个句柄将来调用RasHangup来挂断一个拨号。使用RasDial拨号成功后,windows的任务栏中会出现一个ADSL连接的图标。
7. RasEnumConn是用来枚举已经拨号成功的连接的。RasEnumEntries才是用来枚举所有的ADSL连接的。一开始由于不清楚phonebook,entry这些概念,所以误以为RasEnumConn是用来枚举机器中的ADSL连接的。

    /*
    * Schedule Download ADSL utilities, based on windows RAS
    * We use LoadLibrary to load rasapi32.dll here because:
    * " If an application links statically to the RASAPI32 DLL, the application will fail
    * to load if Remote Access Service is not installed. A RAS application can load when
    * RAS is not installed by using LoadLibrary to load the DLL, and GetProcAddress to
    * obtain pointers to the RAS functions. " -- from MSDN
    * Written by Eric Zhang <nicolas.m.zhang@gmail.com>
    
*/

    #include "..\include\adsl.h"
    #include 
"..\include\logger.h"
    #include 
"..\include\utils.h"
    #include 
"..\include\defs.h"
    #include 
"..\include\macros.h"
    #include 
<strsafe.h>

    typedef DWORD (APIENTRY *FN_ENUM_ENTRIES)(LPCTSTR, LPCTSTR, LPRASENTRYNAME, LPDWORD, LPDWORD);
    typedef DWORD (APIENTRY 
*FN_GET_ENTRY_DIAL_PARAMS)(LPCTSTR, LPRASDIALPARAMS, LPBOOL);
    typedef DWORD (APIENTRY 
*FN_RAS_DIAL)(LPRASDIALEXTENSIONS, LPCTSTR, LPRASDIALPARAMS, DWORD, LPVOID, LPHRASCONN);
    typedef DWORD (APIENTRY 
*FN_RAS_HANGUP)(HRASCONN);

    extern DWORD tls_index_adsl;
    
extern HANDLE sdc_heap;
    
extern CRITICAL_SECTION sdc_cs_adsl;

    // dll module handle
    HMODULE ras_module = NULL;

    RASENTRYNAME *adsl_enum_entries(DWORD *entry_num)
    {
       DWORD errcode;
       FN_ENUM_ENTRIES enum_entries;
       RASENTRYNAME ras_entry;
       RASENTRYNAME 
*ras_entry_list;
       DWORD total_bytes, total_entries;
       DWORD result;

       M_RETURN_VAL_IF_FAIL(logger_is_enabled(), NULL);
       EnterCriticalSection(&sdc_cs_adsl);
       
// load rasapi32.dll
       if (ras_module == NULL) {
          ras_module 
= LoadLibrary(ADSL_RASAPI32_DLL);
          
if (ras_module == NULL) {
             GET_ERROR_CODE(errcode);
             M_GTIF_WITH_LOG(FALSE, failed, LOG_LEVEL_ERROR, __SDFILE__, __LINE__, ADSL_LOAD_DLL_FAILED, utils_format_error_string(errcode));
          }
       }

       // get function address
       enum_entries = (FN_ENUM_ENTRIES)GetProcAddress(ras_module, "RasEnumEntriesW");
       
if (enum_entries == NULL) {
          GET_ERROR_CODE(errcode);
          M_GTIF_WITH_LOG(FALSE, failed, LOG_LEVEL_ERROR, __SDFILE__, __LINE__, ADSL_GET_FN_ENUM_ENTRIES_FAILED, utils_format_error_string(errcode));
       }

       // Free the entries list last time allocated
       ras_entry_list = (RASENTRYNAME *)TlsGetValue(tls_index_adsl);
       
if (ras_entry_list != NULL) {
          HeapFree(sdc_heap, NULL, ras_entry_list);
          TlsSetValue(tls_index_adsl, NULL);
       }

       // begin working
       ras_entry.dwSize = sizeof(RASENTRYNAME);
       total_bytes 
= sizeof(RASENTRYNAME);
       result 
= enum_entries(NULL, NULL, &ras_entry, &total_bytes, &total_entries);
       
if (result == 0) {
          
if (total_entries < 1) {
             
// no entry found
             ras_entry_list = NULL;
             
*entry_num = 0;
          } 
else {
             
// only one entry, copy it into ras_entry_list and return
             ras_entry_list = (RASENTRYNAME *)HeapAlloc(sdc_heap, HEAP_ZERO_MEMORY, sizeof(RASENTRYNAME));
             M_GTIF_WITH_LOG(ras_entry_list 
!= NULL, failed, LOG_LEVEL_ERROR, __SDFILE__, __LINE__, ADSL_HEAP_ALLOC_FAILED, sizeof(RASENTRYNAME));
             CopyMemory(ras_entry_list, 
&ras_entry, sizeof(RASENTRYNAME));
             TlsSetValue(tls_index_adsl, ras_entry_list);
             
*entry_num = 1;
          }
       } 
else if (result == ERROR_BUFFER_TOO_SMALL) {
          
// multiple entries, alloc memory and recall enum_entries
          ras_entry_list = (RASENTRYNAME *)HeapAlloc(sdc_heap, HEAP_ZERO_MEMORY, total_bytes);
          M_GTIF_WITH_LOG(ras_entry_list 
!= NULL, failed, LOG_LEVEL_ERROR, __SDFILE__, __LINE__, ADSL_HEAP_ALLOC_FAILED, total_bytes);
          ras_entry_list
->dwSize = sizeof(RASENTRYNAME);
          
// call again
          result = enum_entries(NULL, NULL, ras_entry_list, &total_bytes, &total_entries);
          
if (result == 0) {
             
// success
             TlsSetValue(tls_index_adsl, ras_entry_list);
             
*entry_num = total_entries;
          } 
else {
             
// failed, free the storage have allocated and return fail
             HeapFree(sdc_heap, NULL, ras_entry_list);
             ras_entry_list 
= NULL;
             
*entry_num = -1;
             M_GTIF_WITH_LOG(FALSE, failed, LOG_LEVEL_ERROR, __SDFILE__, __LINE__, ADSL_ENUM_ENTRIES_FAILED, result);
          }
       }

       LeaveCriticalSection(&sdc_cs_adsl);
       
return ras_entry_list;
    failed:
       LeaveCriticalSection(
&sdc_cs_adsl);
       
return NULL;
    }

    WORD adsl_entry_save_password(PCTSTR phone_book_path, PCTSTR entry_name)
    {
       FN_GET_ENTRY_DIAL_PARAMS get_entry_dial_params;
       RASDIALPARAMS ras_dial_params;
       DWORD result;
       DWORD errcode;
       BOOL save_password = FALSE;

       M_RETURN_VAL_IF_FAIL(phone_book_path != NULL, -1);
       M_RETURN_VAL_IF_FAIL(entry_name 
!= NULL, -1);
       M_RETURN_VAL_IF_FAIL(logger_is_enabled(), 
-1);

       EnterCriticalSection(&sdc_cs_adsl);
       
// load rasapi32.dll
       if (ras_module == NULL) {
          ras_module 
= LoadLibrary(ADSL_RASAPI32_DLL);
          
if (ras_module == NULL) {
             GET_ERROR_CODE(errcode);
             M_GTIF_WITH_LOG(FALSE, failed, LOG_LEVEL_ERROR, __SDFILE__, __LINE__, ADSL_LOAD_DLL_FAILED, utils_format_error_string(errcode));
          }
       }

       // get function address
       get_entry_dial_params = (FN_GET_ENTRY_DIAL_PARAMS)GetProcAddress(ras_module, "RasGetEntryDialParamsW");
       
if (get_entry_dial_params == NULL) {
          GET_ERROR_CODE(errcode);
          M_GTIF_WITH_LOG(FALSE, failed, LOG_LEVEL_ERROR, __SDFILE__, __LINE__, ADSL_GET_FN_ENTRY_PARAMS_FAILED, utils_format_error_string(errcode));
       }

       // call the function
       ras_dial_params.dwSize = sizeof(RASDIALPARAMS);
       M_GTIF_WITH_LOG(SUCCEEDED(StringCchCopy(ras_dial_params.szEntryName, _countof(ras_dial_params.szEntryName), entry_name)),
          failed, LOG_LEVEL_ERROR, __SDFILE__, __LINE__, ADSL_STRING_OPERATE_FAILED);
       result 
= get_entry_dial_params(phone_book_path, &ras_dial_params, &save_password);
       M_GTIF_WITH_LOG(result 
== 0, failed, LOG_LEVEL_ERROR, __SDFILE__, __LINE__, ADSL_GET_ENTRY_DIAL_PARAM_FAILED, result);

       LeaveCriticalSection(&sdc_cs_adsl);
       
return save_password;
    failed:
       LeaveCriticalSection(
&sdc_cs_adsl);
       
return -1;
    }

    BOOL adsl_dial(PCTSTR phone_book_path, PCTSTR entry_name, HRASCONN *adsl_conn)
    {
       RASDIALPARAMS dial_params;
       HRASCONN ras_conn 
= NULL;
       DWORD result, errcode;
       FN_GET_ENTRY_DIAL_PARAMS get_entry_dial_params;
       FN_RAS_DIAL ras_dial;
       BOOL save_password;

       M_RETURN_VAL_IF_FAIL(phone_book_path != NULL, FALSE);
       M_RETURN_VAL_IF_FAIL(entry_name 
!= NULL, FALSE);
       M_RETURN_VAL_IF_FAIL(logger_is_enabled(), FALSE);

       EnterCriticalSection(&sdc_cs_adsl);
       
// load rasapi32.dll
       if (ras_module == NULL) {
          ras_module 
= LoadLibrary(ADSL_RASAPI32_DLL);
          
if (ras_module == NULL) {
             GET_ERROR_CODE(errcode);
             M_GTIF_WITH_LOG(FALSE, failed, LOG_LEVEL_ERROR, __SDFILE__, __LINE__, ADSL_LOAD_DLL_FAILED, utils_format_error_string(errcode));
          }
       }

       // get function address
       get_entry_dial_params = (FN_GET_ENTRY_DIAL_PARAMS)GetProcAddress(ras_module, "RasGetEntryDialParamsW");
       
if (get_entry_dial_params == NULL) {
          GET_ERROR_CODE(errcode);
          M_GTIF_WITH_LOG(FALSE, failed, LOG_LEVEL_ERROR, __SDFILE__, __LINE__, ADSL_GET_FN_ENTRY_PARAMS_FAILED, utils_format_error_string(errcode));
       }
       ras_dial 
= (FN_RAS_DIAL)GetProcAddress(ras_module, "RasDialW");
       
if (ras_dial == NULL) {
          GET_ERROR_CODE(errcode);
          M_GTIF_WITH_LOG(FALSE, failed, LOG_LEVEL_ERROR, __SDFILE__, __LINE__, ADSL_GET_FN_DIAL_FAILED, utils_format_error_string(errcode));
       }

       // get entry stuffs
       dial_params.dwSize = sizeof(RASDIALPARAMS);
       M_GTIF_WITH_LOG(SUCCEEDED(StringCchCopy(dial_params.szEntryName, _countof(dial_params.szEntryName), entry_name)),
          failed, LOG_LEVEL_ERROR, __SDFILE__, __LINE__, ADSL_STRING_OPERATE_FAILED);
       result 
= get_entry_dial_params(phone_book_path, &dial_params, &save_password);
       M_GTIF_WITH_LOG(result 
== 0, failed, LOG_LEVEL_ERROR, __SDFILE__, __LINE__, ADSL_GET_ENTRY_DIAL_PARAM_FAILED, result);
       M_GTIF_WITH_LOG(save_password, failed, LOG_LEVEL_ERROR, __SDFILE__, __LINE__, ADSL_DIAL_NOT_SAVE_PASS);

       // begin dial
       result = ras_dial(NULL, phone_book_path, &dial_params, NULL, NULL, &ras_conn);
       M_GTIF_WITH_LOG(result 
== 0, failed, LOG_LEVEL_ERROR, __SDFILE__, __LINE__, ADSL_DIAL_FAILED, result);
       M_GTIF_WITH_LOG(ras_conn 
!= NULL, failed, LOG_LEVEL_ERROR, __SDFILE__, __LINE__, ADSL_DIAL_CONN_NULL);

       *adsl_conn = ras_conn;

       LeaveCriticalSection(&sdc_cs_adsl);
       
return TRUE;
    failed:
       
*adsl_conn = NULL;
       LeaveCriticalSection(
&sdc_cs_adsl);
       
return FALSE;
    }

    BOOL adsl_hangup(HRASCONN adsl_conn)
    {
       DWORD result, errcode;
       FN_RAS_HANGUP ras_hangup;

       M_RETURN_VAL_IF_FAIL(adsl_conn != NULL, FALSE);
       M_RETURN_VAL_IF_FAIL(logger_is_enabled(), FALSE);

       EnterCriticalSection(&sdc_cs_adsl);
       
// load rasapi32.dll
       if (ras_module == NULL) {
          ras_module 
= LoadLibrary(ADSL_RASAPI32_DLL);
          
if (ras_module == NULL) {
             GET_ERROR_CODE(errcode);
             M_GTIF_WITH_LOG(FALSE, failed, LOG_LEVEL_ERROR, __SDFILE__, __LINE__, ADSL_LOAD_DLL_FAILED, utils_format_error_string(errcode));
          }
       }

       // get function address
       ras_hangup = (FN_RAS_HANGUP)GetProcAddress(ras_module, "RasHangUpW");
       
if (ras_hangup == NULL) {
          GET_ERROR_CODE(errcode);
          M_GTIF_WITH_LOG(FALSE, failed, LOG_LEVEL_ERROR, __SDFILE__, __LINE__, ADSL_GET_FN_HANGUP_FAILED, utils_format_error_string(errcode));
       }

       // hangup the connection
       result = ras_hangup(adsl_conn);
       M_GTIF_WITH_LOG(result 
== 0, failed, LOG_LEVEL_ERROR, __SDFILE__, __LINE__, ADSL_HANGUP_FAILED, result);

       // Sleep 100ms to make other threads work, this makes RasHangUp success
       Sleep(100);

       LeaveCriticalSection(&sdc_cs_adsl);
       
return TRUE;
    failed:
       LeaveCriticalSection(
&sdc_cs_adsl);
       
return FALSE;
    }

 

抱歉!评论已关闭.