]> git.saurik.com Git - wxWidgets.git/blame - src/msw/dialup.cpp
Don't take hidden wxGrid row/columns into account when auto-sizing.
[wxWidgets.git] / src / msw / dialup.cpp
CommitLineData
a0b4c98b 1/////////////////////////////////////////////////////////////////////////////
670f9935 2// Name: src/msw/dialup.cpp
a0b4c98b
VZ
3// Purpose: MSW implementation of network/dialup classes and functions
4// Author: Vadim Zeitlin
5// Modified by:
6// Created: 07.07.99
a0b4c98b 7// Copyright: (c) Vadim Zeitlin
65571936 8// Licence: wxWindows licence
a0b4c98b
VZ
9/////////////////////////////////////////////////////////////////////////////
10
11// ============================================================================
12// declarations
13// ============================================================================
14
15// ----------------------------------------------------------------------------
16// headers
17// ----------------------------------------------------------------------------
18
19// for compilers that support precompilation, includes "wx.h".
20#include "wx/wxprec.h"
21
22#ifdef __BORLANDC__
23 #pragma hdrstop
24#endif
25
a0b4c98b
VZ
26#if wxUSE_DIALUP_MANAGER
27
670f9935
WS
28#include "wx/dialup.h"
29
a0b4c98b
VZ
30#ifndef WX_PRECOMP
31 #include "wx/log.h"
d1f4970d
VZ
32 #include "wx/intl.h"
33 #include "wx/event.h"
670f9935 34 #include "wx/app.h"
c0badb70 35 #include "wx/timer.h"
02761f6c 36 #include "wx/module.h"
a0b4c98b
VZ
37#endif
38
fcec6429
VZ
39#include "wx/generic/choicdgg.h"
40
142ae7b3 41#include "wx/msw/private.h"
b481194f 42#include "wx/msw/private/hiddenwin.h"
a0b4c98b 43#include "wx/dynlib.h"
a0b4c98b 44
9b11752c
VZ
45wxDEFINE_EVENT( wxEVT_DIALUP_CONNECTED, wxDialUpEvent );
46wxDEFINE_EVENT( wxEVT_DIALUP_DISCONNECTED, wxDialUpEvent );
2e4df4bf 47
3bce6687
JS
48// Doesn't yet compile under VC++ 4, BC++, Watcom C++,
49// Wine: no wininet.h
3aabb24c 50#if (!defined(__BORLANDC__) || (__BORLANDC__>=0x550)) && \
ce20b5d7 51 (!defined(__GNUWIN32__) || wxCHECK_W32API_VERSION(0, 5)) && \
7ba4fbeb 52 !defined(__GNUWIN32_OLD__) && \
5283098e 53 !defined(__WINE__) && \
7ba4fbeb 54 (!defined(__VISUALC__) || (__VISUALC__ >= 1020))
106f0395 55
a0b4c98b
VZ
56#include <ras.h>
57#include <raserror.h>
58
2690830e
VZ
59#include <wininet.h>
60
a2327a9f
JS
61// Not in VC++ 5
62#ifndef INTERNET_CONNECTION_LAN
63#define INTERNET_CONNECTION_LAN 2
64#endif
65#ifndef INTERNET_CONNECTION_PROXY
66#define INTERNET_CONNECTION_PROXY 4
67#endif
68
8563c6f1
VZ
69static const wxChar *
70 wxMSWDIALUP_WNDCLASSNAME = wxT("_wxDialUpManager_Internal_Class");
71static const wxChar *gs_classForDialUpWindow = NULL;
72
a0b4c98b
VZ
73// ----------------------------------------------------------------------------
74// constants
75// ----------------------------------------------------------------------------
76
77// this message is sent by the secondary thread when RAS status changes
78#define wxWM_RAS_STATUS_CHANGED (WM_USER + 10010)
2690830e 79#define wxWM_RAS_DIALING_PROGRESS (WM_USER + 10011)
a0b4c98b
VZ
80
81// ----------------------------------------------------------------------------
82// types
83// ----------------------------------------------------------------------------
84
85// the signatures of RAS functions: all this is quite heavy, but we must do it
86// to allow running wxWin programs on machine which don't have RAS installed
87// (this does exist) - if we link with rasapi32.lib, the program will fail on
88// startup because of the missing DLL...
89
90#ifndef UNICODE
2690830e
VZ
91 typedef DWORD (APIENTRY * RASDIAL)( LPRASDIALEXTENSIONS, LPCSTR, LPRASDIALPARAMSA, DWORD, LPVOID, LPHRASCONN );
92 typedef DWORD (APIENTRY * RASENUMCONNECTIONS)( LPRASCONNA, LPDWORD, LPDWORD );
93 typedef DWORD (APIENTRY * RASENUMENTRIES)( LPCSTR, LPCSTR, LPRASENTRYNAMEA, LPDWORD, LPDWORD );
94 typedef DWORD (APIENTRY * RASGETCONNECTSTATUS)( HRASCONN, LPRASCONNSTATUSA );
95 typedef DWORD (APIENTRY * RASGETERRORSTRING)( UINT, LPSTR, DWORD );
96 typedef DWORD (APIENTRY * RASHANGUP)( HRASCONN );
97 typedef DWORD (APIENTRY * RASGETPROJECTIONINFO)( HRASCONN, RASPROJECTION, LPVOID, LPDWORD );
98 typedef DWORD (APIENTRY * RASCREATEPHONEBOOKENTRY)( HWND, LPCSTR );
99 typedef DWORD (APIENTRY * RASEDITPHONEBOOKENTRY)( HWND, LPCSTR, LPCSTR );
100 typedef DWORD (APIENTRY * RASSETENTRYDIALPARAMS)( LPCSTR, LPRASDIALPARAMSA, BOOL );
101 typedef DWORD (APIENTRY * RASGETENTRYDIALPARAMS)( LPCSTR, LPRASDIALPARAMSA, LPBOOL );
102 typedef DWORD (APIENTRY * RASENUMDEVICES)( LPRASDEVINFOA, LPDWORD, LPDWORD );
103 typedef DWORD (APIENTRY * RASGETCOUNTRYINFO)( LPRASCTRYINFOA, LPDWORD );
104 typedef DWORD (APIENTRY * RASGETENTRYPROPERTIES)( LPCSTR, LPCSTR, LPRASENTRYA, LPDWORD, LPBYTE, LPDWORD );
105 typedef DWORD (APIENTRY * RASSETENTRYPROPERTIES)( LPCSTR, LPCSTR, LPRASENTRYA, DWORD, LPBYTE, DWORD );
106 typedef DWORD (APIENTRY * RASRENAMEENTRY)( LPCSTR, LPCSTR, LPCSTR );
107 typedef DWORD (APIENTRY * RASDELETEENTRY)( LPCSTR, LPCSTR );
108 typedef DWORD (APIENTRY * RASVALIDATEENTRYNAME)( LPCSTR, LPCSTR );
109 typedef DWORD (APIENTRY * RASCONNECTIONNOTIFICATION)( HRASCONN, HANDLE, DWORD );
a0b4c98b 110
9a83f860 111 static const wxChar gs_funcSuffix = wxT('A');
a0b4c98b 112#else // Unicode
2690830e
VZ
113 typedef DWORD (APIENTRY * RASDIAL)( LPRASDIALEXTENSIONS, LPCWSTR, LPRASDIALPARAMSW, DWORD, LPVOID, LPHRASCONN );
114 typedef DWORD (APIENTRY * RASENUMCONNECTIONS)( LPRASCONNW, LPDWORD, LPDWORD );
115 typedef DWORD (APIENTRY * RASENUMENTRIES)( LPCWSTR, LPCWSTR, LPRASENTRYNAMEW, LPDWORD, LPDWORD );
116 typedef DWORD (APIENTRY * RASGETCONNECTSTATUS)( HRASCONN, LPRASCONNSTATUSW );
117 typedef DWORD (APIENTRY * RASGETERRORSTRING)( UINT, LPWSTR, DWORD );
118 typedef DWORD (APIENTRY * RASHANGUP)( HRASCONN );
119 typedef DWORD (APIENTRY * RASGETPROJECTIONINFO)( HRASCONN, RASPROJECTION, LPVOID, LPDWORD );
120 typedef DWORD (APIENTRY * RASCREATEPHONEBOOKENTRY)( HWND, LPCWSTR );
121 typedef DWORD (APIENTRY * RASEDITPHONEBOOKENTRY)( HWND, LPCWSTR, LPCWSTR );
122 typedef DWORD (APIENTRY * RASSETENTRYDIALPARAMS)( LPCWSTR, LPRASDIALPARAMSW, BOOL );
123 typedef DWORD (APIENTRY * RASGETENTRYDIALPARAMS)( LPCWSTR, LPRASDIALPARAMSW, LPBOOL );
124 typedef DWORD (APIENTRY * RASENUMDEVICES)( LPRASDEVINFOW, LPDWORD, LPDWORD );
125 typedef DWORD (APIENTRY * RASGETCOUNTRYINFO)( LPRASCTRYINFOW, LPDWORD );
126 typedef DWORD (APIENTRY * RASGETENTRYPROPERTIES)( LPCWSTR, LPCWSTR, LPRASENTRYW, LPDWORD, LPBYTE, LPDWORD );
127 typedef DWORD (APIENTRY * RASSETENTRYPROPERTIES)( LPCWSTR, LPCWSTR, LPRASENTRYW, DWORD, LPBYTE, DWORD );
128 typedef DWORD (APIENTRY * RASRENAMEENTRY)( LPCWSTR, LPCWSTR, LPCWSTR );
129 typedef DWORD (APIENTRY * RASDELETEENTRY)( LPCWSTR, LPCWSTR );
130 typedef DWORD (APIENTRY * RASVALIDATEENTRYNAME)( LPCWSTR, LPCWSTR );
131 typedef DWORD (APIENTRY * RASCONNECTIONNOTIFICATION)( HRASCONN, HANDLE, DWORD );
a0b4c98b 132
9a83f860 133 static const wxChar gs_funcSuffix = wxT('W');
a0b4c98b
VZ
134#endif // ASCII/Unicode
135
136// structure passed to the secondary thread
3b415ba4 137struct WXDLLEXPORT wxRasThreadData
a0b4c98b
VZ
138{
139 wxRasThreadData()
140 {
141 hWnd = 0;
97247d36
VZ
142 hEventRas =
143 hEventQuit = 0;
a0b4c98b
VZ
144 dialUpManager = NULL;
145 }
146
97247d36
VZ
147 ~wxRasThreadData()
148 {
149 if ( hWnd )
150 DestroyWindow(hWnd);
151
152 if ( hEventQuit )
153 CloseHandle(hEventQuit);
154
155 if ( hEventRas )
156 CloseHandle(hEventRas);
157 }
158
a0b4c98b 159 HWND hWnd; // window to send notifications to
97247d36
VZ
160 HANDLE hEventRas, // automatic event which RAS signals when status changes
161 hEventQuit; // manual event which we signal when we terminate
a0b4c98b 162
fb1a4789 163 class WXDLLIMPEXP_FWD_CORE wxDialUpManagerMSW *dialUpManager; // the owner
a0b4c98b
VZ
164};
165
166// ----------------------------------------------------------------------------
167// wxDialUpManager class for MSW
168// ----------------------------------------------------------------------------
169
170class WXDLLEXPORT wxDialUpManagerMSW : public wxDialUpManager
171{
172public:
173 // ctor & dtor
174 wxDialUpManagerMSW();
175 virtual ~wxDialUpManagerMSW();
176
177 // implement base class pure virtuals
178 virtual bool IsOk() const;
2690830e 179 virtual size_t GetISPNames(wxArrayString& names) const;
a0b4c98b
VZ
180 virtual bool Dial(const wxString& nameOfISP,
181 const wxString& username,
182 const wxString& password,
183 bool async);
184 virtual bool IsDialing() const;
185 virtual bool CancelDialing();
186 virtual bool HangUp();
2690830e 187 virtual bool IsAlwaysOnline() const;
a0b4c98b 188 virtual bool IsOnline() const;
d71cc120 189 virtual void SetOnlineStatus(bool isOnline = true);
a0b4c98b
VZ
190 virtual bool EnableAutoCheckOnlineStatus(size_t nSeconds);
191 virtual void DisableAutoCheckOnlineStatus();
192 virtual void SetWellKnownHost(const wxString& hostname, int port);
193 virtual void SetConnectCommand(const wxString& commandDial,
194 const wxString& commandHangup);
195
196 // for RasTimer
197 void CheckRasStatus();
198
199 // for wxRasStatusWindowProc
200 void OnConnectStatusChange();
2690830e 201 void OnDialProgress(RASCONNSTATE rasconnstate, DWORD dwError);
a0b4c98b
VZ
202
203 // for wxRasDialFunc
2690830e 204 static HWND GetRasWindow() { return ms_hwndRas; }
8563c6f1 205 static void ResetRasWindow() { ms_hwndRas = NULL; }
a0b4c98b
VZ
206 static wxDialUpManagerMSW *GetDialer() { return ms_dialer; }
207
208private:
209 // return the error string for the given RAS error code
210 static wxString GetErrorString(DWORD error);
211
212 // find the (first) handle of the active connection
213 static HRASCONN FindActiveConnection();
214
215 // notify the application about status change
d71cc120 216 void NotifyApp(bool connected, bool fromOurselves = false) const;
a0b4c98b
VZ
217
218 // destroy the thread data and the thread itself
219 void CleanUpThreadData();
220
6bba111c
VZ
221 // number of times EnableAutoCheckOnlineStatus() had been called minus the
222 // number of times DisableAutoCheckOnlineStatus() had been called
223 int m_autoCheckLevel;
224
a0b4c98b 225 // timer used for polling RAS status
3b415ba4 226 class WXDLLEXPORT RasTimer : public wxTimer
a0b4c98b
VZ
227 {
228 public:
229 RasTimer(wxDialUpManagerMSW *dialUpManager)
230 { m_dialUpManager = dialUpManager; }
231
232 virtual void Notify() { m_dialUpManager->CheckRasStatus(); }
233
234 private:
235 wxDialUpManagerMSW *m_dialUpManager;
2eb10e2a 236
c0c133e1 237 wxDECLARE_NO_COPY_CLASS(RasTimer);
a0b4c98b
VZ
238 } m_timerStatusPolling;
239
240 // thread handle for the thread sitting on connection change event
241 HANDLE m_hThread;
242
243 // data used by this thread and our hidden window to send messages between
244 // each other
97247d36 245 wxRasThreadData *m_data;
a0b4c98b 246
4f89dbc4 247 // the handle of rasapi32.dll when it's loaded
4522bb3e 248 wxDynamicLibrary m_dllRas;
4f89dbc4 249
2690830e
VZ
250 // the hidden window we use for passing messages between threads
251 static HWND ms_hwndRas;
252
a0b4c98b
VZ
253 // the handle of the connection we initiated or 0 if none
254 static HRASCONN ms_hRasConnection;
255
a0b4c98b
VZ
256 // the pointers to RAS functions
257 static RASDIAL ms_pfnRasDial;
258 static RASENUMCONNECTIONS ms_pfnRasEnumConnections;
259 static RASENUMENTRIES ms_pfnRasEnumEntries;
260 static RASGETCONNECTSTATUS ms_pfnRasGetConnectStatus;
261 static RASGETERRORSTRING ms_pfnRasGetErrorString;
262 static RASHANGUP ms_pfnRasHangUp;
263 static RASGETPROJECTIONINFO ms_pfnRasGetProjectionInfo;
264 static RASCREATEPHONEBOOKENTRY ms_pfnRasCreatePhonebookEntry;
265 static RASEDITPHONEBOOKENTRY ms_pfnRasEditPhonebookEntry;
266 static RASSETENTRYDIALPARAMS ms_pfnRasSetEntryDialParams;
267 static RASGETENTRYDIALPARAMS ms_pfnRasGetEntryDialParams;
268 static RASENUMDEVICES ms_pfnRasEnumDevices;
269 static RASGETCOUNTRYINFO ms_pfnRasGetCountryInfo;
270 static RASGETENTRYPROPERTIES ms_pfnRasGetEntryProperties;
271 static RASSETENTRYPROPERTIES ms_pfnRasSetEntryProperties;
272 static RASRENAMEENTRY ms_pfnRasRenameEntry;
273 static RASDELETEENTRY ms_pfnRasDeleteEntry;
274 static RASVALIDATEENTRYNAME ms_pfnRasValidateEntryName;
275
276 // this function is not supported by Win95
277 static RASCONNECTIONNOTIFICATION ms_pfnRasConnectionNotification;
278
279 // if this flag is different from -1, it overrides IsOnline()
280 static int ms_userSpecifiedOnlineStatus;
281
282 // this flag tells us if we're online
283 static int ms_isConnected;
284
285 // this flag tells us whether a call to RasDial() is in progress
286 static wxDialUpManagerMSW *ms_dialer;
2eb10e2a 287
c0c133e1 288 wxDECLARE_NO_COPY_CLASS(wxDialUpManagerMSW);
a0b4c98b
VZ
289};
290
8563c6f1
VZ
291// module to destroy helper window created by wxDialUpManagerMSW
292class wxDialUpManagerModule : public wxModule
293{
294public:
295 bool OnInit() { return true; }
296 void OnExit()
297 {
298 HWND hwnd = wxDialUpManagerMSW::GetRasWindow();
299 if ( hwnd )
300 {
301 ::DestroyWindow(hwnd);
302 wxDialUpManagerMSW::ResetRasWindow();
303 }
304
305 if ( gs_classForDialUpWindow )
306 {
307 ::UnregisterClass(wxMSWDIALUP_WNDCLASSNAME, wxGetInstance());
308 gs_classForDialUpWindow = NULL;
309 }
310 }
311
312private:
313 DECLARE_DYNAMIC_CLASS(wxDialUpManagerModule)
314};
315
316IMPLEMENT_DYNAMIC_CLASS(wxDialUpManagerModule, wxModule)
317
a0b4c98b
VZ
318// ----------------------------------------------------------------------------
319// private functions
320// ----------------------------------------------------------------------------
321
322static LRESULT WINAPI wxRasStatusWindowProc(HWND hWnd, UINT message,
323 WPARAM wParam, LPARAM lParam);
324
325static DWORD wxRasMonitorThread(wxRasThreadData *data);
326
327static void WINAPI wxRasDialFunc(UINT unMsg,
328 RASCONNSTATE rasconnstate,
329 DWORD dwError);
330
331// ============================================================================
332// implementation
333// ============================================================================
334
335// ----------------------------------------------------------------------------
336// init the static variables
337// ----------------------------------------------------------------------------
338
339HRASCONN wxDialUpManagerMSW::ms_hRasConnection = 0;
340
2690830e
VZ
341HWND wxDialUpManagerMSW::ms_hwndRas = 0;
342
a0b4c98b
VZ
343RASDIAL wxDialUpManagerMSW::ms_pfnRasDial = 0;
344RASENUMCONNECTIONS wxDialUpManagerMSW::ms_pfnRasEnumConnections = 0;
345RASENUMENTRIES wxDialUpManagerMSW::ms_pfnRasEnumEntries = 0;
346RASGETCONNECTSTATUS wxDialUpManagerMSW::ms_pfnRasGetConnectStatus = 0;
347RASGETERRORSTRING wxDialUpManagerMSW::ms_pfnRasGetErrorString = 0;
348RASHANGUP wxDialUpManagerMSW::ms_pfnRasHangUp = 0;
349RASGETPROJECTIONINFO wxDialUpManagerMSW::ms_pfnRasGetProjectionInfo = 0;
350RASCREATEPHONEBOOKENTRY wxDialUpManagerMSW::ms_pfnRasCreatePhonebookEntry = 0;
351RASEDITPHONEBOOKENTRY wxDialUpManagerMSW::ms_pfnRasEditPhonebookEntry = 0;
352RASSETENTRYDIALPARAMS wxDialUpManagerMSW::ms_pfnRasSetEntryDialParams = 0;
353RASGETENTRYDIALPARAMS wxDialUpManagerMSW::ms_pfnRasGetEntryDialParams = 0;
354RASENUMDEVICES wxDialUpManagerMSW::ms_pfnRasEnumDevices = 0;
355RASGETCOUNTRYINFO wxDialUpManagerMSW::ms_pfnRasGetCountryInfo = 0;
356RASGETENTRYPROPERTIES wxDialUpManagerMSW::ms_pfnRasGetEntryProperties = 0;
357RASSETENTRYPROPERTIES wxDialUpManagerMSW::ms_pfnRasSetEntryProperties = 0;
358RASRENAMEENTRY wxDialUpManagerMSW::ms_pfnRasRenameEntry = 0;
359RASDELETEENTRY wxDialUpManagerMSW::ms_pfnRasDeleteEntry = 0;
360RASVALIDATEENTRYNAME wxDialUpManagerMSW::ms_pfnRasValidateEntryName = 0;
361RASCONNECTIONNOTIFICATION wxDialUpManagerMSW::ms_pfnRasConnectionNotification = 0;
362
363int wxDialUpManagerMSW::ms_userSpecifiedOnlineStatus = -1;
364int wxDialUpManagerMSW::ms_isConnected = -1;
365wxDialUpManagerMSW *wxDialUpManagerMSW::ms_dialer = NULL;
366
367// ----------------------------------------------------------------------------
368// ctor and dtor: the dynamic linking happens here
369// ----------------------------------------------------------------------------
370
371// the static creator function is implemented here
372wxDialUpManager *wxDialUpManager::Create()
373{
374 return new wxDialUpManagerMSW;
375}
376
377#ifdef __VISUALC__
378 // warning about "'this' : used in base member initializer list" - so what?
379 #pragma warning(disable:4355)
380#endif // VC++
381
382wxDialUpManagerMSW::wxDialUpManagerMSW()
4522bb3e 383 : m_timerStatusPolling(this),
9a83f860 384 m_dllRas(wxT("RASAPI32"))
a0b4c98b
VZ
385{
386 // initialize our data
6bba111c 387 m_autoCheckLevel = 0;
a0b4c98b 388 m_hThread = 0;
97247d36 389 m_data = new wxRasThreadData;
a0b4c98b 390
4f89dbc4
RL
391 if ( !m_dllRas.IsLoaded() )
392 {
393 wxLogError(_("Dial up functions are unavailable because the remote access service (RAS) is not installed on this machine. Please install it."));
394 }
1c25d245 395 else if ( !ms_pfnRasDial )
a0b4c98b 396 {
4f89dbc4
RL
397 // resolve the functions we need
398
399 // this will contain the name of the function we failed to resolve
400 // if any at the end
401 const char *funcName = NULL;
402
403 // get the function from rasapi32.dll and abort if it's not found
404 #define RESOLVE_RAS_FUNCTION(type, name) \
9a83f860 405 ms_pfn##name = (type)m_dllRas.GetSymbol( wxString(wxT(#name)) \
4f89dbc4
RL
406 + gs_funcSuffix); \
407 if ( !ms_pfn##name ) \
408 { \
409 funcName = #name; \
410 goto exit; \
411 }
412
413 // a variant of above macro which doesn't abort if the function is
414 // not found in the DLL
415 #define RESOLVE_OPTIONAL_RAS_FUNCTION(type, name) \
9a83f860 416 ms_pfn##name = (type)m_dllRas.GetSymbol( wxString(wxT(#name)) \
4f89dbc4
RL
417 + gs_funcSuffix);
418
419 RESOLVE_RAS_FUNCTION(RASDIAL, RasDial);
420 RESOLVE_RAS_FUNCTION(RASENUMCONNECTIONS, RasEnumConnections);
421 RESOLVE_RAS_FUNCTION(RASENUMENTRIES, RasEnumEntries);
422 RESOLVE_RAS_FUNCTION(RASGETCONNECTSTATUS, RasGetConnectStatus);
423 RESOLVE_RAS_FUNCTION(RASGETERRORSTRING, RasGetErrorString);
424 RESOLVE_RAS_FUNCTION(RASHANGUP, RasHangUp);
425 RESOLVE_RAS_FUNCTION(RASGETENTRYDIALPARAMS, RasGetEntryDialParams);
426
427 // suppress error messages about missing (non essential) functions
a0b4c98b 428 {
4f89dbc4
RL
429 wxLogNull noLog;
430
431 RESOLVE_OPTIONAL_RAS_FUNCTION(RASGETPROJECTIONINFO, RasGetProjectionInfo);
432 RESOLVE_OPTIONAL_RAS_FUNCTION(RASCREATEPHONEBOOKENTRY, RasCreatePhonebookEntry);
433 RESOLVE_OPTIONAL_RAS_FUNCTION(RASEDITPHONEBOOKENTRY, RasEditPhonebookEntry);
434 RESOLVE_OPTIONAL_RAS_FUNCTION(RASSETENTRYDIALPARAMS, RasSetEntryDialParams);
435 RESOLVE_OPTIONAL_RAS_FUNCTION(RASGETENTRYPROPERTIES, RasGetEntryProperties);
436 RESOLVE_OPTIONAL_RAS_FUNCTION(RASSETENTRYPROPERTIES, RasSetEntryProperties);
437 RESOLVE_OPTIONAL_RAS_FUNCTION(RASRENAMEENTRY, RasRenameEntry);
438 RESOLVE_OPTIONAL_RAS_FUNCTION(RASDELETEENTRY, RasDeleteEntry);
439 RESOLVE_OPTIONAL_RAS_FUNCTION(RASVALIDATEENTRYNAME, RasValidateEntryName);
440 RESOLVE_OPTIONAL_RAS_FUNCTION(RASGETCOUNTRYINFO, RasGetCountryInfo);
441 RESOLVE_OPTIONAL_RAS_FUNCTION(RASENUMDEVICES, RasEnumDevices);
442 RESOLVE_OPTIONAL_RAS_FUNCTION(RASCONNECTIONNOTIFICATION, RasConnectionNotification);
a0b4c98b 443 }
a0b4c98b 444
4f89dbc4
RL
445 // keep your preprocessor name space clean
446 #undef RESOLVE_RAS_FUNCTION
447 #undef RESOLVE_OPTIONAL_RAS_FUNCTION
a0b4c98b
VZ
448
449exit:
4f89dbc4
RL
450 if ( funcName )
451 {
e6d4038a
VZ
452 wxLogError(_("The version of remote access service (RAS) installed "
453 "on this machine is too old, please upgrade (the "
454 "following required function is missing: %s)."),
455 funcName);
4f89dbc4
RL
456 m_dllRas.Unload();
457 return;
a0b4c98b
VZ
458 }
459 }
460
461 // enable auto check by default
462 EnableAutoCheckOnlineStatus(0);
463}
464
465wxDialUpManagerMSW::~wxDialUpManagerMSW()
466{
467 CleanUpThreadData();
a0b4c98b
VZ
468}
469
470// ----------------------------------------------------------------------------
471// helper functions
472// ----------------------------------------------------------------------------
473
474wxString wxDialUpManagerMSW::GetErrorString(DWORD error)
475{
476 wxChar buffer[512]; // this should be more than enough according to MS docs
477 DWORD dwRet = ms_pfnRasGetErrorString(error, buffer, WXSIZEOF(buffer));
478 switch ( dwRet )
479 {
480 case ERROR_INVALID_PARAMETER:
481 // this was a standard Win32 error probably
482 return wxString(wxSysErrorMsg(error));
483
484 default:
485 {
f6bcfd97
BP
486 wxLogSysError(dwRet,
487 _("Failed to retrieve text of RAS error message"));
a0b4c98b
VZ
488
489 wxString msg;
490 msg.Printf(_("unknown error (error code %08x)."), error);
491 return msg;
492 }
493
494 case 0:
495 // we want the error message to start from a lower case letter
907173e5 496 buffer[0] = (wxChar)wxTolower(buffer[0]);
a0b4c98b
VZ
497
498 return wxString(buffer);
499 }
500}
501
502HRASCONN wxDialUpManagerMSW::FindActiveConnection()
503{
504 // enumerate connections
505 DWORD cbBuf = sizeof(RASCONN);
506 LPRASCONN lpRasConn = (LPRASCONN)malloc(cbBuf);
507 if ( !lpRasConn )
508 {
509 // out of memory
510 return 0;
511 }
512
513 lpRasConn->dwSize = sizeof(RASCONN);
514
515 DWORD nConnections = 0;
516 DWORD dwRet = ERROR_BUFFER_TOO_SMALL;
517
518 while ( dwRet == ERROR_BUFFER_TOO_SMALL )
519 {
520 dwRet = ms_pfnRasEnumConnections(lpRasConn, &cbBuf, &nConnections);
521
522 if ( dwRet == ERROR_BUFFER_TOO_SMALL )
523 {
524 LPRASCONN lpRasConnOld = lpRasConn;
525 lpRasConn = (LPRASCONN)realloc(lpRasConn, cbBuf);
526 if ( !lpRasConn )
527 {
528 // out of memory
529 free(lpRasConnOld);
530
531 return 0;
532 }
533 }
534 else if ( dwRet == 0 )
535 {
536 // ok, success
537 break;
538 }
539 else
540 {
3103e8a9 541 // an error occurred
a0b4c98b 542 wxLogError(_("Cannot find active dialup connection: %s"),
5b09e9c2 543 GetErrorString(dwRet).c_str());
a0b4c98b
VZ
544 return 0;
545 }
546 }
547
548 HRASCONN hrasconn;
549
550 switch ( nConnections )
551 {
552 case 0:
553 // no connections
554 hrasconn = 0;
555 break;
556
557 default:
558 // more than 1 connection - we don't know what to do with this
559 // case, so give a warning but continue (taking the first
560 // connection) - the warning is really needed because this function
561 // is used, for example, to select the connection to hang up and so
562 // we may hang up the wrong connection here...
f6bcfd97 563 wxLogWarning(_("Several active dialup connections found, choosing one randomly."));
a0b4c98b
VZ
564 // fall through
565
566 case 1:
567 // exactly 1 connection, great
568 hrasconn = lpRasConn->hrasconn;
569 }
570
571 free(lpRasConn);
572
573 return hrasconn;
574}
575
576void wxDialUpManagerMSW::CleanUpThreadData()
577{
578 if ( m_hThread )
579 {
97247d36 580 if ( !SetEvent(m_data->hEventQuit) )
a0b4c98b 581 {
9a83f860 582 wxLogLastError(wxT("SetEvent(RasThreadQuit)"));
a0b4c98b 583 }
97247d36
VZ
584 else // sent quit request to the background thread
585 {
586 // the thread still needs m_data so we can't free it here, rather
587 // let the thread do it itself
588 m_data = NULL;
589 }
a0b4c98b
VZ
590
591 CloseHandle(m_hThread);
592
593 m_hThread = 0;
594 }
595
5276b0a5 596 wxDELETE(m_data);
a0b4c98b
VZ
597}
598
599// ----------------------------------------------------------------------------
600// connection status
601// ----------------------------------------------------------------------------
602
603void wxDialUpManagerMSW::CheckRasStatus()
604{
605 // use int, not bool to compare with -1
606 int isConnected = FindActiveConnection() != 0;
607 if ( isConnected != ms_isConnected )
608 {
609 if ( ms_isConnected != -1 )
610 {
611 // notify the program
612 NotifyApp(isConnected != 0);
613 }
614 // else: it's the first time we're called, just update the flag
615
616 ms_isConnected = isConnected;
617 }
618}
619
620void wxDialUpManagerMSW::NotifyApp(bool connected, bool fromOurselves) const
621{
622 wxDialUpEvent event(connected, fromOurselves);
623 (void)wxTheApp->ProcessEvent(event);
624}
625
626// this function is called whenever the status of any RAS connection on this
627// machine changes by RAS itself
628void wxDialUpManagerMSW::OnConnectStatusChange()
629{
630 // we know that status changed, but we don't know whether we're connected
631 // or not - so find it out
632 CheckRasStatus();
633}
634
635// this function is called by our callback which we give to RasDial() when
636// calling it asynchronously
637void wxDialUpManagerMSW::OnDialProgress(RASCONNSTATE rasconnstate,
638 DWORD dwError)
639{
640 if ( !GetDialer() )
641 {
642 // this probably means that CancelDialing() was called and we get
643 // "disconnected" notification
644 return;
645 }
646
647 // we're only interested in 2 events: connected and disconnected
648 if ( dwError )
649 {
650 wxLogError(_("Failed to establish dialup connection: %s"),
5b09e9c2 651 GetErrorString(dwError).c_str());
a0b4c98b
VZ
652
653 // we should still call RasHangUp() if we got a non 0 connection
654 if ( ms_hRasConnection )
655 {
656 ms_pfnRasHangUp(ms_hRasConnection);
657 ms_hRasConnection = 0;
658 }
659
660 ms_dialer = NULL;
661
d71cc120 662 NotifyApp(false /* !connected */, true /* we dialed ourselves */);
a0b4c98b
VZ
663 }
664 else if ( rasconnstate == RASCS_Connected )
665 {
d71cc120 666 ms_isConnected = true;
a0b4c98b
VZ
667 ms_dialer = NULL;
668
d71cc120 669 NotifyApp(true /* connected */, true /* we dialed ourselves */);
a0b4c98b
VZ
670 }
671}
672
673// ----------------------------------------------------------------------------
674// implementation of wxDialUpManager functions
675// ----------------------------------------------------------------------------
676
677bool wxDialUpManagerMSW::IsOk() const
678{
4f89dbc4 679 return m_dllRas.IsLoaded();
a0b4c98b
VZ
680}
681
2690830e
VZ
682size_t wxDialUpManagerMSW::GetISPNames(wxArrayString& names) const
683{
684 // fetch the entries
685 DWORD size = sizeof(RASENTRYNAME);
686 RASENTRYNAME *rasEntries = (RASENTRYNAME *)malloc(size);
687 rasEntries->dwSize = sizeof(RASENTRYNAME);
688
689 DWORD nEntries;
690 DWORD dwRet;
691 do
692 {
693 dwRet = ms_pfnRasEnumEntries
694 (
695 NULL, // reserved
696 NULL, // default phone book (or all)
697 rasEntries, // [out] buffer for the entries
698 &size, // [in/out] size of the buffer
699 &nEntries // [out] number of entries fetched
700 );
701
702 if ( dwRet == ERROR_BUFFER_TOO_SMALL )
703 {
704 // reallocate the buffer
fb9bea06
JS
705 void *n = realloc(rasEntries, size);
706 if (n == NULL)
707 {
708 free(rasEntries);
709 return 0;
710 }
711 rasEntries = (RASENTRYNAME *)n;
2690830e
VZ
712 }
713 else if ( dwRet != 0 )
714 {
715 // some other error - abort
5b09e9c2
VZ
716 wxLogError(_("Failed to get ISP names: %s"),
717 GetErrorString(dwRet).c_str());
2690830e
VZ
718
719 free(rasEntries);
720
721 return 0u;
722 }
723 }
724 while ( dwRet != 0 );
725
726 // process them
727 names.Empty();
728 for ( size_t n = 0; n < (size_t)nEntries; n++ )
729 {
730 names.Add(rasEntries[n].szEntryName);
731 }
732
733 free(rasEntries);
734
735 // return the number of entries
736 return names.GetCount();
737}
738
a0b4c98b
VZ
739bool wxDialUpManagerMSW::Dial(const wxString& nameOfISP,
740 const wxString& username,
741 const wxString& password,
742 bool async)
743{
2690830e 744 // check preconditions
d71cc120 745 wxCHECK_MSG( IsOk(), false, wxT("using uninitialized wxDialUpManager") );
a0b4c98b
VZ
746
747 if ( ms_hRasConnection )
748 {
223d09f6 749 wxFAIL_MSG(wxT("there is already an active connection"));
a0b4c98b 750
d71cc120 751 return true;
a0b4c98b
VZ
752 }
753
2690830e
VZ
754 // get the default ISP if none given
755 wxString entryName(nameOfISP);
756 if ( !entryName )
757 {
758 wxArrayString names;
759 size_t count = GetISPNames(names);
760 switch ( count )
761 {
762 case 0:
763 // no known ISPs, abort
764 wxLogError(_("Failed to connect: no ISP to dial."));
765
d71cc120 766 return false;
2690830e
VZ
767
768 case 1:
769 // only one ISP, choose it
770 entryName = names[0u];
771 break;
772
773 default:
774 // several ISPs, let the user choose
775 {
776 wxString *strings = new wxString[count];
777 for ( size_t i = 0; i < count; i++ )
778 {
779 strings[i] = names[i];
780 }
781
782 entryName = wxGetSingleChoice
783 (
784 _("Choose ISP to dial"),
f6bcfd97 785 _("Please choose which ISP do you want to connect to"),
2690830e
VZ
786 count,
787 strings
788 );
789
790 delete [] strings;
791
792 if ( !entryName )
793 {
794 // cancelled by user
d71cc120 795 return false;
2690830e
VZ
796 }
797 }
798 }
799 }
800
a0b4c98b
VZ
801 RASDIALPARAMS rasDialParams;
802 rasDialParams.dwSize = sizeof(rasDialParams);
64accea5 803 wxStrlcpy(rasDialParams.szEntryName, entryName.c_str(), RAS_MaxEntryName);
2690830e
VZ
804
805 // do we have the username and password?
806 if ( !username || !password )
807 {
808 BOOL gotPassword;
809 DWORD dwRet = ms_pfnRasGetEntryDialParams
810 (
811 NULL, // default phonebook
812 &rasDialParams, // [in/out] the params of this entry
813 &gotPassword // [out] did we get password?
814 );
815
816 if ( dwRet != 0 )
817 {
818 wxLogError(_("Failed to connect: missing username/password."));
819
d71cc120 820 return false;
2690830e
VZ
821 }
822 }
4f89dbc4
RL
823 else
824 {
64accea5
VZ
825 wxStrlcpy(rasDialParams.szUserName, username.c_str(), UNLEN);
826 wxStrlcpy(rasDialParams.szPassword, password.c_str(), PWLEN);
4f89dbc4 827 }
2690830e 828
4f89dbc4 829 // default values for other fields
a0b4c98b
VZ
830 rasDialParams.szPhoneNumber[0] = '\0';
831 rasDialParams.szCallbackNumber[0] = '\0';
a0b4c98b 832
a0b4c98b
VZ
833 rasDialParams.szDomain[0] = '*';
834 rasDialParams.szDomain[1] = '\0';
835
836 // apparently, this is not really necessary - passing NULL instead of the
837 // phone book has the same effect
838#if 0
839 wxString phoneBook;
840 if ( wxGetOsVersion() == wxWINDOWS_NT )
841 {
842 // first get the length
843 UINT nLen = ::GetSystemDirectory(NULL, 0);
844 nLen++;
845
846 if ( !::GetSystemDirectory(phoneBook.GetWriteBuf(nLen), nLen) )
847 {
848 wxLogSysError(_("Cannot find the location of address book file"));
849 }
850
851 phoneBook.UngetWriteBuf();
852
853 // this is the default phone book
854 phoneBook << "\\ras\\rasphone.pbk";
855 }
856#endif // 0
857
858 // TODO may be we should disable auto check while async dialing is in
859 // progress?
860
861 ms_dialer = this;
862
863 DWORD dwRet = ms_pfnRasDial
864 (
1c25d245
VZ
865 NULL, // no extended features
866 NULL, // default phone book file (NT only)
a0b4c98b 867 &rasDialParams,
1c25d245
VZ
868 0, // use callback for notifications
869 async ? (void *)wxRasDialFunc // cast needed for gcc 3.1
870 : 0, // no notifications, sync operation
a0b4c98b
VZ
871 &ms_hRasConnection
872 );
873
874 if ( dwRet != 0 )
875 {
bf9b6266 876 // can't pass a wxWCharBuffer through ( ... )
32efa676 877 if ( async )
43b2d5e7 878 {
32efa676
VS
879 wxLogError(_("Failed to initiate dialup connection: %s"),
880 GetErrorString(dwRet).c_str());
43b2d5e7 881 }
32efa676 882 else
43b2d5e7 883 {
32efa676
VS
884 wxLogError(_("Failed to establish dialup connection: %s"),
885 GetErrorString(dwRet).c_str());
43b2d5e7 886 }
a0b4c98b
VZ
887
888 // we should still call RasHangUp() if we got a non 0 connection
889 if ( ms_hRasConnection )
890 {
891 ms_pfnRasHangUp(ms_hRasConnection);
892 ms_hRasConnection = 0;
893 }
894
895 ms_dialer = NULL;
896
d71cc120 897 return false;
a0b4c98b
VZ
898 }
899
900 // for async dialing, we're not yet connected
901 if ( !async )
902 {
d71cc120 903 ms_isConnected = true;
a0b4c98b
VZ
904 }
905
d71cc120 906 return true;
a0b4c98b
VZ
907}
908
909bool wxDialUpManagerMSW::IsDialing() const
910{
911 return GetDialer() != NULL;
912}
913
914bool wxDialUpManagerMSW::CancelDialing()
915{
916 if ( !GetDialer() )
917 {
918 // silently ignore
d71cc120 919 return false;
a0b4c98b
VZ
920 }
921
223d09f6 922 wxASSERT_MSG( ms_hRasConnection, wxT("dialing but no connection?") );
a0b4c98b
VZ
923
924 ms_dialer = NULL;
925
926 return HangUp();
927}
928
929bool wxDialUpManagerMSW::HangUp()
930{
d71cc120 931 wxCHECK_MSG( IsOk(), false, wxT("using uninitialized wxDialUpManager") );
a0b4c98b
VZ
932
933 // we may terminate either the connection we initiated or another one which
934 // is active now
935 HRASCONN hRasConn;
936 if ( ms_hRasConnection )
937 {
938 hRasConn = ms_hRasConnection;
939
940 ms_hRasConnection = 0;
941 }
942 else
943 {
944 hRasConn = FindActiveConnection();
945 }
946
947 if ( !hRasConn )
948 {
949 wxLogError(_("Cannot hang up - no active dialup connection."));
950
d71cc120 951 return false;
a0b4c98b
VZ
952 }
953
fbd3c46d
VZ
954 // note that it's not an error if the connection had been already
955 // terminated
956 const DWORD dwRet = ms_pfnRasHangUp(hRasConn);
957 if ( dwRet != 0 && dwRet != ERROR_NO_CONNECTION )
a0b4c98b
VZ
958 {
959 wxLogError(_("Failed to terminate the dialup connection: %s"),
5b09e9c2 960 GetErrorString(dwRet).c_str());
a0b4c98b
VZ
961 }
962
d71cc120 963 ms_isConnected = false;
a0b4c98b 964
d71cc120 965 return true;
a0b4c98b
VZ
966}
967
2690830e
VZ
968bool wxDialUpManagerMSW::IsAlwaysOnline() const
969{
19caf229 970 // assume no permanent connection by default
d71cc120 971 bool isAlwaysOnline = false;
2690830e 972
19caf229 973 // try to use WinInet functions
4f89dbc4
RL
974
975 // NB: we could probably use wxDynamicLibrary here just as well,
976 // but we allow multiple instances of wxDialUpManagerMSW so
977 // we might as well use the ref counted version here too.
978
9a83f860 979 wxDynamicLibrary hDll(wxT("WININET"));
4f89dbc4 980 if ( hDll.IsLoaded() )
2690830e 981 {
5a56be28 982 typedef BOOL (WINAPI *INTERNETGETCONNECTEDSTATE)(LPDWORD, DWORD);
2690830e
VZ
983 INTERNETGETCONNECTEDSTATE pfnInternetGetConnectedState;
984
985 #define RESOLVE_FUNCTION(type, name) \
9a83f860 986 pfn##name = (type)hDll.GetSymbol(wxT(#name))
2690830e
VZ
987
988 RESOLVE_FUNCTION(INTERNETGETCONNECTEDSTATE, InternetGetConnectedState);
989
990 if ( pfnInternetGetConnectedState )
991 {
992 DWORD flags = 0;
993 if ( pfnInternetGetConnectedState(&flags, 0 /* reserved */) )
994 {
995 // there is some connection to the net, see of which type
19caf229
VZ
996 isAlwaysOnline = (flags & (INTERNET_CONNECTION_LAN |
997 INTERNET_CONNECTION_PROXY)) != 0;
2690830e 998 }
19caf229 999 //else: no Internet connection at all
2690830e
VZ
1000 }
1001 }
1002
19caf229 1003 return isAlwaysOnline;
2690830e
VZ
1004}
1005
a0b4c98b
VZ
1006bool wxDialUpManagerMSW::IsOnline() const
1007{
d71cc120 1008 wxCHECK_MSG( IsOk(), false, wxT("using uninitialized wxDialUpManager") );
a0b4c98b 1009
90e9494a
VZ
1010 if ( IsAlwaysOnline() )
1011 {
1012 // always => now
1013 return true;
1014 }
1015
a0b4c98b
VZ
1016 if ( ms_userSpecifiedOnlineStatus != -1 )
1017 {
1018 // user specified flag overrides our logic
1019 return ms_userSpecifiedOnlineStatus != 0;
1020 }
1021 else
1022 {
d71cc120 1023 // return true if there is at least one active connection
a0b4c98b
VZ
1024 return FindActiveConnection() != 0;
1025 }
1026}
1027
1028void wxDialUpManagerMSW::SetOnlineStatus(bool isOnline)
1029{
223d09f6 1030 wxCHECK_RET( IsOk(), wxT("using uninitialized wxDialUpManager") );
a0b4c98b
VZ
1031
1032 ms_userSpecifiedOnlineStatus = isOnline;
1033}
1034
1035bool wxDialUpManagerMSW::EnableAutoCheckOnlineStatus(size_t nSeconds)
1036{
d71cc120 1037 wxCHECK_MSG( IsOk(), false, wxT("using uninitialized wxDialUpManager") );
a0b4c98b 1038
6bba111c
VZ
1039 if ( m_autoCheckLevel++ )
1040 {
1041 // already checking
d71cc120 1042 return true;
6bba111c
VZ
1043 }
1044
a0b4c98b
VZ
1045 bool ok = ms_pfnRasConnectionNotification != 0;
1046
1047 if ( ok )
1048 {
1049 // we're running under NT 4.0, Windows 98 or later and can use
1050 // RasConnectionNotification() to be notified by a secondary thread
1051
1052 // first, see if we don't have this thread already running
1053 if ( m_hThread != 0 )
1054 {
6bba111c 1055 if ( ::ResumeThread(m_hThread) != (DWORD)-1 )
d71cc120 1056 return true;
a0b4c98b 1057
6bba111c
VZ
1058 // we're leaving a zombie thread... but what else can we do?
1059 wxLogLastError(wxT("ResumeThread(RasThread)"));
a0b4c98b 1060
d71cc120 1061 ok = false;
a0b4c98b
VZ
1062 }
1063 }
1064
1065 // create all the stuff we need to be notified about RAS connection
1066 // status change
1067
1068 if ( ok )
1069 {
1070 // first create an event to wait on
d71cc120 1071 m_data->hEventRas = ::CreateEvent
97247d36 1072 (
a0b4c98b 1073 NULL, // security attribute (default)
97247d36 1074 FALSE, // manual reset (no, it is automatic)
a0b4c98b
VZ
1075 FALSE, // initial state (not signaled)
1076 NULL // name (no)
97247d36
VZ
1077 );
1078 if ( !m_data->hEventRas )
a0b4c98b 1079 {
f6bcfd97 1080 wxLogLastError(wxT("CreateEvent(RasStatus)"));
a0b4c98b 1081
d71cc120 1082 ok = false;
a0b4c98b
VZ
1083 }
1084 }
1085
1086 if ( ok )
1087 {
97247d36
VZ
1088 // create the event we use to quit the thread: using a manual event
1089 // here avoids problems with missing the event if wxDialUpManagerMSW
1090 // is created and destroyed immediately, before wxRasStatusWindowProc
1091 // starts waiting on the event
d71cc120 1092 m_data->hEventQuit = ::CreateEvent
97247d36
VZ
1093 (
1094 NULL, // default security
1095 TRUE, // manual event
1096 FALSE, // initially non signalled
1097 NULL // nameless
1098 );
1099 if ( !m_data->hEventQuit )
a0b4c98b 1100 {
f6bcfd97 1101 wxLogLastError(wxT("CreateEvent(RasThreadQuit)"));
a0b4c98b
VZ
1102
1103 CleanUpThreadData();
1104
d71cc120 1105 ok = false;
a0b4c98b
VZ
1106 }
1107 }
1108
2690830e 1109 if ( ok && !ms_hwndRas )
a0b4c98b
VZ
1110 {
1111 // create a hidden window to receive notification about connections
1112 // status change
8563c6f1
VZ
1113 ms_hwndRas = wxCreateHiddenWindow
1114 (
1115 &gs_classForDialUpWindow,
1116 wxMSWDIALUP_WNDCLASSNAME,
1117 wxRasStatusWindowProc
1118 );
2690830e 1119 if ( !ms_hwndRas )
a0b4c98b 1120 {
f6bcfd97 1121 wxLogLastError(wxT("CreateWindow(RasHiddenWindow)"));
a0b4c98b
VZ
1122
1123 CleanUpThreadData();
1124
d71cc120 1125 ok = false;
a0b4c98b 1126 }
a0b4c98b
VZ
1127 }
1128
97247d36 1129 m_data->hWnd = ms_hwndRas;
2690830e 1130
a0b4c98b
VZ
1131 if ( ok )
1132 {
1133 // start the secondary thread
97247d36 1134 m_data->dialUpManager = this;
a0b4c98b
VZ
1135
1136 DWORD tid;
1137 m_hThread = CreateThread
1138 (
1139 NULL,
1140 0,
1141 (LPTHREAD_START_ROUTINE)wxRasMonitorThread,
97247d36 1142 (void *)m_data,
a0b4c98b
VZ
1143 0,
1144 &tid
1145 );
1146
1147 if ( !m_hThread )
1148 {
f6bcfd97 1149 wxLogLastError(wxT("CreateThread(RasStatusThread)"));
a0b4c98b
VZ
1150
1151 CleanUpThreadData();
1152 }
1153 }
1154
1155 if ( ok )
1156 {
1157 // start receiving RAS notifications
1158 DWORD dwRet = ms_pfnRasConnectionNotification
1159 (
1160 (HRASCONN)INVALID_HANDLE_VALUE,
97247d36 1161 m_data->hEventRas,
a0b4c98b
VZ
1162 3 /* RASCN_Connection | RASCN_Disconnection */
1163 );
1164
1165 if ( dwRet != 0 )
1166 {
223d09f6 1167 wxLogDebug(wxT("RasConnectionNotification() failed: %s"),
5b09e9c2 1168 GetErrorString(dwRet).c_str());
a0b4c98b
VZ
1169
1170 CleanUpThreadData();
1171 }
1172 else
1173 {
d71cc120 1174 return true;
a0b4c98b
VZ
1175 }
1176 }
1177
1178 // we're running under Windows 95 and have to poll ourselves
1179 // (or, alternatively, the code above for NT/98 failed)
1180 m_timerStatusPolling.Stop();
1181 if ( nSeconds == 0 )
1182 {
1183 // default value
1184 nSeconds = 60;
1185 }
1186 m_timerStatusPolling.Start(nSeconds * 1000);
1187
d71cc120 1188 return true;
a0b4c98b
VZ
1189}
1190
1191void wxDialUpManagerMSW::DisableAutoCheckOnlineStatus()
1192{
223d09f6 1193 wxCHECK_RET( IsOk(), wxT("using uninitialized wxDialUpManager") );
a0b4c98b 1194
8d7eaf91 1195 if ( --m_autoCheckLevel != 0 )
6bba111c
VZ
1196 {
1197 // still checking
1198 return;
1199 }
1200
a0b4c98b
VZ
1201 if ( m_hThread )
1202 {
1203 // we have running secondary thread, it's just enough to suspend it
1204 if ( SuspendThread(m_hThread) == (DWORD)-1 )
1205 {
f6bcfd97 1206 wxLogLastError(wxT("SuspendThread(RasThread)"));
a0b4c98b
VZ
1207 }
1208 }
1209 else
1210 {
1211 // even simpler - just stop the timer
1212 m_timerStatusPolling.Stop();
1213 }
1214}
1215
1216// ----------------------------------------------------------------------------
1217// stubs which don't do anything in MSW version
1218// ----------------------------------------------------------------------------
1219
1220void wxDialUpManagerMSW::SetWellKnownHost(const wxString& WXUNUSED(hostname),
1221 int WXUNUSED(port))
1222{
223d09f6 1223 wxCHECK_RET( IsOk(), wxT("using uninitialized wxDialUpManager") );
a0b4c98b
VZ
1224
1225 // nothing to do - we don't use this
1226}
1227
1228void wxDialUpManagerMSW::SetConnectCommand(const wxString& WXUNUSED(dial),
1229 const wxString& WXUNUSED(hangup))
1230{
223d09f6 1231 wxCHECK_RET( IsOk(), wxT("using uninitialized wxDialUpManager") );
a0b4c98b
VZ
1232
1233 // nothing to do - we don't use this
1234}
1235
1236// ----------------------------------------------------------------------------
1237// callbacks
1238// ----------------------------------------------------------------------------
1239
1240static DWORD wxRasMonitorThread(wxRasThreadData *data)
1241{
1242 HANDLE handles[2];
1243 handles[0] = data->hEventRas;
1244 handles[1] = data->hEventQuit;
1245
d71cc120 1246 bool cont = true;
a0b4c98b
VZ
1247 while ( cont )
1248 {
d71cc120 1249 DWORD dwRet = ::WaitForMultipleObjects(2, handles, FALSE, INFINITE);
a0b4c98b
VZ
1250
1251 switch ( dwRet )
1252 {
1253 case WAIT_OBJECT_0:
1254 // RAS connection status changed
1255 SendMessage(data->hWnd, wxWM_RAS_STATUS_CHANGED,
1256 0, (LPARAM)data);
1257 break;
1258
1259 case WAIT_OBJECT_0 + 1:
d71cc120 1260 cont = false;
a0b4c98b
VZ
1261 break;
1262
97247d36 1263 default:
9a83f860 1264 wxFAIL_MSG( wxT("unexpected return of WaitForMultipleObjects()") );
97247d36
VZ
1265 // fall through
1266
a0b4c98b 1267 case WAIT_FAILED:
97247d36
VZ
1268 // using wxLogLastError() from here is dangerous: we risk to
1269 // deadlock the main thread if wxLog sends output to GUI
1270 DWORD err = GetLastError();
141f4958
WS
1271 wxMessageOutputDebug dbg;
1272 dbg.Printf
97247d36
VZ
1273 (
1274 wxT("WaitForMultipleObjects(RasMonitor) failed: 0x%08lx (%s)"),
1275 err,
1276 wxSysErrorMsg(err)
1277 );
97247d36
VZ
1278
1279 // no sense in continuing, who knows if the handles we're
1280 // waiting for even exist yet...
1281 return (DWORD)-1;
a0b4c98b
VZ
1282 }
1283 }
1284
97247d36 1285 // we don't need it any more now and if this thread ran, it is our
070d6391 1286 // responsibility to free the data
97247d36
VZ
1287 delete data;
1288
a0b4c98b
VZ
1289 return 0;
1290}
1291
1292static LRESULT APIENTRY wxRasStatusWindowProc(HWND hWnd, UINT message,
1293 WPARAM wParam, LPARAM lParam)
1294{
cd6af1cb 1295 switch ( message )
a0b4c98b 1296 {
cd6af1cb
VZ
1297 case wxWM_RAS_STATUS_CHANGED:
1298 {
1299 wxRasThreadData *data = (wxRasThreadData *)lParam;
1300 data->dialUpManager->OnConnectStatusChange();
1301 }
1302 break;
2690830e 1303
cd6af1cb
VZ
1304 case wxWM_RAS_DIALING_PROGRESS:
1305 {
1306 wxDialUpManagerMSW *dialMan = wxDialUpManagerMSW::GetDialer();
1307
1308 dialMan->OnDialProgress((RASCONNSTATE)wParam, lParam);
1309 }
1310 break;
1311
1312 default:
1313 return ::DefWindowProc(hWnd, message, wParam, lParam);
2690830e 1314 }
a0b4c98b
VZ
1315
1316 return 0;
1317}
1318
2eb10e2a 1319static void WINAPI wxRasDialFunc(UINT WXUNUSED(unMsg),
a0b4c98b
VZ
1320 RASCONNSTATE rasconnstate,
1321 DWORD dwError)
1322{
1323 wxDialUpManagerMSW *dialUpManager = wxDialUpManagerMSW::GetDialer();
1324
223d09f6 1325 wxCHECK_RET( dialUpManager, wxT("who started to dial then?") );
a0b4c98b 1326
2a1f999f 1327 SendMessage(wxDialUpManagerMSW::GetRasWindow(), wxWM_RAS_DIALING_PROGRESS,
2690830e 1328 rasconnstate, dwError);
a0b4c98b
VZ
1329}
1330
1c25d245
VZ
1331#endif // __BORLANDC__
1332
a0b4c98b 1333#endif // wxUSE_DIALUP_MANAGER