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连接的。
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;
}
* 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;
}