zoukankan      html  css  js  c++  java
  • Windows下ADSL的操作编程 枚举ADSL连接、拨号、挂断

    最后面有完整的源代码,在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;
        }
  • 相关阅读:
    中国天气网数据获取
    雪球数据的定时爬取
    爬虫下载中间件
    简书全站CrawlSpider爬取 mysql异步保存
    房天下新房和二手房
    多线程
    selenium+chromdriver 动态网页的爬虫
    汽车之家下载文件和图片
    re正则
    532.数组中的K-diff数对
  • 原文地址:https://www.cnblogs.com/super119/p/2011351.html
Copyright © 2011-2022 走看看