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