/////////////////////////////////////////////////////////////////////////////
-// Name: msw/dialup.cpp
+// Name: src/msw/dialup.cpp
// Purpose: MSW implementation of network/dialup classes and functions
// Author: Vadim Zeitlin
// Modified by:
#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/generic/choicdgg.h"
+
#include "wx/dynlib.h"
-#include "wx/dialup.h"
+wxDEFINE_EVENT( wxEVT_DIALUP_CONNECTED, wxDialUpEvent )
+wxDEFINE_EVENT( wxEVT_DIALUP_DISCONNECTED, wxDialUpEvent )
-// Doesn't yet compile under BC++ nor with mingw: no wininet.h
-#if !defined(__BORLANDC__) && !defined(__GNUWIN32_OLD__)
+// 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(__WINE__) && \
+ (!defined(__VISUALC__) || (__VISUALC__ >= 1020))
#include <ras.h>
#include <raserror.h>
#include <wininet.h>
-#include "wx/msw/private.h"
+// Not in VC++ 5
+#ifndef INTERNET_CONNECTION_LAN
+#define INTERNET_CONNECTION_LAN 2
+#endif
+#ifndef INTERNET_CONNECTION_PROXY
+#define INTERNET_CONNECTION_PROXY 4
+#endif
+
+// implemented in utils.cpp
+extern "C" WXDLLIMPEXP_BASE HWND
+wxCreateHiddenWindow(LPCTSTR *pclassname, LPCTSTR classname, WNDPROC wndproc);
+
+static const wxChar *
+ wxMSWDIALUP_WNDCLASSNAME = wxT("_wxDialUpManager_Internal_Class");
+static const wxChar *gs_classForDialUpWindow = NULL;
// ----------------------------------------------------------------------------
// constants
typedef DWORD (APIENTRY * RASVALIDATEENTRYNAME)( LPCSTR, LPCSTR );
typedef DWORD (APIENTRY * RASCONNECTIONNOTIFICATION)( HRASCONN, HANDLE, DWORD );
- static const char gs_funcSuffix = 'A';
+ static const wxChar gs_funcSuffix = _T('A');
#else // Unicode
typedef DWORD (APIENTRY * RASDIAL)( LPRASDIALEXTENSIONS, LPCWSTR, LPRASDIALPARAMSW, DWORD, LPVOID, LPHRASCONN );
typedef DWORD (APIENTRY * RASENUMCONNECTIONS)( LPRASCONNW, LPDWORD, LPDWORD );
typedef DWORD (APIENTRY * RASVALIDATEENTRYNAME)( LPCWSTR, LPCWSTR );
typedef DWORD (APIENTRY * RASCONNECTIONNOTIFICATION)( HRASCONN, HANDLE, DWORD );
- static const char gs_funcSuffix = 'W';
+ static const wxChar gs_funcSuffix = _T('W');
#endif // ASCII/Unicode
// structure passed to the secondary thread
-struct wxRasThreadData
+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
};
// ----------------------------------------------------------------------------
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);
// for wxRasDialFunc
static HWND GetRasWindow() { return ms_hwndRas; }
+ static void ResetRasWindow() { ms_hwndRas = NULL; }
static wxDialUpManagerMSW *GetDialer() { return ms_dialer; }
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 RasTimer : public wxTimer
+ class WXDLLEXPORT RasTimer : public wxTimer
{
public:
RasTimer(wxDialUpManagerMSW *dialUpManager)
private:
wxDialUpManagerMSW *m_dialUpManager;
+
+ DECLARE_NO_COPY_CLASS(RasTimer)
} m_timerStatusPolling;
// thread handle for the thread sitting on connection change event
// 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
+ wxDynamicLibrary m_dllRas;
// the hidden window we use for passing messages between threads
static HWND ms_hwndRas;
// the handle of the connection we initiated or 0 if none
static HRASCONN ms_hRasConnection;
- // the use count of rasapi32.dll
- static int ms_nDllCount;
-
- // the handle of rasapi32.dll when it's loaded
- static wxDllType ms_dllRas;
-
// the pointers to RAS functions
static RASDIAL ms_pfnRasDial;
static RASENUMCONNECTIONS ms_pfnRasEnumConnections;
// 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)
};
+// 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
// ----------------------------------------------------------------------------
HWND wxDialUpManagerMSW::ms_hwndRas = 0;
-int wxDialUpManagerMSW::ms_nDllCount = 0;
-wxDllType wxDialUpManagerMSW::ms_dllRas = 0;
-
RASDIAL wxDialUpManagerMSW::ms_pfnRasDial = 0;
RASENUMCONNECTIONS wxDialUpManagerMSW::ms_pfnRasEnumConnections = 0;
RASENUMENTRIES wxDialUpManagerMSW::ms_pfnRasEnumEntries = 0;
int wxDialUpManagerMSW::ms_userSpecifiedOnlineStatus = -1;
int wxDialUpManagerMSW::ms_isConnected = -1;
-int wxDialUpManagerMSW::ms_isAlwaysOnline = -1;
wxDialUpManagerMSW *wxDialUpManagerMSW::ms_dialer = NULL;
// ----------------------------------------------------------------------------
#endif // VC++
wxDialUpManagerMSW::wxDialUpManagerMSW()
- : m_timerStatusPolling(this)
+ : m_timerStatusPolling(this),
+ m_dllRas(_T("RASAPI32"))
{
// initialize our data
+ m_autoCheckLevel = 0;
m_hThread = 0;
+ m_data = new wxRasThreadData;
- if ( !ms_nDllCount++ )
+ if ( !m_dllRas.IsLoaded() )
{
- // load the RAS library
- ms_dllRas = wxDllLoader::LoadLibrary("RASAPI32");
- if ( !ms_dllRas )
+ 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 )
+ {
+ // resolve the functions we need
+
+ // this will contain the name of the function we failed to resolve
+ // if any at the end
+ const char *funcName = NULL;
+
+ // 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)) \
+ + gs_funcSuffix); \
+ if ( !ms_pfn##name ) \
+ { \
+ funcName = #name; \
+ goto exit; \
+ }
+
+ // 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)) \
+ + gs_funcSuffix);
+
+ RESOLVE_RAS_FUNCTION(RASDIAL, RasDial);
+ RESOLVE_RAS_FUNCTION(RASENUMCONNECTIONS, RasEnumConnections);
+ RESOLVE_RAS_FUNCTION(RASENUMENTRIES, RasEnumEntries);
+ RESOLVE_RAS_FUNCTION(RASGETCONNECTSTATUS, RasGetConnectStatus);
+ RESOLVE_RAS_FUNCTION(RASGETERRORSTRING, RasGetErrorString);
+ RESOLVE_RAS_FUNCTION(RASHANGUP, RasHangUp);
+ RESOLVE_RAS_FUNCTION(RASGETENTRYDIALPARAMS, RasGetEntryDialParams);
+
+ // suppress error messages about missing (non essential) functions
{
- wxLogError(_("Dial up functions are unavailable because the "
- "remote access service (RAS) is not installed "
- "on this machine. Please install it."));
+ wxLogNull noLog;
+
+ RESOLVE_OPTIONAL_RAS_FUNCTION(RASGETPROJECTIONINFO, RasGetProjectionInfo);
+ RESOLVE_OPTIONAL_RAS_FUNCTION(RASCREATEPHONEBOOKENTRY, RasCreatePhonebookEntry);
+ RESOLVE_OPTIONAL_RAS_FUNCTION(RASEDITPHONEBOOKENTRY, RasEditPhonebookEntry);
+ RESOLVE_OPTIONAL_RAS_FUNCTION(RASSETENTRYDIALPARAMS, RasSetEntryDialParams);
+ RESOLVE_OPTIONAL_RAS_FUNCTION(RASGETENTRYPROPERTIES, RasGetEntryProperties);
+ RESOLVE_OPTIONAL_RAS_FUNCTION(RASSETENTRYPROPERTIES, RasSetEntryProperties);
+ RESOLVE_OPTIONAL_RAS_FUNCTION(RASRENAMEENTRY, RasRenameEntry);
+ RESOLVE_OPTIONAL_RAS_FUNCTION(RASDELETEENTRY, RasDeleteEntry);
+ RESOLVE_OPTIONAL_RAS_FUNCTION(RASVALIDATEENTRYNAME, RasValidateEntryName);
+ RESOLVE_OPTIONAL_RAS_FUNCTION(RASGETCOUNTRYINFO, RasGetCountryInfo);
+ RESOLVE_OPTIONAL_RAS_FUNCTION(RASENUMDEVICES, RasEnumDevices);
+ RESOLVE_OPTIONAL_RAS_FUNCTION(RASCONNECTIONNOTIFICATION, RasConnectionNotification);
}
- else
- {
- // resolve the functions we need
-
- // this will contain the name of the function we failed to resolve
- // if any at the end
- const char *funcName = NULL;
-
- // get the function from rasapi32.dll and abort if it's not found
- #define RESOLVE_RAS_FUNCTION(type, name) \
- ms_pfn##name = (type)wxDllLoader::GetSymbol(ms_dllRas, \
- wxString(_T(#name)) + gs_funcSuffix); \
- if ( !ms_pfn##name ) \
- { \
- funcName = #name; \
- goto exit; \
- }
-
- // 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)wxDllLoader::GetSymbol(ms_dllRas, \
- wxString(_T(#name)) + gs_funcSuffix);
-
- RESOLVE_RAS_FUNCTION(RASDIAL, RasDial);
- RESOLVE_RAS_FUNCTION(RASENUMCONNECTIONS, RasEnumConnections);
- RESOLVE_RAS_FUNCTION(RASENUMENTRIES, RasEnumEntries);
- RESOLVE_RAS_FUNCTION(RASGETCONNECTSTATUS, RasGetConnectStatus);
- RESOLVE_RAS_FUNCTION(RASGETERRORSTRING, RasGetErrorString);
- RESOLVE_RAS_FUNCTION(RASHANGUP, RasHangUp);
- RESOLVE_RAS_FUNCTION(RASGETENTRYDIALPARAMS, RasGetEntryDialParams);
-
- // suppress wxDllLoader messages about missing (non essential)
- // functions
- {
- wxLogNull noLog;
-
- RESOLVE_OPTIONAL_RAS_FUNCTION(RASGETPROJECTIONINFO, RasGetProjectionInfo);
- RESOLVE_OPTIONAL_RAS_FUNCTION(RASCREATEPHONEBOOKENTRY, RasCreatePhonebookEntry);
- RESOLVE_OPTIONAL_RAS_FUNCTION(RASEDITPHONEBOOKENTRY, RasEditPhonebookEntry);
- RESOLVE_OPTIONAL_RAS_FUNCTION(RASSETENTRYDIALPARAMS, RasSetEntryDialParams);
- RESOLVE_OPTIONAL_RAS_FUNCTION(RASGETENTRYPROPERTIES, RasGetEntryProperties);
- RESOLVE_OPTIONAL_RAS_FUNCTION(RASSETENTRYPROPERTIES, RasSetEntryProperties);
- RESOLVE_OPTIONAL_RAS_FUNCTION(RASRENAMEENTRY, RasRenameEntry);
- RESOLVE_OPTIONAL_RAS_FUNCTION(RASDELETEENTRY, RasDeleteEntry);
- RESOLVE_OPTIONAL_RAS_FUNCTION(RASVALIDATEENTRYNAME, RasValidateEntryName);
- RESOLVE_OPTIONAL_RAS_FUNCTION(RASGETCOUNTRYINFO, RasGetCountryInfo);
- RESOLVE_OPTIONAL_RAS_FUNCTION(RASENUMDEVICES, RasEnumDevices);
- RESOLVE_OPTIONAL_RAS_FUNCTION(RASCONNECTIONNOTIFICATION, RasConnectionNotification);
- }
- // keep your preprocessor name space clean
- #undef RESOLVE_RAS_FUNCTION
- #undef RESOLVE_OPTIONAL_RAS_FUNCTION
+ // keep your preprocessor name space clean
+ #undef RESOLVE_RAS_FUNCTION
+ #undef RESOLVE_OPTIONAL_RAS_FUNCTION
exit:
- if ( 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);
-
- wxDllLoader::UnloadLibrary(ms_dllRas);
- ms_dllRas = 0;
- ms_nDllCount = 0;
-
- return;
- }
+ if ( 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;
}
}
wxDialUpManagerMSW::~wxDialUpManagerMSW()
{
CleanUpThreadData();
-
- if ( !--ms_nDllCount )
- {
- // unload the RAS library
- wxDllLoader::UnloadLibrary(ms_dllRas);
- ms_dllRas = 0;
- }
}
// ----------------------------------------------------------------------------
default:
{
- wxLogSysError(dwRet, _("Failed to retrieve text of RAS "
- "error message"));
+ wxLogSysError(dwRet,
+ _("Failed to retrieve text of RAS error message"));
wxString msg;
msg.Printf(_("unknown error (error code %08x)."), 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);
}
}
else
{
- // an error occured
+ // an error occurred
wxLogError(_("Cannot find active dialup connection: %s"),
- GetErrorString(dwRet));
+ GetErrorString(dwRet).c_str());
return 0;
}
}
// 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."));
+ wxLogWarning(_("Several active dialup connections found, choosing one randomly."));
// fall through
case 1:
{
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
{
- wxLogLastError("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);
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 )
+ if ( m_data )
{
- CloseHandle(m_data.hEventRas);
-
- m_data.hEventRas = 0;
+ delete m_data;
+ m_data = NULL;
}
}
if ( dwError )
{
wxLogError(_("Failed to establish dialup connection: %s"),
- GetErrorString(dwError));
+ GetErrorString(dwError).c_str());
// we should still call RasHangUp() if we got a non 0 connection
if ( ms_hRasConnection )
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 */);
}
}
bool wxDialUpManagerMSW::IsOk() const
{
- return ms_dllRas != 0;
+ return m_dllRas.IsLoaded();
}
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 )
{
// some other error - abort
- wxLogError(_("Failed to get ISP names: %s"), GetErrorString(dwRet));
+ wxLogError(_("Failed to get ISP names: %s"),
+ GetErrorString(dwRet).c_str());
free(rasEntries);
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
// no known ISPs, abort
wxLogError(_("Failed to connect: no ISP to dial."));
- return FALSE;
+ return false;
case 1:
// only one ISP, choose it
entryName = wxGetSingleChoice
(
_("Choose ISP to dial"),
- _("Please choose which ISP do you want to "
- "connect to"),
+ _("Please choose which ISP do you want to connect to"),
count,
strings
);
if ( !entryName )
{
// cancelled by user
- return FALSE;
+ return false;
}
}
}
RASDIALPARAMS rasDialParams;
rasDialParams.dwSize = sizeof(rasDialParams);
- strncpy(rasDialParams.szEntryName, entryName, RAS_MaxEntryName);
+ wxStrlcpy(rasDialParams.szEntryName, entryName.c_str(), RAS_MaxEntryName);
// do we have the username and password?
if ( !username || !password )
{
wxLogError(_("Failed to connect: missing username/password."));
- return FALSE;
+ return false;
}
}
- else
- {
- strncpy(rasDialParams.szUserName, username, UNLEN);
- strncpy(rasDialParams.szPassword, password, PWLEN);
- }
+ else
+ {
+ wxStrlcpy(rasDialParams.szUserName, username.c_str(), UNLEN);
+ wxStrlcpy(rasDialParams.szPassword, password.c_str(), PWLEN);
+ }
- // default values for other fields
+ // default values for other fields
rasDialParams.szPhoneNumber[0] = '\0';
rasDialParams.szCallbackNumber[0] = '\0';
rasDialParams.szCallbackNumber[0] = '\0';
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 )
{
- wxLogError(_("Failed to %s dialup connection: %s"),
- async ? _("initiate") : _("establish"),
- GetErrorString(dwRet));
+ // can't pass a wxWCharBuffer through ( ... )
+ 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 )
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
if ( !GetDialer() )
{
// silently ignore
- return FALSE;
+ return false;
}
wxASSERT_MSG( ms_hRasConnection, wxT("dialing but no connection?") );
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
{
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));
+ 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
- bool ok;
- wxDllType hDll = wxDllLoader::LoadLibrary(_T("WININET"), &ok);
- if ( ok )
+ // 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 (*INTERNETGETCONNECTEDSTATE)(LPDWORD, DWORD);
+ typedef BOOL (WINAPI *INTERNETGETCONNECTEDSTATE)(LPDWORD, DWORD);
INTERNETGETCONNECTEDSTATE pfnInternetGetConnectedState;
#define RESOLVE_FUNCTION(type, name) \
- pfn##name = (type)wxDllLoader::GetSymbol(hDll, _T(#name))
+ pfn##name = (type)hDll.GetSymbol(_T(#name))
RESOLVE_FUNCTION(INTERNETGETCONNECTEDSTATE, InternetGetConnectedState);
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);
-
- wxLogMessage("InternetGetConnectedState() returned TRUE, "
- "flags = %08x", flags);
- }
- else
- {
- // no Internet connection at all
- ms_isAlwaysOnline = FALSE;
+ isAlwaysOnline = (flags & (INTERNET_CONNECTION_LAN |
+ INTERNET_CONNECTION_PROXY)) != 0;
}
+ //else: no Internet connection at all
}
-
- wxDllLoader::UnloadLibrary(hDll);
}
- // 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 )
{
}
else
{
- // return TRUE if there is at least one active connection
+ // return true if there is at least one active connection
return FindActiveConnection() != 0;
}
}
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;
// 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("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;
}
}
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("CreateEvent(RasStatus)");
+ 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("CreateEvent(RasThreadQuit)");
+ wxLogLastError(wxT("CreateEvent(RasThreadQuit)"));
CleanUpThreadData();
- ok = FALSE;
+ ok = false;
}
}
{
// create a hidden window to receive notification about connections
// status change
- extern wxChar wxPanelClassName[];
- ms_hwndRas = ::CreateWindow(wxPanelClassName, NULL,
- 0, 0, 0, 0,
- 0, NULL,
- (HMENU)NULL, wxGetInstance(), 0);
+ ms_hwndRas = wxCreateHiddenWindow
+ (
+ &gs_classForDialUpWindow,
+ wxMSWDIALUP_WNDCLASSNAME,
+ wxRasStatusWindowProc
+ );
if ( !ms_hwndRas )
{
- wxLogLastError("CreateWindow(RasHiddenWindow)");
+ 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
NULL,
0,
(LPTHREAD_START_ROUTINE)wxRasMonitorThread,
- (void *)&m_data,
+ (void *)m_data,
0,
&tid
);
if ( !m_hThread )
{
- wxLogLastError("CreateThread(RasStatusThread)");
+ wxLogLastError(wxT("CreateThread(RasStatusThread)"));
CleanUpThreadData();
}
DWORD dwRet = ms_pfnRasConnectionNotification
(
(HRASCONN)INVALID_HANDLE_VALUE,
- m_data.hEventRas,
+ m_data->hEventRas,
3 /* RASCN_Connection | RASCN_Disconnection */
);
if ( dwRet != 0 )
{
wxLogDebug(wxT("RasConnectionNotification() failed: %s"),
- GetErrorString(dwRet));
+ GetErrorString(dwRet).c_str());
CleanUpThreadData();
}
else
{
- return TRUE;
+ return true;
}
}
}
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
if ( SuspendThread(m_hThread) == (DWORD)-1 )
{
- wxLogLastError("SuspendThread(RasThread)");
+ wxLogLastError(wxT("SuspendThread(RasThread)"));
}
}
else
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 )
{
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("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;
}
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;
+
+ case wxWM_RAS_DIALING_PROGRESS:
+ {
+ wxDialUpManagerMSW *dialMan = wxDialUpManagerMSW::GetDialer();
+
+ dialMan->OnDialProgress((RASCONNSTATE)wParam, lParam);
+ }
+ break;
- dialUpManager->OnDialProgress((RASCONNSTATE)wParam, lParam);
+ 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)
{
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 // __BORLANDC__
+
#endif // wxUSE_DIALUP_MANAGER