]> git.saurik.com Git - wxWidgets.git/blobdiff - src/msw/dialup.cpp
applying OSAF patch for "toolbar selection not correct on Mac after calling Realize...
[wxWidgets.git] / src / msw / dialup.cpp
index 3dae96970fc57d31ef1be302126446fac88c493c..04ee582b81f23c26f6ed95e24b22dd2b770d4563 100644 (file)
     #pragma hdrstop
 #endif
 
-// these functions require Win32
-#if defined(__WIN16__) && wxUSE_DIALUP_MANAGER
-    #undef wxUSE_DIALUP_MANAGER
-    #define wxUSE_DIALUP_MANAGER 0
-#endif // wxUSE_DIALUP_MANAGER && Win16
-
 #if wxUSE_DIALUP_MANAGER
 
 #ifndef WX_PRECOMP
 DEFINE_EVENT_TYPE(wxEVT_DIALUP_CONNECTED)
 DEFINE_EVENT_TYPE(wxEVT_DIALUP_DISCONNECTED)
 
-// Doesn't yet compile under VC++ 4, BC++, Watcom C++: no wininet.h
-#if !defined(__BORLANDC__) && \
+// Doesn't yet compile under VC++ 4, BC++, Watcom C++,
+// Wine: no wininet.h
+#if (!defined(__BORLANDC__) || (__BORLANDC__>=0x550)) && \
     (!defined(__GNUWIN32__) || wxCHECK_W32API_VERSION(0, 5)) && \
     !defined(__GNUWIN32_OLD__) && \
-    !defined(__WATCOMC__) && \
+    !defined(__WINE__) && \
     (!defined(__VISUALC__) || (__VISUALC__ >= 1020))
 
 #include <ras.h>
@@ -137,13 +132,26 @@ struct WXDLLEXPORT wxRasThreadData
     wxRasThreadData()
     {
         hWnd = 0;
-        hEventRas = hEventQuit = INVALID_HANDLE_VALUE;
+        hEventRas =
+        hEventQuit = 0;
         dialUpManager = NULL;
     }
 
+    ~wxRasThreadData()
+    {
+        if ( hWnd )
+            DestroyWindow(hWnd);
+
+        if ( hEventQuit )
+            CloseHandle(hEventQuit);
+
+        if ( hEventRas )
+            CloseHandle(hEventRas);
+    }
+
     HWND    hWnd;       // window to send notifications to
-    HANDLE  hEventRas,  // event which RAS signals when status changes
-            hEventQuit; // event which we signal when we terminate
+    HANDLE  hEventRas,  // automatic event which RAS signals when status changes
+            hEventQuit; // manual event which we signal when we terminate
 
     class WXDLLEXPORT wxDialUpManagerMSW *dialUpManager;  // the owner
 };
@@ -171,7 +179,7 @@ public:
     virtual bool HangUp();
     virtual bool IsAlwaysOnline() const;
     virtual bool IsOnline() const;
-    virtual void SetOnlineStatus(bool isOnline = TRUE);
+    virtual void SetOnlineStatus(bool isOnline = true);
     virtual bool EnableAutoCheckOnlineStatus(size_t nSeconds);
     virtual void DisableAutoCheckOnlineStatus();
     virtual void SetWellKnownHost(const wxString& hostname, int port);
@@ -197,11 +205,15 @@ private:
     static HRASCONN FindActiveConnection();
 
     // notify the application about status change
-    void NotifyApp(bool connected, bool fromOurselves = FALSE) const;
+    void NotifyApp(bool connected, bool fromOurselves = false) const;
 
     // destroy the thread data and the thread itself
     void CleanUpThreadData();
 
+    // number of times EnableAutoCheckOnlineStatus() had been called minus the
+    // number of times DisableAutoCheckOnlineStatus() had been called
+    int m_autoCheckLevel;
+
     // timer used for polling RAS status
     class WXDLLEXPORT RasTimer : public wxTimer
     {
@@ -213,6 +225,8 @@ private:
 
     private:
         wxDialUpManagerMSW *m_dialUpManager;
+
+        DECLARE_NO_COPY_CLASS(RasTimer)
     } m_timerStatusPolling;
 
     // thread handle for the thread sitting on connection change event
@@ -220,10 +234,10 @@ private:
 
     // data used by this thread and our hidden window to send messages between
     // each other
-    wxRasThreadData m_data;
+    wxRasThreadData *m_data;
 
     // the handle of rasapi32.dll when it's loaded
-    wxPluginManager m_dllRas;
+    wxDynamicLibrary m_dllRas;
 
     // the hidden window we use for passing messages between threads
     static HWND ms_hwndRas;
@@ -231,12 +245,6 @@ private:
     // the handle of the connection we initiated or 0 if none
     static HRASCONN ms_hRasConnection;
 
-    // FIXME: There is probably no reason these really need to
-    //        be static anymore since the dll refcounting is
-    //        handled by wxPluginManager now.  Whether or not
-    //        we still _want_ them to be static is another
-    //        issue entirely..
-
     // the pointers to RAS functions
     static RASDIAL ms_pfnRasDial;
     static RASENUMCONNECTIONS ms_pfnRasEnumConnections;
@@ -266,12 +274,10 @@ private:
     // this flag tells us if we're online
     static int ms_isConnected;
 
-    // this flag is the result of the call to IsAlwaysOnline() (-1 if not
-    // called yet)
-    static int ms_isAlwaysOnline;
-
     // this flag tells us whether a call to RasDial() is in progress
     static wxDialUpManagerMSW *ms_dialer;
+
+    DECLARE_NO_COPY_CLASS(wxDialUpManagerMSW)
 };
 
 // ----------------------------------------------------------------------------
@@ -321,7 +327,6 @@ RASCONNECTIONNOTIFICATION wxDialUpManagerMSW::ms_pfnRasConnectionNotification =
 
 int wxDialUpManagerMSW::ms_userSpecifiedOnlineStatus = -1;
 int wxDialUpManagerMSW::ms_isConnected = -1;
-int wxDialUpManagerMSW::ms_isAlwaysOnline = -1;
 wxDialUpManagerMSW *wxDialUpManagerMSW::ms_dialer = NULL;
 
 // ----------------------------------------------------------------------------
@@ -340,11 +345,13 @@ wxDialUpManager *wxDialUpManager::Create()
 #endif // VC++
 
 wxDialUpManagerMSW::wxDialUpManagerMSW()
-                  : m_timerStatusPolling(this)
-                  , m_dllRas(_T("RASAPI32"))
+                  : m_timerStatusPolling(this),
+                    m_dllRas(_T("RASAPI32"))
 {
     // initialize our data
+    m_autoCheckLevel = 0;
     m_hThread = 0;
+    m_data = new wxRasThreadData;
 
     if ( !m_dllRas.IsLoaded() )
     {
@@ -453,7 +460,7 @@ wxString wxDialUpManagerMSW::GetErrorString(DWORD error)
 
         case 0:
             // we want the error message to start from a lower case letter
-            buffer[0] = wxTolower(buffer[0]);
+            buffer[0] = (wxChar)wxTolower(buffer[0]);
 
             return wxString(buffer);
     }
@@ -537,35 +544,26 @@ void wxDialUpManagerMSW::CleanUpThreadData()
 {
     if ( m_hThread )
     {
-        if ( !SetEvent(m_data.hEventQuit) )
+        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.hWnd )
+    if ( m_data )
     {
-        DestroyWindow(m_data.hWnd);
-
-        m_data.hWnd = 0;
-    }
-
-    if ( m_data.hEventQuit )
-    {
-        CloseHandle(m_data.hEventQuit);
-
-        m_data.hEventQuit = 0;
-    }
-
-    if ( m_data.hEventRas )
-    {
-        CloseHandle(m_data.hEventRas);
-
-        m_data.hEventRas = 0;
+        delete m_data;
+        m_data = NULL;
     }
 }
 
@@ -632,14 +630,14 @@ void wxDialUpManagerMSW::OnDialProgress(RASCONNSTATE rasconnstate,
 
         ms_dialer = NULL;
 
-        NotifyApp(FALSE /* !connected */, TRUE /* we dialed ourselves */);
+        NotifyApp(false /* !connected */, true /* we dialed ourselves */);
     }
     else if ( rasconnstate == RASCS_Connected )
     {
-        ms_isConnected = TRUE;
+        ms_isConnected = true;
         ms_dialer = NULL;
 
-        NotifyApp(TRUE /* connected */, TRUE /* we dialed ourselves */);
+        NotifyApp(true /* connected */, true /* we dialed ourselves */);
     }
 }
 
@@ -709,13 +707,13 @@ bool wxDialUpManagerMSW::Dial(const wxString& nameOfISP,
                               bool async)
 {
     // check preconditions
-    wxCHECK_MSG( IsOk(), FALSE, wxT("using uninitialized wxDialUpManager") );
+    wxCHECK_MSG( IsOk(), false, wxT("using uninitialized wxDialUpManager") );
 
     if ( ms_hRasConnection )
     {
         wxFAIL_MSG(wxT("there is already an active connection"));
 
-        return TRUE;
+        return true;
     }
 
     // get the default ISP if none given
@@ -730,7 +728,7 @@ bool wxDialUpManagerMSW::Dial(const wxString& nameOfISP,
                 // no known ISPs, abort
                 wxLogError(_("Failed to connect: no ISP to dial."));
 
-                return FALSE;
+                return false;
 
             case 1:
                 // only one ISP, choose it
@@ -759,7 +757,7 @@ bool wxDialUpManagerMSW::Dial(const wxString& nameOfISP,
                     if ( !entryName )
                     {
                         // cancelled by user
-                        return FALSE;
+                        return false;
                     }
                 }
         }
@@ -784,7 +782,7 @@ bool wxDialUpManagerMSW::Dial(const wxString& nameOfISP,
         {
             wxLogError(_("Failed to connect: missing username/password."));
 
-            return FALSE;
+            return false;
         }
     }
     else
@@ -855,16 +853,16 @@ bool wxDialUpManagerMSW::Dial(const wxString& nameOfISP,
 
         ms_dialer = NULL;
 
-        return FALSE;
+        return false;
     }
 
     // for async dialing, we're not yet connected
     if ( !async )
     {
-        ms_isConnected = TRUE;
+        ms_isConnected = true;
     }
 
-    return TRUE;
+    return true;
 }
 
 bool wxDialUpManagerMSW::IsDialing() const
@@ -877,7 +875,7 @@ bool wxDialUpManagerMSW::CancelDialing()
     if ( !GetDialer() )
     {
         // silently ignore
-        return FALSE;
+        return false;
     }
 
     wxASSERT_MSG( ms_hRasConnection, wxT("dialing but no connection?") );
@@ -889,7 +887,7 @@ bool wxDialUpManagerMSW::CancelDialing()
 
 bool wxDialUpManagerMSW::HangUp()
 {
-    wxCHECK_MSG( IsOk(), FALSE, wxT("using uninitialized wxDialUpManager") );
+    wxCHECK_MSG( IsOk(), false, wxT("using uninitialized wxDialUpManager") );
 
     // we may terminate either the connection we initiated or another one which
     // is active now
@@ -909,7 +907,7 @@ bool wxDialUpManagerMSW::HangUp()
     {
         wxLogError(_("Cannot hang up - no active dialup connection."));
 
-        return FALSE;
+        return false;
     }
 
     DWORD dwRet = ms_pfnRasHangUp(hRasConn);
@@ -919,27 +917,23 @@ bool wxDialUpManagerMSW::HangUp()
                    GetErrorString(dwRet).c_str());
     }
 
-    ms_isConnected = FALSE;
+    ms_isConnected = false;
 
-    return TRUE;
+    return true;
 }
 
 bool wxDialUpManagerMSW::IsAlwaysOnline() const
 {
-    // we cache the result (presumably this won't change while the program is
-    // running!)
-    if ( ms_isAlwaysOnline != -1 )
-    {
-        return ms_isAlwaysOnline != 0;
-    }
+    // assume no permanent connection by default
+    bool isAlwaysOnline = false;
 
-    // try to use WinInet function first
+    // 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.
 
-    wxPluginManager hDll(_T("WININET"));
+    wxDynamicLibrary hDll(_T("WININET"));
     if ( hDll.IsLoaded() )
     {
         typedef BOOL (WINAPI *INTERNETGETCONNECTEDSTATE)(LPDWORD, DWORD);
@@ -956,44 +950,25 @@ bool wxDialUpManagerMSW::IsAlwaysOnline() const
             if ( pfnInternetGetConnectedState(&flags, 0 /* reserved */) )
             {
                 // there is some connection to the net, see of which type
-                ms_isAlwaysOnline = ((flags & INTERNET_CONNECTION_LAN) != 0)
-                                    || ((flags & INTERNET_CONNECTION_PROXY) != 0);
-            }
-            else
-            {
-                // no Internet connection at all
-                ms_isAlwaysOnline = FALSE;
+                isAlwaysOnline = (flags & (INTERNET_CONNECTION_LAN |
+                                           INTERNET_CONNECTION_PROXY)) != 0;
             }
+            //else: no Internet connection at all
         }
     }
 
-    // did we succeed with WinInet? if not, try something else
-    if ( ms_isAlwaysOnline == -1 )
-    {
-        if ( !IsOnline() )
-        {
-            // definitely no permanent connection because we are not connected
-            // now
-            ms_isAlwaysOnline = FALSE;
-        }
-        else
-        {
-            // of course, having a modem doesn't prevent us from having a
-            // permanent connection as well, but we have to guess somehow and
-            // it's probably more common that a system connected via a modem
-            // doesn't have any other net access, so:
-            ms_isAlwaysOnline = FALSE;
-        }
-    }
-
-    wxASSERT_MSG( ms_isAlwaysOnline != -1, wxT("logic error") );
-
-    return ms_isAlwaysOnline != 0;
+    return isAlwaysOnline;
 }
 
 bool wxDialUpManagerMSW::IsOnline() const
 {
-    wxCHECK_MSG( IsOk(), FALSE, wxT("using uninitialized wxDialUpManager") );
+    wxCHECK_MSG( IsOk(), false, wxT("using uninitialized wxDialUpManager") );
+
+    if ( IsAlwaysOnline() )
+    {
+        // always => now
+        return true;
+    }
 
     if ( ms_userSpecifiedOnlineStatus != -1 )
     {
@@ -1002,7 +977,7 @@ bool wxDialUpManagerMSW::IsOnline() const
     }
     else
     {
-        // return TRUE if there is at least one active connection
+        // return true if there is at least one active connection
         return FindActiveConnection() != 0;
     }
 }
@@ -1016,7 +991,13 @@ void wxDialUpManagerMSW::SetOnlineStatus(bool isOnline)
 
 bool wxDialUpManagerMSW::EnableAutoCheckOnlineStatus(size_t nSeconds)
 {
-    wxCHECK_MSG( IsOk(), FALSE, wxT("using uninitialized wxDialUpManager") );
+    wxCHECK_MSG( IsOk(), false, wxT("using uninitialized wxDialUpManager") );
+
+    if ( m_autoCheckLevel++ )
+    {
+        // already checking
+        return true;
+    }
 
     bool ok = ms_pfnRasConnectionNotification != 0;
 
@@ -1028,22 +1009,13 @@ bool wxDialUpManagerMSW::EnableAutoCheckOnlineStatus(size_t nSeconds)
         // first, see if we don't have this thread already running
         if ( m_hThread != 0 )
         {
-            DWORD dwSuspendCount = 2;
-            while ( dwSuspendCount > 1 )
-            {
-                dwSuspendCount = ResumeThread(m_hThread);
-                if ( dwSuspendCount == (DWORD)-1 )
-                {
-                    wxLogLastError(wxT("ResumeThread(RasThread)"));
+            if ( ::ResumeThread(m_hThread) != (DWORD)-1 )
+                return true;
 
-                    ok = FALSE;
-                }
-            }
+            // we're leaving a zombie thread... but what else can we do?
+            wxLogLastError(wxT("ResumeThread(RasThread)"));
 
-            if ( ok )
-            {
-                return TRUE;
-            }
+            ok = false;
         }
     }
 
@@ -1053,32 +1025,41 @@ bool wxDialUpManagerMSW::EnableAutoCheckOnlineStatus(size_t nSeconds)
     if ( ok )
     {
         // first create an event to wait on
-        m_data.hEventRas = CreateEvent
-                           (
+        m_data->hEventRas = ::CreateEvent
+                            (
                              NULL,      // security attribute (default)
-                             FALSE,     // manual reset (not)
+                             FALSE,     // manual reset (no, it is automatic)
                              FALSE,     // initial state (not signaled)
                              NULL       // name (no)
-                           );
-        if ( !m_data.hEventRas )
+                            );
+        if ( !m_data->hEventRas )
         {
             wxLogLastError(wxT("CreateEvent(RasStatus)"));
 
-            ok = FALSE;
+            ok = false;
         }
     }
 
     if ( ok )
     {
-        // create the event we use to quit the thread
-        m_data.hEventQuit = CreateEvent(NULL, FALSE, FALSE, NULL);
-        if ( !m_data.hEventQuit )
+        // 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;
+            ok = false;
         }
     }
 
@@ -1097,25 +1078,19 @@ bool wxDialUpManagerMSW::EnableAutoCheckOnlineStatus(size_t nSeconds)
 
             CleanUpThreadData();
 
-            ok = FALSE;
+            ok = false;
         }
 
         // and subclass it
-        FARPROC windowProc = MakeProcInstance
-                             (
-                              (FARPROC)wxRasStatusWindowProc,
-                              wxGetInstance()
-                             );
-
-        ::SetWindowLong(ms_hwndRas, GWL_WNDPROC, (LONG) windowProc);
+        wxSetWindowProc(ms_hwndRas, wxRasStatusWindowProc);
     }
 
-    m_data.hWnd = ms_hwndRas;
+    m_data->hWnd = ms_hwndRas;
 
     if ( ok )
     {
         // start the secondary thread
-        m_data.dialUpManager = this;
+        m_data->dialUpManager = this;
 
         DWORD tid;
         m_hThread = CreateThread
@@ -1123,7 +1098,7 @@ bool wxDialUpManagerMSW::EnableAutoCheckOnlineStatus(size_t nSeconds)
                      NULL,
                      0,
                      (LPTHREAD_START_ROUTINE)wxRasMonitorThread,
-                     (void *)&m_data,
+                     (void *)m_data,
                      0,
                      &tid
                     );
@@ -1142,7 +1117,7 @@ bool wxDialUpManagerMSW::EnableAutoCheckOnlineStatus(size_t nSeconds)
         DWORD dwRet = ms_pfnRasConnectionNotification
                       (
                         (HRASCONN)INVALID_HANDLE_VALUE,
-                        m_data.hEventRas,
+                        m_data->hEventRas,
                         3 /* RASCN_Connection | RASCN_Disconnection */
                       );
 
@@ -1155,7 +1130,7 @@ bool wxDialUpManagerMSW::EnableAutoCheckOnlineStatus(size_t nSeconds)
         }
         else
         {
-            return TRUE;
+            return true;
         }
     }
 
@@ -1169,13 +1144,19 @@ bool wxDialUpManagerMSW::EnableAutoCheckOnlineStatus(size_t nSeconds)
     }
     m_timerStatusPolling.Start(nSeconds * 1000);
 
-    return TRUE;
+    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
@@ -1221,10 +1202,10 @@ static DWORD wxRasMonitorThread(wxRasThreadData *data)
     handles[0] = data->hEventRas;
     handles[1] = data->hEventQuit;
 
-    bool cont = TRUE;
+    bool cont = true;
     while ( cont )
     {
-        DWORD dwRet = WaitForMultipleObjects(2, handles, FALSE, INFINITE);
+        DWORD dwRet = ::WaitForMultipleObjects(2, handles, FALSE, INFINITE);
 
         switch ( dwRet )
         {
@@ -1235,15 +1216,37 @@ static DWORD wxRasMonitorThread(wxRasThreadData *data)
                 break;
 
             case WAIT_OBJECT_0 + 1:
-                cont = FALSE;
+                cont = false;
                 break;
 
+            default:
+                wxFAIL_MSG( _T("unexpected return of WaitForMultipleObjects()") );
+                // fall through
+
             case WAIT_FAILED:
-                wxLogLastError(wxT("WaitForMultipleObjects(RasMonitor)"));
-                break;
+#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;
 }
 
@@ -1274,7 +1277,7 @@ static LRESULT APIENTRY wxRasStatusWindowProc(HWND hWnd, UINT message,
     return 0;
 }
 
-static void WINAPI wxRasDialFunc(UINT unMsg,
+static void WINAPI wxRasDialFunc(UINT WXUNUSED(unMsg),
                                  RASCONNSTATE rasconnstate,
                                  DWORD dwError)
 {