dialup.cpp

来自「A*算法 A*算法 A*算法 A*算法A*算法A*算法」· C++ 代码 · 共 1,333 行 · 第 1/3 页

CPP
1,333
字号
        ms_dialer = NULL;

        return false;
    }

    // for async dialing, we're not yet connected
    if ( !async )
    {
        ms_isConnected = true;
    }

    return true;
}

bool wxDialUpManagerMSW::IsDialing() const
{
    return GetDialer() != NULL;
}

bool wxDialUpManagerMSW::CancelDialing()
{
    if ( !GetDialer() )
    {
        // silently ignore
        return false;
    }

    wxASSERT_MSG( ms_hRasConnection, wxT("dialing but no connection?") );

    ms_dialer = NULL;

    return HangUp();
}

bool wxDialUpManagerMSW::HangUp()
{
    wxCHECK_MSG( IsOk(), false, wxT("using uninitialized wxDialUpManager") );

    // we may terminate either the connection we initiated or another one which
    // is active now
    HRASCONN hRasConn;
    if ( ms_hRasConnection )
    {
        hRasConn = ms_hRasConnection;

        ms_hRasConnection = 0;
    }
    else
    {
        hRasConn = FindActiveConnection();
    }

    if ( !hRasConn )
    {
        wxLogError(_("Cannot hang up - no active dialup connection."));

        return false;
    }

    // note that it's not an error if the connection had been already
    // terminated
    const DWORD dwRet = ms_pfnRasHangUp(hRasConn);
    if ( dwRet != 0 && dwRet != ERROR_NO_CONNECTION )
    {
        wxLogError(_("Failed to terminate the dialup connection: %s"),
                   GetErrorString(dwRet).c_str());
    }

    ms_isConnected = false;

    return true;
}

bool wxDialUpManagerMSW::IsAlwaysOnline() const
{
    // assume no permanent connection by default
    bool isAlwaysOnline = false;

    // try to use WinInet functions

    // NB: we could probably use wxDynamicLibrary here just as well,
    //     but we allow multiple instances of wxDialUpManagerMSW so
    //     we might as well use the ref counted version here too.

    wxDynamicLibrary hDll(_T("WININET"));
    if ( hDll.IsLoaded() )
    {
        typedef BOOL (WINAPI *INTERNETGETCONNECTEDSTATE)(LPDWORD, DWORD);
        INTERNETGETCONNECTEDSTATE pfnInternetGetConnectedState;

        #define RESOLVE_FUNCTION(type, name) \
            pfn##name = (type)hDll.GetSymbol(_T(#name))

        RESOLVE_FUNCTION(INTERNETGETCONNECTEDSTATE, InternetGetConnectedState);

        if ( pfnInternetGetConnectedState )
        {
            DWORD flags = 0;
            if ( pfnInternetGetConnectedState(&flags, 0 /* reserved */) )
            {
                // there is some connection to the net, see of which type
                isAlwaysOnline = (flags & (INTERNET_CONNECTION_LAN |
                                           INTERNET_CONNECTION_PROXY)) != 0;
            }
            //else: no Internet connection at all
        }
    }

    return isAlwaysOnline;
}

bool wxDialUpManagerMSW::IsOnline() const
{
    wxCHECK_MSG( IsOk(), false, wxT("using uninitialized wxDialUpManager") );

    if ( IsAlwaysOnline() )
    {
        // always => now
        return true;
    }

    if ( ms_userSpecifiedOnlineStatus != -1 )
    {
        // user specified flag overrides our logic
        return ms_userSpecifiedOnlineStatus != 0;
    }
    else
    {
        // return true if there is at least one active connection
        return FindActiveConnection() != 0;
    }
}

void wxDialUpManagerMSW::SetOnlineStatus(bool isOnline)
{
    wxCHECK_RET( IsOk(), wxT("using uninitialized wxDialUpManager") );

    ms_userSpecifiedOnlineStatus = isOnline;
}

bool wxDialUpManagerMSW::EnableAutoCheckOnlineStatus(size_t nSeconds)
{
    wxCHECK_MSG( IsOk(), false, wxT("using uninitialized wxDialUpManager") );

    if ( m_autoCheckLevel++ )
    {
        // already checking
        return true;
    }

    bool ok = ms_pfnRasConnectionNotification != 0;

    if ( ok )
    {
        // we're running under NT 4.0, Windows 98 or later and can use
        // RasConnectionNotification() to be notified by a secondary thread

        // first, see if we don't have this thread already running
        if ( m_hThread != 0 )
        {
            if ( ::ResumeThread(m_hThread) != (DWORD)-1 )
                return true;

            // we're leaving a zombie thread... but what else can we do?
            wxLogLastError(wxT("ResumeThread(RasThread)"));

            ok = false;
        }
    }

    // create all the stuff we need to be notified about RAS connection
    // status change

    if ( ok )
    {
        // first create an event to wait on
        m_data->hEventRas = ::CreateEvent
                            (
                             NULL,      // security attribute (default)
                             FALSE,     // manual reset (no, it is automatic)
                             FALSE,     // initial state (not signaled)
                             NULL       // name (no)
                            );
        if ( !m_data->hEventRas )
        {
            wxLogLastError(wxT("CreateEvent(RasStatus)"));

            ok = false;
        }
    }

    if ( ok )
    {
        // create the event we use to quit the thread: using a manual event
        // here avoids problems with missing the event if wxDialUpManagerMSW
        // is created and destroyed immediately, before wxRasStatusWindowProc
        // starts waiting on the event
        m_data->hEventQuit = ::CreateEvent
                             (
                                NULL,   // default security
                                TRUE,   // manual event
                                FALSE,  // initially non signalled
                                NULL    // nameless
                             );
        if ( !m_data->hEventQuit )
        {
            wxLogLastError(wxT("CreateEvent(RasThreadQuit)"));

            CleanUpThreadData();

            ok = false;
        }
    }

    if ( ok && !ms_hwndRas )
    {
        // create a hidden window to receive notification about connections
        // status change
        ms_hwndRas = wxCreateHiddenWindow
                     (
                        &gs_classForDialUpWindow,
                        wxMSWDIALUP_WNDCLASSNAME,
                        wxRasStatusWindowProc
                     );
        if ( !ms_hwndRas )
        {
            wxLogLastError(wxT("CreateWindow(RasHiddenWindow)"));

            CleanUpThreadData();

            ok = false;
        }
    }

    m_data->hWnd = ms_hwndRas;

    if ( ok )
    {
        // start the secondary thread
        m_data->dialUpManager = this;

        DWORD tid;
        m_hThread = CreateThread
                    (
                     NULL,
                     0,
                     (LPTHREAD_START_ROUTINE)wxRasMonitorThread,
                     (void *)m_data,
                     0,
                     &tid
                    );

        if ( !m_hThread )
        {
            wxLogLastError(wxT("CreateThread(RasStatusThread)"));

            CleanUpThreadData();
        }
    }

    if ( ok )
    {
        // start receiving RAS notifications
        DWORD dwRet = ms_pfnRasConnectionNotification
                      (
                        (HRASCONN)INVALID_HANDLE_VALUE,
                        m_data->hEventRas,
                        3 /* RASCN_Connection | RASCN_Disconnection */
                      );

        if ( dwRet != 0 )
        {
            wxLogDebug(wxT("RasConnectionNotification() failed: %s"),
                       GetErrorString(dwRet).c_str());

            CleanUpThreadData();
        }
        else
        {
            return true;
        }
    }

    // we're running under Windows 95 and have to poll ourselves
    // (or, alternatively, the code above for NT/98 failed)
    m_timerStatusPolling.Stop();
    if ( nSeconds == 0 )
    {
        // default value
        nSeconds = 60;
    }
    m_timerStatusPolling.Start(nSeconds * 1000);

    return true;
}

void wxDialUpManagerMSW::DisableAutoCheckOnlineStatus()
{
    wxCHECK_RET( IsOk(), wxT("using uninitialized wxDialUpManager") );

    if ( --m_autoCheckLevel )
    {
        // still checking
        return;
    }

    if ( m_hThread )
    {
        // we have running secondary thread, it's just enough to suspend it
        if ( SuspendThread(m_hThread) == (DWORD)-1 )
        {
            wxLogLastError(wxT("SuspendThread(RasThread)"));
        }
    }
    else
    {
        // even simpler - just stop the timer
        m_timerStatusPolling.Stop();
    }
}

// ----------------------------------------------------------------------------
// stubs which don't do anything in MSW version
// ----------------------------------------------------------------------------

void wxDialUpManagerMSW::SetWellKnownHost(const wxString& WXUNUSED(hostname),
                                          int WXUNUSED(port))
{
    wxCHECK_RET( IsOk(), wxT("using uninitialized wxDialUpManager") );

    // nothing to do - we don't use this
}

void wxDialUpManagerMSW::SetConnectCommand(const wxString& WXUNUSED(dial),
                                           const wxString& WXUNUSED(hangup))
{
    wxCHECK_RET( IsOk(), wxT("using uninitialized wxDialUpManager") );

    // nothing to do - we don't use this
}

// ----------------------------------------------------------------------------
// callbacks
// ----------------------------------------------------------------------------

static DWORD wxRasMonitorThread(wxRasThreadData *data)
{
    HANDLE handles[2];
    handles[0] = data->hEventRas;
    handles[1] = data->hEventQuit;

    bool cont = true;
    while ( cont )
    {
        DWORD dwRet = ::WaitForMultipleObjects(2, handles, FALSE, INFINITE);

        switch ( dwRet )
        {
            case WAIT_OBJECT_0:
                // RAS connection status changed
                SendMessage(data->hWnd, wxWM_RAS_STATUS_CHANGED,
                            0, (LPARAM)data);
                break;

            case WAIT_OBJECT_0 + 1:
                cont = false;
                break;

            default:
                wxFAIL_MSG( _T("unexpected return of WaitForMultipleObjects()") );
                // fall through

            case WAIT_FAILED:
#ifdef __WXDEBUG__
                // using wxLogLastError() from here is dangerous: we risk to
                // deadlock the main thread if wxLog sends output to GUI
                DWORD err = GetLastError();
                wxMessageOutputDebug dbg;
                dbg.Printf
                (
                    wxT("WaitForMultipleObjects(RasMonitor) failed: 0x%08lx (%s)"),
                    err,
                    wxSysErrorMsg(err)
                );
#endif // __WXDEBUG__

                // no sense in continuing, who knows if the handles we're
                // waiting for even exist yet...
                return (DWORD)-1;
        }
    }

    // we don't need it any more now and if this thread ran, it is our
    // responsability to free the data
    delete data;

    return 0;
}

static LRESULT APIENTRY wxRasStatusWindowProc(HWND hWnd, UINT message,
                                              WPARAM wParam, LPARAM lParam)
{
    switch ( message )
    {
        case wxWM_RAS_STATUS_CHANGED:
            {
                wxRasThreadData *data = (wxRasThreadData *)lParam;
                data->dialUpManager->OnConnectStatusChange();
            }
            break;

        case wxWM_RAS_DIALING_PROGRESS:
            {
                wxDialUpManagerMSW *dialMan = wxDialUpManagerMSW::GetDialer();

                dialMan->OnDialProgress((RASCONNSTATE)wParam, lParam);
            }
            break;

        default:
            return ::DefWindowProc(hWnd, message, wParam, lParam);
    }

    return 0;
}

static void WINAPI wxRasDialFunc(UINT WXUNUSED(unMsg),
                                 RASCONNSTATE rasconnstate,
                                 DWORD dwError)
{
    wxDialUpManagerMSW *dialUpManager = wxDialUpManagerMSW::GetDialer();

    wxCHECK_RET( dialUpManager, wxT("who started to dial then?") );

    SendMessage(wxDialUpManagerMSW::GetRasWindow(), wxWM_RAS_DIALING_PROGRESS,
                rasconnstate, dwError);
}

#endif // __BORLANDC__

#endif // wxUSE_DIALUP_MANAGER

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?