1 /////////////////////////////////////////////////////////////////////////////
2 // Name: msw/dialup.cpp
3 // Purpose: MSW implementation of network/dialup classes and functions
4 // Author: Vadim Zeitlin
8 // Copyright: (c) Vadim Zeitlin
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
12 // ============================================================================
14 // ============================================================================
16 // ----------------------------------------------------------------------------
18 // ----------------------------------------------------------------------------
20 // for compilers that support precompilation, includes "wx.h".
21 #include "wx/wxprec.h"
27 // these functions require Win32
28 #if defined(__WIN16__) && wxUSE_DIALUP_MANAGER
29 #undef wxUSE_DIALUP_MANAGER
30 #define wxUSE_DIALUP_MANAGER 0
31 #endif // wxUSE_DIALUP_MANAGER && Win16
33 #if wxUSE_DIALUP_MANAGER
39 #include "wx/dynlib.h"
46 #include "wx/msw/private.h"
48 // ----------------------------------------------------------------------------
50 // ----------------------------------------------------------------------------
52 // this message is sent by the secondary thread when RAS status changes
53 #define wxWM_RAS_STATUS_CHANGED (WM_USER + 10010)
55 // ----------------------------------------------------------------------------
57 // ----------------------------------------------------------------------------
59 // the signatures of RAS functions: all this is quite heavy, but we must do it
60 // to allow running wxWin programs on machine which don't have RAS installed
61 // (this does exist) - if we link with rasapi32.lib, the program will fail on
62 // startup because of the missing DLL...
65 typedef DWORD (* RASDIAL
)( LPRASDIALEXTENSIONS
, LPCSTR
, LPRASDIALPARAMSA
, DWORD
, LPVOID
, LPHRASCONN
);
66 typedef DWORD (* RASENUMCONNECTIONS
)( LPRASCONNA
, LPDWORD
, LPDWORD
);
67 typedef DWORD (* RASENUMENTRIES
)( LPCSTR
, LPCSTR
, LPRASENTRYNAMEA
, LPDWORD
, LPDWORD
);
68 typedef DWORD (* RASGETCONNECTSTATUS
)( HRASCONN
, LPRASCONNSTATUSA
);
69 typedef DWORD (* RASGETERRORSTRING
)( UINT
, LPSTR
, DWORD
);
70 typedef DWORD (* RASHANGUP
)( HRASCONN
);
71 typedef DWORD (* RASGETPROJECTIONINFO
)( HRASCONN
, RASPROJECTION
, LPVOID
, LPDWORD
);
72 typedef DWORD (* RASCREATEPHONEBOOKENTRY
)( HWND
, LPCSTR
);
73 typedef DWORD (* RASEDITPHONEBOOKENTRY
)( HWND
, LPCSTR
, LPCSTR
);
74 typedef DWORD (* RASSETENTRYDIALPARAMS
)( LPCSTR
, LPRASDIALPARAMSA
, BOOL
);
75 typedef DWORD (* RASGETENTRYDIALPARAMS
)( LPCSTR
, LPRASDIALPARAMSA
, LPBOOL
);
76 typedef DWORD (* RASENUMDEVICES
)( LPRASDEVINFOA
, LPDWORD
, LPDWORD
);
77 typedef DWORD (* RASGETCOUNTRYINFO
)( LPRASCTRYINFOA
, LPDWORD
);
78 typedef DWORD (* RASGETENTRYPROPERTIES
)( LPCSTR
, LPCSTR
, LPRASENTRYA
, LPDWORD
, LPBYTE
, LPDWORD
);
79 typedef DWORD (* RASSETENTRYPROPERTIES
)( LPCSTR
, LPCSTR
, LPRASENTRYA
, DWORD
, LPBYTE
, DWORD
);
80 typedef DWORD (* RASRENAMEENTRY
)( LPCSTR
, LPCSTR
, LPCSTR
);
81 typedef DWORD (* RASDELETEENTRY
)( LPCSTR
, LPCSTR
);
82 typedef DWORD (* RASVALIDATEENTRYNAME
)( LPCSTR
, LPCSTR
);
83 typedef DWORD (* RASCONNECTIONNOTIFICATION
)( HRASCONN
, HANDLE
, DWORD
);
85 static const char gs_funcSuffix
= 'A';
87 typedef DWORD (* RASDIAL
)( LPRASDIALEXTENSIONS
, LPCWSTR
, LPRASDIALPARAMSW
, DWORD
, LPVOID
, LPHRASCONN
);
88 typedef DWORD (* RASENUMCONNECTIONS
)( LPRASCONNW
, LPDWORD
, LPDWORD
);
89 typedef DWORD (* RASENUMENTRIES
)( LPCWSTR
, LPCWSTR
, LPRASENTRYNAMEW
, LPDWORD
, LPDWORD
);
90 typedef DWORD (* RASGETCONNECTSTATUS
)( HRASCONN
, LPRASCONNSTATUSW
);
91 typedef DWORD (* RASGETERRORSTRING
)( UINT
, LPWSTR
, DWORD
);
92 typedef DWORD (* RASHANGUP
)( HRASCONN
);
93 typedef DWORD (* RASGETPROJECTIONINFO
)( HRASCONN
, RASPROJECTION
, LPVOID
, LPDWORD
);
94 typedef DWORD (* RASCREATEPHONEBOOKENTRY
)( HWND
, LPCWSTR
);
95 typedef DWORD (* RASEDITPHONEBOOKENTRY
)( HWND
, LPCWSTR
, LPCWSTR
);
96 typedef DWORD (* RASSETENTRYDIALPARAMS
)( LPCWSTR
, LPRASDIALPARAMSW
, BOOL
);
97 typedef DWORD (* RASGETENTRYDIALPARAMS
)( LPCWSTR
, LPRASDIALPARAMSW
, LPBOOL
);
98 typedef DWORD (* RASENUMDEVICES
)( LPRASDEVINFOW
, LPDWORD
, LPDWORD
);
99 typedef DWORD (* RASGETCOUNTRYINFO
)( LPRASCTRYINFOW
, LPDWORD
);
100 typedef DWORD (* RASGETENTRYPROPERTIES
)( LPCWSTR
, LPCWSTR
, LPRASENTRYW
, LPDWORD
, LPBYTE
, LPDWORD
);
101 typedef DWORD (* RASSETENTRYPROPERTIES
)( LPCWSTR
, LPCWSTR
, LPRASENTRYW
, DWORD
, LPBYTE
, DWORD
);
102 typedef DWORD (* RASRENAMEENTRY
)( LPCWSTR
, LPCWSTR
, LPCWSTR
);
103 typedef DWORD (* RASDELETEENTRY
)( LPCWSTR
, LPCWSTR
);
104 typedef DWORD (* RASVALIDATEENTRYNAME
)( LPCWSTR
, LPCWSTR
);
105 typedef DWORD (* RASCONNECTIONNOTIFICATION
)( HRASCONN
, HANDLE
, DWORD
);
107 static const char gs_funcSuffix
= 'W';
108 #endif // ASCII/Unicode
110 // structure passed to the secondary thread
111 struct wxRasThreadData
116 hEventRas
= hEventQuit
= INVALID_HANDLE_VALUE
;
117 dialUpManager
= NULL
;
120 HWND hWnd
; // window to send notifications to
121 HANDLE hEventRas
, // event which RAS signals when status changes
122 hEventQuit
; // event which we signal when we terminate
124 class WXDLLEXPORT wxDialUpManagerMSW
*dialUpManager
; // the owner
127 // ----------------------------------------------------------------------------
128 // wxDialUpManager class for MSW
129 // ----------------------------------------------------------------------------
131 class WXDLLEXPORT wxDialUpManagerMSW
: public wxDialUpManager
135 wxDialUpManagerMSW();
136 virtual ~wxDialUpManagerMSW();
138 // implement base class pure virtuals
139 virtual bool IsOk() const;
140 virtual bool Dial(const wxString
& nameOfISP
,
141 const wxString
& username
,
142 const wxString
& password
,
144 virtual bool IsDialing() const;
145 virtual bool CancelDialing();
146 virtual bool HangUp();
147 virtual bool IsOnline() const;
148 virtual void SetOnlineStatus(bool isOnline
= TRUE
);
149 virtual bool EnableAutoCheckOnlineStatus(size_t nSeconds
);
150 virtual void DisableAutoCheckOnlineStatus();
151 virtual void SetWellKnownHost(const wxString
& hostname
, int port
);
152 virtual void SetConnectCommand(const wxString
& commandDial
,
153 const wxString
& commandHangup
);
156 void CheckRasStatus();
158 // for wxRasStatusWindowProc
159 void OnConnectStatusChange();
162 void OnDialProgress(RASCONNSTATE rasconnstate
, DWORD dwError
);
163 static wxDialUpManagerMSW
*GetDialer() { return ms_dialer
; }
166 // return the error string for the given RAS error code
167 static wxString
GetErrorString(DWORD error
);
169 // find the (first) handle of the active connection
170 static HRASCONN
FindActiveConnection();
172 // notify the application about status change
173 void NotifyApp(bool connected
, bool fromOurselves
= FALSE
) const;
175 // destroy the thread data and the thread itself
176 void CleanUpThreadData();
178 // timer used for polling RAS status
179 class RasTimer
: public wxTimer
182 RasTimer(wxDialUpManagerMSW
*dialUpManager
)
183 { m_dialUpManager
= dialUpManager
; }
185 virtual void Notify() { m_dialUpManager
->CheckRasStatus(); }
188 wxDialUpManagerMSW
*m_dialUpManager
;
189 } m_timerStatusPolling
;
191 // thread handle for the thread sitting on connection change event
194 // data used by this thread and our hidden window to send messages between
196 wxRasThreadData m_data
;
198 // the handle of the connection we initiated or 0 if none
199 static HRASCONN ms_hRasConnection
;
201 // the use count of rasapi32.dll
202 static int ms_nDllCount
;
204 // the handle of rasapi32.dll when it's loaded
205 static wxDllType ms_dllRas
;
207 // the pointers to RAS functions
208 static RASDIAL ms_pfnRasDial
;
209 static RASENUMCONNECTIONS ms_pfnRasEnumConnections
;
210 static RASENUMENTRIES ms_pfnRasEnumEntries
;
211 static RASGETCONNECTSTATUS ms_pfnRasGetConnectStatus
;
212 static RASGETERRORSTRING ms_pfnRasGetErrorString
;
213 static RASHANGUP ms_pfnRasHangUp
;
214 static RASGETPROJECTIONINFO ms_pfnRasGetProjectionInfo
;
215 static RASCREATEPHONEBOOKENTRY ms_pfnRasCreatePhonebookEntry
;
216 static RASEDITPHONEBOOKENTRY ms_pfnRasEditPhonebookEntry
;
217 static RASSETENTRYDIALPARAMS ms_pfnRasSetEntryDialParams
;
218 static RASGETENTRYDIALPARAMS ms_pfnRasGetEntryDialParams
;
219 static RASENUMDEVICES ms_pfnRasEnumDevices
;
220 static RASGETCOUNTRYINFO ms_pfnRasGetCountryInfo
;
221 static RASGETENTRYPROPERTIES ms_pfnRasGetEntryProperties
;
222 static RASSETENTRYPROPERTIES ms_pfnRasSetEntryProperties
;
223 static RASRENAMEENTRY ms_pfnRasRenameEntry
;
224 static RASDELETEENTRY ms_pfnRasDeleteEntry
;
225 static RASVALIDATEENTRYNAME ms_pfnRasValidateEntryName
;
227 // this function is not supported by Win95
228 static RASCONNECTIONNOTIFICATION ms_pfnRasConnectionNotification
;
230 // if this flag is different from -1, it overrides IsOnline()
231 static int ms_userSpecifiedOnlineStatus
;
233 // this flag tells us if we're online
234 static int ms_isConnected
;
236 // this flag tells us whether a call to RasDial() is in progress
237 static wxDialUpManagerMSW
*ms_dialer
;
240 // ----------------------------------------------------------------------------
242 // ----------------------------------------------------------------------------
244 static LRESULT WINAPI
wxRasStatusWindowProc(HWND hWnd
, UINT message
,
245 WPARAM wParam
, LPARAM lParam
);
247 static DWORD
wxRasMonitorThread(wxRasThreadData
*data
);
249 static void WINAPI
wxRasDialFunc(UINT unMsg
,
250 RASCONNSTATE rasconnstate
,
253 // ============================================================================
255 // ============================================================================
257 // ----------------------------------------------------------------------------
258 // init the static variables
259 // ----------------------------------------------------------------------------
261 HRASCONN
wxDialUpManagerMSW::ms_hRasConnection
= 0;
263 int wxDialUpManagerMSW::ms_nDllCount
= 0;
264 wxDllType
wxDialUpManagerMSW::ms_dllRas
= 0;
266 RASDIAL
wxDialUpManagerMSW::ms_pfnRasDial
= 0;
267 RASENUMCONNECTIONS
wxDialUpManagerMSW::ms_pfnRasEnumConnections
= 0;
268 RASENUMENTRIES
wxDialUpManagerMSW::ms_pfnRasEnumEntries
= 0;
269 RASGETCONNECTSTATUS
wxDialUpManagerMSW::ms_pfnRasGetConnectStatus
= 0;
270 RASGETERRORSTRING
wxDialUpManagerMSW::ms_pfnRasGetErrorString
= 0;
271 RASHANGUP
wxDialUpManagerMSW::ms_pfnRasHangUp
= 0;
272 RASGETPROJECTIONINFO
wxDialUpManagerMSW::ms_pfnRasGetProjectionInfo
= 0;
273 RASCREATEPHONEBOOKENTRY
wxDialUpManagerMSW::ms_pfnRasCreatePhonebookEntry
= 0;
274 RASEDITPHONEBOOKENTRY
wxDialUpManagerMSW::ms_pfnRasEditPhonebookEntry
= 0;
275 RASSETENTRYDIALPARAMS
wxDialUpManagerMSW::ms_pfnRasSetEntryDialParams
= 0;
276 RASGETENTRYDIALPARAMS
wxDialUpManagerMSW::ms_pfnRasGetEntryDialParams
= 0;
277 RASENUMDEVICES
wxDialUpManagerMSW::ms_pfnRasEnumDevices
= 0;
278 RASGETCOUNTRYINFO
wxDialUpManagerMSW::ms_pfnRasGetCountryInfo
= 0;
279 RASGETENTRYPROPERTIES
wxDialUpManagerMSW::ms_pfnRasGetEntryProperties
= 0;
280 RASSETENTRYPROPERTIES
wxDialUpManagerMSW::ms_pfnRasSetEntryProperties
= 0;
281 RASRENAMEENTRY
wxDialUpManagerMSW::ms_pfnRasRenameEntry
= 0;
282 RASDELETEENTRY
wxDialUpManagerMSW::ms_pfnRasDeleteEntry
= 0;
283 RASVALIDATEENTRYNAME
wxDialUpManagerMSW::ms_pfnRasValidateEntryName
= 0;
284 RASCONNECTIONNOTIFICATION
wxDialUpManagerMSW::ms_pfnRasConnectionNotification
= 0;
286 int wxDialUpManagerMSW::ms_userSpecifiedOnlineStatus
= -1;
287 int wxDialUpManagerMSW::ms_isConnected
= -1;
288 wxDialUpManagerMSW
*wxDialUpManagerMSW::ms_dialer
= NULL
;
290 // ----------------------------------------------------------------------------
291 // ctor and dtor: the dynamic linking happens here
292 // ----------------------------------------------------------------------------
294 // the static creator function is implemented here
295 wxDialUpManager
*wxDialUpManager::Create()
297 return new wxDialUpManagerMSW
;
301 // warning about "'this' : used in base member initializer list" - so what?
302 #pragma warning(disable:4355)
305 wxDialUpManagerMSW::wxDialUpManagerMSW()
306 : m_timerStatusPolling(this)
308 // initialize our data
311 if ( !ms_nDllCount
++ )
313 // load the RAS library
314 ms_dllRas
= wxDllLoader::LoadLibrary("RASAPI32");
317 wxLogError(_("Dial up functions are unavailable because the "
318 "remote access service (RAS) is not installed "
319 "on this machine. Please install it."));
323 // resolve the functions we need
325 // this will contain the name of the function we failed to resolve
327 const char *funcName
= NULL
;
329 // get the function from rasapi32.dll and abort if it's not found
330 #define RESOLVE_RAS_FUNCTION(type, name) \
331 ms_pfn##name = (type)wxDllLoader::GetSymbol(ms_dllRas, \
332 wxString(#name) + gs_funcSuffix); \
333 if ( !ms_pfn##name ) \
339 // a variant of above macro which doesn't abort if the function is
340 // not found in the DLL
341 #define RESOLVE_OPTIONAL_RAS_FUNCTION(type, name) \
342 ms_pfn##name = (type)wxDllLoader::GetSymbol(ms_dllRas, \
343 wxString(#name) + gs_funcSuffix);
345 RESOLVE_RAS_FUNCTION(RASDIAL
, RasDial
);
346 RESOLVE_RAS_FUNCTION(RASENUMCONNECTIONS
, RasEnumConnections
);
347 RESOLVE_RAS_FUNCTION(RASENUMENTRIES
, RasEnumEntries
);
348 RESOLVE_RAS_FUNCTION(RASGETCONNECTSTATUS
, RasGetConnectStatus
);
349 RESOLVE_RAS_FUNCTION(RASGETERRORSTRING
, RasGetErrorString
);
350 RESOLVE_RAS_FUNCTION(RASHANGUP
, RasHangUp
);
352 // suppress wxDllLoader messages about missing (non essential)
357 RESOLVE_OPTIONAL_RAS_FUNCTION(RASGETPROJECTIONINFO
, RasGetProjectionInfo
);
358 RESOLVE_OPTIONAL_RAS_FUNCTION(RASCREATEPHONEBOOKENTRY
, RasCreatePhonebookEntry
);
359 RESOLVE_OPTIONAL_RAS_FUNCTION(RASEDITPHONEBOOKENTRY
, RasEditPhonebookEntry
);
360 RESOLVE_OPTIONAL_RAS_FUNCTION(RASSETENTRYDIALPARAMS
, RasSetEntryDialParams
);
361 RESOLVE_OPTIONAL_RAS_FUNCTION(RASGETENTRYDIALPARAMS
, RasGetEntryDialParams
);
362 RESOLVE_OPTIONAL_RAS_FUNCTION(RASGETENTRYPROPERTIES
, RasGetEntryProperties
);
363 RESOLVE_OPTIONAL_RAS_FUNCTION(RASSETENTRYPROPERTIES
, RasSetEntryProperties
);
364 RESOLVE_OPTIONAL_RAS_FUNCTION(RASRENAMEENTRY
, RasRenameEntry
);
365 RESOLVE_OPTIONAL_RAS_FUNCTION(RASDELETEENTRY
, RasDeleteEntry
);
366 RESOLVE_OPTIONAL_RAS_FUNCTION(RASVALIDATEENTRYNAME
, RasValidateEntryName
);
367 RESOLVE_OPTIONAL_RAS_FUNCTION(RASGETCOUNTRYINFO
, RasGetCountryInfo
);
368 RESOLVE_OPTIONAL_RAS_FUNCTION(RASENUMDEVICES
, RasEnumDevices
);
369 RESOLVE_OPTIONAL_RAS_FUNCTION(RASCONNECTIONNOTIFICATION
, RasConnectionNotification
);
372 // keep your preprocessor name space clean
373 #undef RESOLVE_RAS_FUNCTION
374 #undef RESOLVE_OPTIONAL_RAS_FUNCTION
379 wxLogError(_("The version of remote access service (RAS) "
380 "installed on this machine is too old, please "
381 "upgrade (the following required function is "
382 "missing: %s)."), funcName
);
384 wxDllLoader::UnloadLibrary(ms_dllRas
);
393 // enable auto check by default
394 EnableAutoCheckOnlineStatus(0);
397 wxDialUpManagerMSW::~wxDialUpManagerMSW()
401 if ( !--ms_nDllCount
)
403 // unload the RAS library
404 wxDllLoader::UnloadLibrary(ms_dllRas
);
409 // ----------------------------------------------------------------------------
411 // ----------------------------------------------------------------------------
413 wxString
wxDialUpManagerMSW::GetErrorString(DWORD error
)
415 wxChar buffer
[512]; // this should be more than enough according to MS docs
416 DWORD dwRet
= ms_pfnRasGetErrorString(error
, buffer
, WXSIZEOF(buffer
));
419 case ERROR_INVALID_PARAMETER
:
420 // this was a standard Win32 error probably
421 return wxString(wxSysErrorMsg(error
));
425 wxLogSysError(dwRet
, _("Failed to retrieve text of RAS "
429 msg
.Printf(_("unknown error (error code %08x)."), error
);
434 // we want the error message to start from a lower case letter
435 buffer
[0] = wxTolower(buffer
[0]);
437 return wxString(buffer
);
441 HRASCONN
wxDialUpManagerMSW::FindActiveConnection()
443 // enumerate connections
444 DWORD cbBuf
= sizeof(RASCONN
);
445 LPRASCONN lpRasConn
= (LPRASCONN
)malloc(cbBuf
);
452 lpRasConn
->dwSize
= sizeof(RASCONN
);
454 DWORD nConnections
= 0;
455 DWORD dwRet
= ERROR_BUFFER_TOO_SMALL
;
457 while ( dwRet
== ERROR_BUFFER_TOO_SMALL
)
459 dwRet
= ms_pfnRasEnumConnections(lpRasConn
, &cbBuf
, &nConnections
);
461 if ( dwRet
== ERROR_BUFFER_TOO_SMALL
)
463 LPRASCONN lpRasConnOld
= lpRasConn
;
464 lpRasConn
= (LPRASCONN
)realloc(lpRasConn
, cbBuf
);
473 else if ( dwRet
== 0 )
481 wxLogError(_("Cannot find active dialup connection: %s"),
482 GetErrorString(dwRet
));
489 switch ( nConnections
)
497 // more than 1 connection - we don't know what to do with this
498 // case, so give a warning but continue (taking the first
499 // connection) - the warning is really needed because this function
500 // is used, for example, to select the connection to hang up and so
501 // we may hang up the wrong connection here...
502 wxLogWarning(_("Several active dialup connections found, "
503 "choosing one randomly."));
507 // exactly 1 connection, great
508 hrasconn
= lpRasConn
->hrasconn
;
516 void wxDialUpManagerMSW::CleanUpThreadData()
520 if ( !SetEvent(m_data
.hEventQuit
) )
522 wxLogLastError("SetEvent(RasThreadQuit)");
525 CloseHandle(m_hThread
);
532 DestroyWindow(m_data
.hWnd
);
537 if ( m_data
.hEventQuit
)
539 CloseHandle(m_data
.hEventQuit
);
541 m_data
.hEventQuit
= 0;
544 if ( m_data
.hEventRas
)
546 CloseHandle(m_data
.hEventRas
);
548 m_data
.hEventRas
= 0;
552 // ----------------------------------------------------------------------------
554 // ----------------------------------------------------------------------------
556 void wxDialUpManagerMSW::CheckRasStatus()
558 // use int, not bool to compare with -1
559 int isConnected
= FindActiveConnection() != 0;
560 if ( isConnected
!= ms_isConnected
)
562 if ( ms_isConnected
!= -1 )
564 // notify the program
565 NotifyApp(isConnected
!= 0);
567 // else: it's the first time we're called, just update the flag
569 ms_isConnected
= isConnected
;
573 void wxDialUpManagerMSW::NotifyApp(bool connected
, bool fromOurselves
) const
575 wxDialUpEvent
event(connected
, fromOurselves
);
576 (void)wxTheApp
->ProcessEvent(event
);
579 // this function is called whenever the status of any RAS connection on this
580 // machine changes by RAS itself
581 void wxDialUpManagerMSW::OnConnectStatusChange()
583 // we know that status changed, but we don't know whether we're connected
584 // or not - so find it out
588 // this function is called by our callback which we give to RasDial() when
589 // calling it asynchronously
590 void wxDialUpManagerMSW::OnDialProgress(RASCONNSTATE rasconnstate
,
595 // this probably means that CancelDialing() was called and we get
596 // "disconnected" notification
600 // we're only interested in 2 events: connected and disconnected
603 wxLogError(_("Failed to establish dialup connection: %s"),
604 GetErrorString(dwError
));
606 // we should still call RasHangUp() if we got a non 0 connection
607 if ( ms_hRasConnection
)
609 ms_pfnRasHangUp(ms_hRasConnection
);
610 ms_hRasConnection
= 0;
615 NotifyApp(FALSE
/* !connected */, TRUE
/* we dialed ourselves */);
617 else if ( rasconnstate
== RASCS_Connected
)
619 ms_isConnected
= TRUE
;
622 NotifyApp(TRUE
/* connected */, TRUE
/* we dialed ourselves */);
626 // ----------------------------------------------------------------------------
627 // implementation of wxDialUpManager functions
628 // ----------------------------------------------------------------------------
630 bool wxDialUpManagerMSW::IsOk() const
632 return ms_dllRas
!= 0;
635 bool wxDialUpManagerMSW::Dial(const wxString
& nameOfISP
,
636 const wxString
& username
,
637 const wxString
& password
,
640 wxCHECK_MSG( IsOk(), FALSE
, T("using uninitialized wxDialUpManager") );
642 if ( ms_hRasConnection
)
644 wxFAIL_MSG(T("there is already an active connection"));
649 RASDIALPARAMS rasDialParams
;
650 rasDialParams
.dwSize
= sizeof(rasDialParams
);
651 strncpy(rasDialParams
.szEntryName
, nameOfISP
, RAS_MaxEntryName
);
652 rasDialParams
.szPhoneNumber
[0] = '\0';
653 rasDialParams
.szCallbackNumber
[0] = '\0';
654 rasDialParams
.szCallbackNumber
[0] = '\0';
656 strncpy(rasDialParams
.szUserName
, username
, UNLEN
);
657 strncpy(rasDialParams
.szPassword
, password
, PWLEN
);
659 rasDialParams
.szDomain
[0] = '*';
660 rasDialParams
.szDomain
[1] = '\0';
662 // apparently, this is not really necessary - passing NULL instead of the
663 // phone book has the same effect
666 if ( wxGetOsVersion() == wxWINDOWS_NT
)
668 // first get the length
669 UINT nLen
= ::GetSystemDirectory(NULL
, 0);
672 if ( !::GetSystemDirectory(phoneBook
.GetWriteBuf(nLen
), nLen
) )
674 wxLogSysError(_("Cannot find the location of address book file"));
677 phoneBook
.UngetWriteBuf();
679 // this is the default phone book
680 phoneBook
<< "\\ras\\rasphone.pbk";
684 // TODO may be we should disable auto check while async dialing is in
689 DWORD dwRet
= ms_pfnRasDial
691 (LPRASDIALEXTENSIONS
)NULL
, // no extended features
692 NULL
, // default phone book file (NT only)
694 0, // use callback for notifications
695 async
? wxRasDialFunc
// the callback
696 : 0, // no notifications - sync operation
702 wxLogError(_("Failed to %s dialup connection: %s"),
703 async
? _("initiate") : _("establish"),
704 GetErrorString(dwRet
));
706 // we should still call RasHangUp() if we got a non 0 connection
707 if ( ms_hRasConnection
)
709 ms_pfnRasHangUp(ms_hRasConnection
);
710 ms_hRasConnection
= 0;
718 // for async dialing, we're not yet connected
721 ms_isConnected
= TRUE
;
727 bool wxDialUpManagerMSW::IsDialing() const
729 return GetDialer() != NULL
;
732 bool wxDialUpManagerMSW::CancelDialing()
740 wxASSERT_MSG( ms_hRasConnection
, T("dialing but no connection?") );
747 bool wxDialUpManagerMSW::HangUp()
749 wxCHECK_MSG( IsOk(), FALSE
, T("using uninitialized wxDialUpManager") );
751 // we may terminate either the connection we initiated or another one which
754 if ( ms_hRasConnection
)
756 hRasConn
= ms_hRasConnection
;
758 ms_hRasConnection
= 0;
762 hRasConn
= FindActiveConnection();
767 wxLogError(_("Cannot hang up - no active dialup connection."));
772 DWORD dwRet
= ms_pfnRasHangUp(hRasConn
);
775 wxLogError(_("Failed to terminate the dialup connection: %s"),
776 GetErrorString(dwRet
));
779 ms_isConnected
= FALSE
;
784 bool wxDialUpManagerMSW::IsOnline() const
786 wxCHECK_MSG( IsOk(), FALSE
, T("using uninitialized wxDialUpManager") );
788 if ( ms_userSpecifiedOnlineStatus
!= -1 )
790 // user specified flag overrides our logic
791 return ms_userSpecifiedOnlineStatus
!= 0;
795 // return TRUE if there is at least one active connection
796 return FindActiveConnection() != 0;
800 void wxDialUpManagerMSW::SetOnlineStatus(bool isOnline
)
802 wxCHECK_RET( IsOk(), T("using uninitialized wxDialUpManager") );
804 ms_userSpecifiedOnlineStatus
= isOnline
;
807 bool wxDialUpManagerMSW::EnableAutoCheckOnlineStatus(size_t nSeconds
)
809 wxCHECK_MSG( IsOk(), FALSE
, T("using uninitialized wxDialUpManager") );
811 bool ok
= ms_pfnRasConnectionNotification
!= 0;
815 // we're running under NT 4.0, Windows 98 or later and can use
816 // RasConnectionNotification() to be notified by a secondary thread
818 // first, see if we don't have this thread already running
819 if ( m_hThread
!= 0 )
821 DWORD dwSuspendCount
= 2;
822 while ( dwSuspendCount
> 1 )
824 dwSuspendCount
= ResumeThread(m_hThread
);
825 if ( dwSuspendCount
== (DWORD
)-1 )
827 wxLogLastError("ResumeThread(RasThread)");
840 // create all the stuff we need to be notified about RAS connection
845 // first create an event to wait on
846 m_data
.hEventRas
= CreateEvent
848 NULL
, // security attribute (default)
849 FALSE
, // manual reset (not)
850 FALSE
, // initial state (not signaled)
853 if ( !m_data
.hEventRas
)
855 wxLogLastError("CreateEvent(RasStatus)");
863 // create the event we use to quit the thread
864 m_data
.hEventQuit
= CreateEvent(NULL
, FALSE
, FALSE
, NULL
);
865 if ( !m_data
.hEventQuit
)
867 wxLogLastError("CreateEvent(RasThreadQuit)");
877 // create a hidden window to receive notification about connections
879 extern wxChar wxPanelClassName
[];
880 m_data
.hWnd
= ::CreateWindow(wxPanelClassName
, NULL
,
883 (HMENU
)NULL
, wxGetInstance(), 0);
886 wxLogLastError("CreateWindow(RasHiddenWindow)");
894 FARPROC windowProc
= MakeProcInstance
896 (FARPROC
)wxRasStatusWindowProc
,
900 ::SetWindowLong(m_data
.hWnd
, GWL_WNDPROC
, (LONG
) windowProc
);
905 // start the secondary thread
906 m_data
.dialUpManager
= this;
909 m_hThread
= CreateThread
913 (LPTHREAD_START_ROUTINE
)wxRasMonitorThread
,
921 wxLogLastError("CreateThread(RasStatusThread)");
929 // start receiving RAS notifications
930 DWORD dwRet
= ms_pfnRasConnectionNotification
932 (HRASCONN
)INVALID_HANDLE_VALUE
,
934 3 /* RASCN_Connection | RASCN_Disconnection */
939 wxLogDebug(T("RasConnectionNotification() failed: %s"),
940 GetErrorString(dwRet
));
950 // we're running under Windows 95 and have to poll ourselves
951 // (or, alternatively, the code above for NT/98 failed)
952 m_timerStatusPolling
.Stop();
958 m_timerStatusPolling
.Start(nSeconds
* 1000);
963 void wxDialUpManagerMSW::DisableAutoCheckOnlineStatus()
965 wxCHECK_RET( IsOk(), T("using uninitialized wxDialUpManager") );
969 // we have running secondary thread, it's just enough to suspend it
970 if ( SuspendThread(m_hThread
) == (DWORD
)-1 )
972 wxLogLastError("SuspendThread(RasThread)");
977 // even simpler - just stop the timer
978 m_timerStatusPolling
.Stop();
982 // ----------------------------------------------------------------------------
983 // stubs which don't do anything in MSW version
984 // ----------------------------------------------------------------------------
986 void wxDialUpManagerMSW::SetWellKnownHost(const wxString
& WXUNUSED(hostname
),
989 wxCHECK_RET( IsOk(), T("using uninitialized wxDialUpManager") );
991 // nothing to do - we don't use this
994 void wxDialUpManagerMSW::SetConnectCommand(const wxString
& WXUNUSED(dial
),
995 const wxString
& WXUNUSED(hangup
))
997 wxCHECK_RET( IsOk(), T("using uninitialized wxDialUpManager") );
999 // nothing to do - we don't use this
1002 // ----------------------------------------------------------------------------
1004 // ----------------------------------------------------------------------------
1006 static DWORD
wxRasMonitorThread(wxRasThreadData
*data
)
1009 handles
[0] = data
->hEventRas
;
1010 handles
[1] = data
->hEventQuit
;
1015 DWORD dwRet
= WaitForMultipleObjects(2, handles
, FALSE
, INFINITE
);
1020 // RAS connection status changed
1021 SendMessage(data
->hWnd
, wxWM_RAS_STATUS_CHANGED
,
1025 case WAIT_OBJECT_0
+ 1:
1030 wxLogLastError("WaitForMultipleObjects(RasMonitor)");
1038 static LRESULT APIENTRY
wxRasStatusWindowProc(HWND hWnd
, UINT message
,
1039 WPARAM wParam
, LPARAM lParam
)
1041 if ( message
== wxWM_RAS_STATUS_CHANGED
)
1043 wxRasThreadData
*data
= (wxRasThreadData
*)lParam
;
1044 data
->dialUpManager
->OnConnectStatusChange();
1050 static void WINAPI
wxRasDialFunc(UINT unMsg
,
1051 RASCONNSTATE rasconnstate
,
1054 wxDialUpManagerMSW
*dialUpManager
= wxDialUpManagerMSW::GetDialer();
1056 wxCHECK_RET( dialUpManager
, T("who started to dial then?") );
1058 dialUpManager
->OnDialProgress(rasconnstate
, dwError
);
1061 #endif // wxUSE_DIALUP_MANAGER