dialup.cpp
来自「A*算法 A*算法 A*算法 A*算法A*算法A*算法」· C++ 代码 · 共 1,333 行 · 第 1/3 页
CPP
1,333 行
// keep your preprocessor name space clean
#undef RESOLVE_RAS_FUNCTION
#undef RESOLVE_OPTIONAL_RAS_FUNCTION
exit:
if ( funcName )
{
static const wxChar *msg = wxTRANSLATE(
"The version of remote access service (RAS) installed on this machine is too\
old, please upgrade (the following required function is missing: %s)."
);
wxLogError(wxGetTranslation(msg), funcName);
m_dllRas.Unload();
return;
}
}
// enable auto check by default
EnableAutoCheckOnlineStatus(0);
}
wxDialUpManagerMSW::~wxDialUpManagerMSW()
{
CleanUpThreadData();
}
// ----------------------------------------------------------------------------
// helper functions
// ----------------------------------------------------------------------------
wxString wxDialUpManagerMSW::GetErrorString(DWORD error)
{
wxChar buffer[512]; // this should be more than enough according to MS docs
DWORD dwRet = ms_pfnRasGetErrorString(error, buffer, WXSIZEOF(buffer));
switch ( dwRet )
{
case ERROR_INVALID_PARAMETER:
// this was a standard Win32 error probably
return wxString(wxSysErrorMsg(error));
default:
{
wxLogSysError(dwRet,
_("Failed to retrieve text of RAS error message"));
wxString msg;
msg.Printf(_("unknown error (error code %08x)."), error);
return msg;
}
case 0:
// we want the error message to start from a lower case letter
buffer[0] = (wxChar)wxTolower(buffer[0]);
return wxString(buffer);
}
}
HRASCONN wxDialUpManagerMSW::FindActiveConnection()
{
// enumerate connections
DWORD cbBuf = sizeof(RASCONN);
LPRASCONN lpRasConn = (LPRASCONN)malloc(cbBuf);
if ( !lpRasConn )
{
// out of memory
return 0;
}
lpRasConn->dwSize = sizeof(RASCONN);
DWORD nConnections = 0;
DWORD dwRet = ERROR_BUFFER_TOO_SMALL;
while ( dwRet == ERROR_BUFFER_TOO_SMALL )
{
dwRet = ms_pfnRasEnumConnections(lpRasConn, &cbBuf, &nConnections);
if ( dwRet == ERROR_BUFFER_TOO_SMALL )
{
LPRASCONN lpRasConnOld = lpRasConn;
lpRasConn = (LPRASCONN)realloc(lpRasConn, cbBuf);
if ( !lpRasConn )
{
// out of memory
free(lpRasConnOld);
return 0;
}
}
else if ( dwRet == 0 )
{
// ok, success
break;
}
else
{
// an error occurred
wxLogError(_("Cannot find active dialup connection: %s"),
GetErrorString(dwRet).c_str());
return 0;
}
}
HRASCONN hrasconn;
switch ( nConnections )
{
case 0:
// no connections
hrasconn = 0;
break;
default:
// more than 1 connection - we don't know what to do with this
// case, so give a warning but continue (taking the first
// connection) - the warning is really needed because this function
// is used, for example, to select the connection to hang up and so
// we may hang up the wrong connection here...
wxLogWarning(_("Several active dialup connections found, choosing one randomly."));
// fall through
case 1:
// exactly 1 connection, great
hrasconn = lpRasConn->hrasconn;
}
free(lpRasConn);
return hrasconn;
}
void wxDialUpManagerMSW::CleanUpThreadData()
{
if ( m_hThread )
{
if ( !SetEvent(m_data->hEventQuit) )
{
wxLogLastError(_T("SetEvent(RasThreadQuit)"));
}
else // sent quit request to the background thread
{
// the thread still needs m_data so we can't free it here, rather
// let the thread do it itself
m_data = NULL;
}
CloseHandle(m_hThread);
m_hThread = 0;
}
if ( m_data )
{
delete m_data;
m_data = NULL;
}
}
// ----------------------------------------------------------------------------
// connection status
// ----------------------------------------------------------------------------
void wxDialUpManagerMSW::CheckRasStatus()
{
// use int, not bool to compare with -1
int isConnected = FindActiveConnection() != 0;
if ( isConnected != ms_isConnected )
{
if ( ms_isConnected != -1 )
{
// notify the program
NotifyApp(isConnected != 0);
}
// else: it's the first time we're called, just update the flag
ms_isConnected = isConnected;
}
}
void wxDialUpManagerMSW::NotifyApp(bool connected, bool fromOurselves) const
{
wxDialUpEvent event(connected, fromOurselves);
(void)wxTheApp->ProcessEvent(event);
}
// this function is called whenever the status of any RAS connection on this
// machine changes by RAS itself
void wxDialUpManagerMSW::OnConnectStatusChange()
{
// we know that status changed, but we don't know whether we're connected
// or not - so find it out
CheckRasStatus();
}
// this function is called by our callback which we give to RasDial() when
// calling it asynchronously
void wxDialUpManagerMSW::OnDialProgress(RASCONNSTATE rasconnstate,
DWORD dwError)
{
if ( !GetDialer() )
{
// this probably means that CancelDialing() was called and we get
// "disconnected" notification
return;
}
// we're only interested in 2 events: connected and disconnected
if ( dwError )
{
wxLogError(_("Failed to establish dialup connection: %s"),
GetErrorString(dwError).c_str());
// we should still call RasHangUp() if we got a non 0 connection
if ( ms_hRasConnection )
{
ms_pfnRasHangUp(ms_hRasConnection);
ms_hRasConnection = 0;
}
ms_dialer = NULL;
NotifyApp(false /* !connected */, true /* we dialed ourselves */);
}
else if ( rasconnstate == RASCS_Connected )
{
ms_isConnected = true;
ms_dialer = NULL;
NotifyApp(true /* connected */, true /* we dialed ourselves */);
}
}
// ----------------------------------------------------------------------------
// implementation of wxDialUpManager functions
// ----------------------------------------------------------------------------
bool wxDialUpManagerMSW::IsOk() const
{
return m_dllRas.IsLoaded();
}
size_t wxDialUpManagerMSW::GetISPNames(wxArrayString& names) const
{
// fetch the entries
DWORD size = sizeof(RASENTRYNAME);
RASENTRYNAME *rasEntries = (RASENTRYNAME *)malloc(size);
rasEntries->dwSize = sizeof(RASENTRYNAME);
DWORD nEntries;
DWORD dwRet;
do
{
dwRet = ms_pfnRasEnumEntries
(
NULL, // reserved
NULL, // default phone book (or all)
rasEntries, // [out] buffer for the entries
&size, // [in/out] size of the buffer
&nEntries // [out] number of entries fetched
);
if ( dwRet == ERROR_BUFFER_TOO_SMALL )
{
// reallocate the buffer
rasEntries = (RASENTRYNAME *)realloc(rasEntries, size);
}
else if ( dwRet != 0 )
{
// some other error - abort
wxLogError(_("Failed to get ISP names: %s"),
GetErrorString(dwRet).c_str());
free(rasEntries);
return 0u;
}
}
while ( dwRet != 0 );
// process them
names.Empty();
for ( size_t n = 0; n < (size_t)nEntries; n++ )
{
names.Add(rasEntries[n].szEntryName);
}
free(rasEntries);
// return the number of entries
return names.GetCount();
}
bool wxDialUpManagerMSW::Dial(const wxString& nameOfISP,
const wxString& username,
const wxString& password,
bool async)
{
// check preconditions
wxCHECK_MSG( IsOk(), false, wxT("using uninitialized wxDialUpManager") );
if ( ms_hRasConnection )
{
wxFAIL_MSG(wxT("there is already an active connection"));
return true;
}
// get the default ISP if none given
wxString entryName(nameOfISP);
if ( !entryName )
{
wxArrayString names;
size_t count = GetISPNames(names);
switch ( count )
{
case 0:
// no known ISPs, abort
wxLogError(_("Failed to connect: no ISP to dial."));
return false;
case 1:
// only one ISP, choose it
entryName = names[0u];
break;
default:
// several ISPs, let the user choose
{
wxString *strings = new wxString[count];
for ( size_t i = 0; i < count; i++ )
{
strings[i] = names[i];
}
entryName = wxGetSingleChoice
(
_("Choose ISP to dial"),
_("Please choose which ISP do you want to connect to"),
count,
strings
);
delete [] strings;
if ( !entryName )
{
// cancelled by user
return false;
}
}
}
}
RASDIALPARAMS rasDialParams;
rasDialParams.dwSize = sizeof(rasDialParams);
wxStrncpy(rasDialParams.szEntryName, entryName, RAS_MaxEntryName);
// do we have the username and password?
if ( !username || !password )
{
BOOL gotPassword;
DWORD dwRet = ms_pfnRasGetEntryDialParams
(
NULL, // default phonebook
&rasDialParams, // [in/out] the params of this entry
&gotPassword // [out] did we get password?
);
if ( dwRet != 0 )
{
wxLogError(_("Failed to connect: missing username/password."));
return false;
}
}
else
{
wxStrncpy(rasDialParams.szUserName, username, UNLEN);
wxStrncpy(rasDialParams.szPassword, password, PWLEN);
}
// default values for other fields
rasDialParams.szPhoneNumber[0] = '\0';
rasDialParams.szCallbackNumber[0] = '\0';
rasDialParams.szCallbackNumber[0] = '\0';
rasDialParams.szDomain[0] = '*';
rasDialParams.szDomain[1] = '\0';
// apparently, this is not really necessary - passing NULL instead of the
// phone book has the same effect
#if 0
wxString phoneBook;
if ( wxGetOsVersion() == wxWINDOWS_NT )
{
// first get the length
UINT nLen = ::GetSystemDirectory(NULL, 0);
nLen++;
if ( !::GetSystemDirectory(phoneBook.GetWriteBuf(nLen), nLen) )
{
wxLogSysError(_("Cannot find the location of address book file"));
}
phoneBook.UngetWriteBuf();
// this is the default phone book
phoneBook << "\\ras\\rasphone.pbk";
}
#endif // 0
// TODO may be we should disable auto check while async dialing is in
// progress?
ms_dialer = this;
DWORD dwRet = ms_pfnRasDial
(
NULL, // no extended features
NULL, // default phone book file (NT only)
&rasDialParams,
0, // use callback for notifications
async ? (void *)wxRasDialFunc // cast needed for gcc 3.1
: 0, // no notifications, sync operation
&ms_hRasConnection
);
if ( dwRet != 0 )
{
// can't pass a wxWCharBuffer through ( ... )
wxLogError(_("Failed to %s dialup connection: %s"),
wxString(async ? _("initiate") : _("establish")).c_str(),
GetErrorString(dwRet).c_str());
// we should still call RasHangUp() if we got a non 0 connection
if ( ms_hRasConnection )
{
ms_pfnRasHangUp(ms_hRasConnection);
ms_hRasConnection = 0;
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?