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