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