X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/03baf031866c399a835fef3a00834e32857e0dde..4e15d1caa03346c126015019c1fdf093033ef40b:/src/msw/dialup.cpp diff --git a/src/msw/dialup.cpp b/src/msw/dialup.cpp index e8480bd8a3..6cc5040544 100644 --- a/src/msw/dialup.cpp +++ b/src/msw/dialup.cpp @@ -1,5 +1,5 @@ ///////////////////////////////////////////////////////////////////////////// -// Name: msw/dialup.cpp +// Name: src/msw/dialup.cpp // Purpose: MSW implementation of network/dialup classes and functions // Author: Vadim Zeitlin // Modified by: @@ -24,35 +24,34 @@ #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 +#include "wx/dialup.h" + #ifndef WX_PRECOMP #include "wx/log.h" #include "wx/intl.h" #include "wx/event.h" + #include "wx/app.h" + #include "wx/timer.h" + #include "wx/module.h" #endif -#include "wx/timer.h" -#include "wx/app.h" #include "wx/generic/choicdgg.h" +#include "wx/msw/private.h" +#include "wx/msw/private/hiddenwin.h" #include "wx/dynlib.h" -#include "wx/dialup.h" -DEFINE_EVENT_TYPE(wxEVT_DIALUP_CONNECTED) -DEFINE_EVENT_TYPE(wxEVT_DIALUP_DISCONNECTED) +wxDEFINE_EVENT( wxEVT_DIALUP_CONNECTED, wxDialUpEvent ); +wxDEFINE_EVENT( wxEVT_DIALUP_DISCONNECTED, wxDialUpEvent ); -// 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 @@ -68,6 +67,10 @@ DEFINE_EVENT_TYPE(wxEVT_DIALUP_DISCONNECTED) #define INTERNET_CONNECTION_PROXY 4 #endif +static const wxChar * + wxMSWDIALUP_WNDCLASSNAME = wxT("_wxDialUpManager_Internal_Class"); +static const wxChar *gs_classForDialUpWindow = NULL; + // ---------------------------------------------------------------------------- // constants // ---------------------------------------------------------------------------- @@ -106,7 +109,7 @@ DEFINE_EVENT_TYPE(wxEVT_DIALUP_DISCONNECTED) typedef DWORD (APIENTRY * RASVALIDATEENTRYNAME)( LPCSTR, LPCSTR ); typedef DWORD (APIENTRY * RASCONNECTIONNOTIFICATION)( HRASCONN, HANDLE, DWORD ); - static const wxChar gs_funcSuffix = _T('A'); + static const wxChar gs_funcSuffix = wxT('A'); #else // Unicode typedef DWORD (APIENTRY * RASDIAL)( LPRASDIALEXTENSIONS, LPCWSTR, LPRASDIALPARAMSW, DWORD, LPVOID, LPHRASCONN ); typedef DWORD (APIENTRY * RASENUMCONNECTIONS)( LPRASCONNW, LPDWORD, LPDWORD ); @@ -128,7 +131,7 @@ DEFINE_EVENT_TYPE(wxEVT_DIALUP_DISCONNECTED) typedef DWORD (APIENTRY * RASVALIDATEENTRYNAME)( LPCWSTR, LPCWSTR ); typedef DWORD (APIENTRY * RASCONNECTIONNOTIFICATION)( HRASCONN, HANDLE, DWORD ); - static const wxChar gs_funcSuffix = _T('W'); + static const wxChar gs_funcSuffix = wxT('W'); #endif // ASCII/Unicode // structure passed to the secondary thread @@ -137,15 +140,28 @@ 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 + class WXDLLIMPEXP_FWD_CORE wxDialUpManagerMSW *dialUpManager; // the owner }; // ---------------------------------------------------------------------------- @@ -171,7 +187,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); @@ -187,6 +203,7 @@ public: // for wxRasDialFunc static HWND GetRasWindow() { return ms_hwndRas; } + static void ResetRasWindow() { ms_hwndRas = NULL; } static wxDialUpManagerMSW *GetDialer() { return ms_dialer; } private: @@ -197,11 +214,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 +234,8 @@ private: private: wxDialUpManagerMSW *m_dialUpManager; + + wxDECLARE_NO_COPY_CLASS(RasTimer); } m_timerStatusPolling; // thread handle for the thread sitting on connection change event @@ -220,10 +243,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 +254,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,14 +283,39 @@ 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; + + wxDECLARE_NO_COPY_CLASS(wxDialUpManagerMSW); +}; + +// module to destroy helper window created by wxDialUpManagerMSW +class wxDialUpManagerModule : public wxModule +{ +public: + bool OnInit() { return true; } + void OnExit() + { + HWND hwnd = wxDialUpManagerMSW::GetRasWindow(); + if ( hwnd ) + { + ::DestroyWindow(hwnd); + wxDialUpManagerMSW::ResetRasWindow(); + } + + if ( gs_classForDialUpWindow ) + { + ::UnregisterClass(wxMSWDIALUP_WNDCLASSNAME, wxGetInstance()); + gs_classForDialUpWindow = NULL; + } + } + +private: + DECLARE_DYNAMIC_CLASS(wxDialUpManagerModule) }; +IMPLEMENT_DYNAMIC_CLASS(wxDialUpManagerModule, wxModule) + // ---------------------------------------------------------------------------- // private functions // ---------------------------------------------------------------------------- @@ -321,7 +363,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,17 +381,19 @@ wxDialUpManager *wxDialUpManager::Create() #endif // VC++ wxDialUpManagerMSW::wxDialUpManagerMSW() - : m_timerStatusPolling(this) - , m_dllRas(_T("RASAPI32")) + : m_timerStatusPolling(this), + m_dllRas(wxT("RASAPI32")) { // initialize our data + m_autoCheckLevel = 0; m_hThread = 0; + m_data = new wxRasThreadData; if ( !m_dllRas.IsLoaded() ) { wxLogError(_("Dial up functions are unavailable because the remote access service (RAS) is not installed on this machine. Please install it.")); } - else if( ms_pfnRasDial == 0 ) + else if ( !ms_pfnRasDial ) { // resolve the functions we need @@ -360,7 +403,7 @@ wxDialUpManagerMSW::wxDialUpManagerMSW() // get the function from rasapi32.dll and abort if it's not found #define RESOLVE_RAS_FUNCTION(type, name) \ - ms_pfn##name = (type)m_dllRas.GetSymbol( wxString(_T(#name)) \ + ms_pfn##name = (type)m_dllRas.GetSymbol( wxString(wxT(#name)) \ + gs_funcSuffix); \ if ( !ms_pfn##name ) \ { \ @@ -371,7 +414,7 @@ wxDialUpManagerMSW::wxDialUpManagerMSW() // a variant of above macro which doesn't abort if the function is // not found in the DLL #define RESOLVE_OPTIONAL_RAS_FUNCTION(type, name) \ - ms_pfn##name = (type)m_dllRas.GetSymbol( wxString(_T(#name)) \ + ms_pfn##name = (type)m_dllRas.GetSymbol( wxString(wxT(#name)) \ + gs_funcSuffix); RESOLVE_RAS_FUNCTION(RASDIAL, RasDial); @@ -407,12 +450,10 @@ wxDialUpManagerMSW::wxDialUpManagerMSW() 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); + wxLogError(_("The version of remote access service (RAS) installed " + "on this machine is too old, please upgrade (the " + "following required function is missing: %s)."), + funcName); m_dllRas.Unload(); return; } @@ -453,7 +494,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); } @@ -498,7 +539,7 @@ HRASCONN wxDialUpManagerMSW::FindActiveConnection() } else { - // an error occured + // an error occurred wxLogError(_("Cannot find active dialup connection: %s"), GetErrorString(dwRet).c_str()); return 0; @@ -537,9 +578,15 @@ void wxDialUpManagerMSW::CleanUpThreadData() { if ( m_hThread ) { - if ( !SetEvent(m_data.hEventQuit) ) + if ( !SetEvent(m_data->hEventQuit) ) + { + wxLogLastError(wxT("SetEvent(RasThreadQuit)")); + } + else // sent quit request to the background thread { - wxLogLastError(_T("SetEvent(RasThreadQuit)")); + // 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); @@ -547,26 +594,7 @@ void wxDialUpManagerMSW::CleanUpThreadData() m_hThread = 0; } - if ( m_data.hWnd ) - { - 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; - } + wxDELETE(m_data); } // ---------------------------------------------------------------------------- @@ -632,14 +660,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 */); } } @@ -675,7 +703,13 @@ size_t wxDialUpManagerMSW::GetISPNames(wxArrayString& names) const if ( dwRet == ERROR_BUFFER_TOO_SMALL ) { // reallocate the buffer - rasEntries = (RASENTRYNAME *)realloc(rasEntries, size); + void *n = realloc(rasEntries, size); + if (n == NULL) + { + free(rasEntries); + return 0; + } + rasEntries = (RASENTRYNAME *)n; } else if ( dwRet != 0 ) { @@ -709,13 +743,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 +764,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 +793,7 @@ bool wxDialUpManagerMSW::Dial(const wxString& nameOfISP, if ( !entryName ) { // cancelled by user - return FALSE; + return false; } } } @@ -767,7 +801,7 @@ bool wxDialUpManagerMSW::Dial(const wxString& nameOfISP, RASDIALPARAMS rasDialParams; rasDialParams.dwSize = sizeof(rasDialParams); - wxStrncpy(rasDialParams.szEntryName, entryName, RAS_MaxEntryName); + wxStrlcpy(rasDialParams.szEntryName, entryName.c_str(), RAS_MaxEntryName); // do we have the username and password? if ( !username || !password ) @@ -784,19 +818,18 @@ bool wxDialUpManagerMSW::Dial(const wxString& nameOfISP, { wxLogError(_("Failed to connect: missing username/password.")); - return FALSE; + return false; } } else { - wxStrncpy(rasDialParams.szUserName, username, UNLEN); - wxStrncpy(rasDialParams.szPassword, password, PWLEN); + wxStrlcpy(rasDialParams.szUserName, username.c_str(), UNLEN); + wxStrlcpy(rasDialParams.szPassword, password.c_str(), 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'; @@ -830,21 +863,28 @@ bool wxDialUpManagerMSW::Dial(const wxString& nameOfISP, DWORD dwRet = ms_pfnRasDial ( - (LPRASDIALEXTENSIONS)NULL, // no extended features - NULL, // default phone book file (NT only) + NULL, // no extended features + NULL, // default phone book file (NT only) &rasDialParams, - 0, // use callback for notifications - async ? wxRasDialFunc // the callback - : 0, // no notifications - sync operation + 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()); + if ( async ) + { + wxLogError(_("Failed to initiate dialup connection: %s"), + GetErrorString(dwRet).c_str()); + } + else + { + wxLogError(_("Failed to establish dialup connection: %s"), + GetErrorString(dwRet).c_str()); + } // we should still call RasHangUp() if we got a non 0 connection if ( ms_hRasConnection ) @@ -855,16 +895,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 +917,7 @@ bool wxDialUpManagerMSW::CancelDialing() if ( !GetDialer() ) { // silently ignore - return FALSE; + return false; } wxASSERT_MSG( ms_hRasConnection, wxT("dialing but no connection?") ); @@ -889,7 +929,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,44 +949,42 @@ bool wxDialUpManagerMSW::HangUp() { wxLogError(_("Cannot hang up - no active dialup connection.")); - return FALSE; + return false; } - DWORD dwRet = ms_pfnRasHangUp(hRasConn); - if ( dwRet != 0 ) + // 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; + 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(wxT("WININET")); if ( hDll.IsLoaded() ) { typedef BOOL (WINAPI *INTERNETGETCONNECTEDSTATE)(LPDWORD, DWORD); INTERNETGETCONNECTEDSTATE pfnInternetGetConnectedState; #define RESOLVE_FUNCTION(type, name) \ - pfn##name = (type)hDll.GetSymbol(_T(#name)) + pfn##name = (type)hDll.GetSymbol(wxT(#name)) RESOLVE_FUNCTION(INTERNETGETCONNECTEDSTATE, InternetGetConnectedState); @@ -956,44 +994,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); + isAlwaysOnline = (flags & (INTERNET_CONNECTION_LAN | + INTERNET_CONNECTION_PROXY)) != 0; } - else - { - // no Internet connection at all - ms_isAlwaysOnline = FALSE; - } - } - } - - // 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; + //else: no Internet connection at all } } - 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 +1021,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 +1035,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 +1053,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 +1069,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; } } @@ -1086,36 +1111,28 @@ bool wxDialUpManagerMSW::EnableAutoCheckOnlineStatus(size_t nSeconds) { // create a hidden window to receive notification about connections // status change - extern const wxChar *wxCanvasClassName; - ms_hwndRas = ::CreateWindow(wxCanvasClassName, NULL, - 0, 0, 0, 0, - 0, NULL, - (HMENU)NULL, wxGetInstance(), 0); + ms_hwndRas = wxCreateHiddenWindow + ( + &gs_classForDialUpWindow, + wxMSWDIALUP_WNDCLASSNAME, + wxRasStatusWindowProc + ); if ( !ms_hwndRas ) { wxLogLastError(wxT("CreateWindow(RasHiddenWindow)")); CleanUpThreadData(); - ok = FALSE; + ok = false; } - - // and subclass it - FARPROC windowProc = MakeProcInstance - ( - (FARPROC)wxRasStatusWindowProc, - wxGetInstance() - ); - - ::SetWindowLong(ms_hwndRas, GWL_WNDPROC, (LONG) windowProc); } - 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 +1140,7 @@ bool wxDialUpManagerMSW::EnableAutoCheckOnlineStatus(size_t nSeconds) NULL, 0, (LPTHREAD_START_ROUTINE)wxRasMonitorThread, - (void *)&m_data, + (void *)m_data, 0, &tid ); @@ -1142,7 +1159,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 +1172,7 @@ bool wxDialUpManagerMSW::EnableAutoCheckOnlineStatus(size_t nSeconds) } else { - return TRUE; + return true; } } @@ -1169,13 +1186,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 != 0 ) + { + // still checking + return; + } + if ( m_hThread ) { // we have running secondary thread, it's just enough to suspend it @@ -1221,10 +1244,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,37 +1258,66 @@ static DWORD wxRasMonitorThread(wxRasThreadData *data) break; case WAIT_OBJECT_0 + 1: - cont = FALSE; + cont = false; break; + default: + wxFAIL_MSG( wxT("unexpected return of WaitForMultipleObjects()") ); + // fall through + case WAIT_FAILED: - wxLogLastError(wxT("WaitForMultipleObjects(RasMonitor)")); - break; + // 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) + ); + + // 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) { - if ( message == wxWM_RAS_STATUS_CHANGED ) - { - wxRasThreadData *data = (wxRasThreadData *)lParam; - data->dialUpManager->OnConnectStatusChange(); - } - else if ( message == wxWM_RAS_DIALING_PROGRESS ) + switch ( message ) { - wxDialUpManagerMSW *dialUpManager = wxDialUpManagerMSW::GetDialer(); + case wxWM_RAS_STATUS_CHANGED: + { + wxRasThreadData *data = (wxRasThreadData *)lParam; + data->dialUpManager->OnConnectStatusChange(); + } + break; - dialUpManager->OnDialProgress((RASCONNSTATE)wParam, lParam); + 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 unMsg, +static void WINAPI wxRasDialFunc(UINT WXUNUSED(unMsg), RASCONNSTATE rasconnstate, DWORD dwError) { @@ -1273,12 +1325,10 @@ static void WINAPI wxRasDialFunc(UINT unMsg, wxCHECK_RET( dialUpManager, wxT("who started to dial then?") ); - SendMessage(dialUpManager->GetRasWindow(), wxWM_RAS_DIALING_PROGRESS, + SendMessage(wxDialUpManagerMSW::GetRasWindow(), wxWM_RAS_DIALING_PROGRESS, rasconnstate, dwError); } -#endif - // __BORLANDC__ -#endif // wxUSE_DIALUP_MANAGER +#endif // __BORLANDC__ -// vi:sts=4:sw=4:et +#endif // wxUSE_DIALUP_MANAGER