Back to index

lightning-sunbird  0.9+nobinonly
nsAutodialWin.cpp
Go to the documentation of this file.
00001 /* ***** BEGIN LICENSE BLOCK *****
00002  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00003  *
00004  * The contents of this file are subject to the Mozilla Public License Version
00005  * 1.1 (the "License"); you may not use this file except in compliance with
00006  * the License. You may obtain a copy of the License at
00007  * http://www.mozilla.org/MPL/
00008  *
00009  * Software distributed under the License is distributed on an "AS IS" basis,
00010  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00011  * for the specific language governing rights and limitations under the
00012  * License.
00013  *
00014  * The Original Code is Mozilla.
00015  *
00016  * The Initial Developer of the Original Code is
00017  * Netscape Communications Corporation.
00018  * Portions created by the Initial Developer are Copyright (C) 2002
00019  * the Initial Developer. All Rights Reserved.
00020  *
00021  * Contributor(s):
00022  *   Steve Meredith <smeredith@netscape.com>
00023  *
00024  * Alternatively, the contents of this file may be used under the terms of
00025  * either the GNU General Public License Version 2 or later (the "GPL"), or
00026  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00027  * in which case the provisions of the GPL or the LGPL are applicable instead
00028  * of those above. If you wish to allow use of your version of this file only
00029  * under the terms of either the GPL or the LGPL, and not to allow others to
00030  * use your version of this file under the terms of the MPL, indicate your
00031  * decision by deleting the provisions above and replace them with the notice
00032  * and other provisions required by the GPL or the LGPL. If you do not delete
00033  * the provisions above, a recipient may use your version of this file under
00034  * the terms of any one of the MPL, the GPL or the LGPL.
00035  *
00036  * ***** END LICENSE BLOCK ***** */
00037 
00038 // This source is mostly a bunch of Windows API calls. It is only compiled for
00039 // Windows builds.
00040 //
00041 // Registry entries for Autodial mappings are located here:
00042 //  HKEY_CURRENT_USER\Software\Microsoft\RAS Autodial\Addresses
00043 
00044 #include <windows.h>
00045 #include <winsvc.h>
00046 #include "nsAutodialWin.h"
00047 #include "prlog.h"
00048 
00049 #ifdef WINCE
00050 #include <objbase.h>
00051 #include <initguid.h>
00052 #include <connmgr.h>
00053 #endif
00054 
00055 #ifdef WINCE
00056 #define AUTODIAL_DEFAULT AUTODIAL_ALWAYS
00057 #else
00058 #define AUTODIAL_DEFAULT AUTODIAL_NEVER
00059 #endif
00060 
00061 //
00062 // Log module for autodial logging...
00063 //
00064 // To enable logging (see prlog.h for full details):
00065 //
00066 //    set NSPR_LOG_MODULES=Autodial:5
00067 //    set NSPR_LOG_FILE=nspr.log
00068 //
00069 // this enables PR_LOG_DEBUG level information and places all output in
00070 // the file nspr.log
00071 //
00072 
00073 #ifdef PR_LOGGING
00074 static PRLogModuleInfo* gLog = nsnull;
00075 #endif
00076 
00077 #define LOGD(args) PR_LOG(gLog, PR_LOG_DEBUG, args)
00078 #define LOGE(args) PR_LOG(gLog, PR_LOG_ERROR, args)
00079 
00080 // Don't try to dial again within a few seconds of when user pressed cancel.
00081 #define NO_RETRY_PERIOD_SEC 5
00082 PRIntervalTime nsRASAutodial::mDontRetryUntil = 0;
00083 
00084 
00085 tRASPHONEBOOKDLG nsRASAutodial::mpRasPhonebookDlg = nsnull;
00086 tRASENUMCONNECTIONS nsRASAutodial::mpRasEnumConnections = nsnull;
00087 tRASENUMENTRIES nsRASAutodial::mpRasEnumEntries = nsnull;
00088 tRASDIALDLG nsRASAutodial::mpRasDialDlg = nsnull;
00089 tRASSETAUTODIALADDRESS nsRASAutodial::mpRasSetAutodialAddress = nsnull;
00090 tRASGETAUTODIALADDRESS nsRASAutodial::mpRasGetAutodialAddress = nsnull;
00091 tRASGETAUTODIALENABLE nsRASAutodial::mpRasGetAutodialEnable = nsnull;
00092 tRASGETAUTODIALPARAM nsRASAutodial::mpRasGetAutodialParam = nsnull;
00093 
00094 HINSTANCE nsRASAutodial::mhRASdlg = nsnull;
00095 HINSTANCE nsRASAutodial::mhRASapi32 = nsnull;
00096 
00097 // ctor. 
00098 nsRASAutodial::nsRASAutodial()
00099 :   mAutodialBehavior(AUTODIAL_DEFAULT),
00100     mNumRASConnectionEntries(0),
00101     mAutodialServiceDialingLocation(-1)
00102 {
00103     mOSVerInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
00104     GetVersionEx(&mOSVerInfo);
00105 
00106 #ifndef WINCE
00107     // We only need to dial on nt based systems. For all other platforms, 
00108     // mAutodialBehavior will remain AUTODIAL_NEVER, and we can skip
00109     // these initializations.
00110     if ((mOSVerInfo.dwPlatformId == VER_PLATFORM_WIN32_NT) 
00111      && (mOSVerInfo.dwMajorVersion >= 4))
00112 #endif
00113     {
00114         // Initializations that can be made again since RAS OS settings can 
00115         // change.
00116         Init();
00117     }
00118 }
00119 
00120 // dtor
00121 nsRASAutodial::~nsRASAutodial()
00122 {
00123 }
00124 
00125 
00126 // Get settings from the OS. These are settings that might change during
00127 // the OS session. Call Init() again to pick up those changes if required.
00128 // Returns NS_ERROR_FAILURE if error or NS_OK if success.
00129 nsresult nsRASAutodial::Init()
00130 {
00131 #ifdef PR_LOGGING
00132     if (!gLog)
00133         gLog = PR_NewLogModule("Autodial");
00134 #endif
00135 
00136     mDefaultEntryName[0] = '\0';
00137     mNumRASConnectionEntries = 0;
00138     mAutodialBehavior = QueryAutodialBehavior();
00139     
00140     // No need to continue in this case.
00141     if (mAutodialBehavior == AUTODIAL_NEVER)
00142     {
00143         return NS_OK;
00144     }
00145 
00146 
00147     // Get the number of dialup entries in the phonebook.
00148     mNumRASConnectionEntries = NumRASEntries();
00149     
00150     // Get the name of the default entry.
00151     nsresult result = GetDefaultEntryName(mDefaultEntryName, 
00152                                            RAS_MaxEntryName + 1);
00153     
00154     return result;
00155 }
00156 
00157 
00158 // Should we attempt to dial on a network error? Yes if the Internet Options
00159 // configured as such. Yes if the RAS autodial service is running (we'll try to
00160 // force it to dial in that case by adding the network address to its db.)
00161 PRBool nsRASAutodial::ShouldDialOnNetworkError()
00162 {
00163 #ifndef WINCE
00164     // Don't try to dial again within a few seconds of when user pressed cancel.
00165     if (mDontRetryUntil) 
00166     {
00167         PRIntervalTime intervalNow = PR_IntervalNow();
00168         if (intervalNow < mDontRetryUntil) 
00169         {
00170             LOGD(("Autodial: Not dialing: too soon."));
00171             return PR_FALSE;
00172         }
00173     }
00174      
00175 
00176     return ((mAutodialBehavior == AUTODIAL_ALWAYS) 
00177              || (mAutodialBehavior == AUTODIAL_ON_NETWORKERROR)
00178              || (mAutodialBehavior == AUTODIAL_USE_SERVICE));
00179 #else
00180     return PR_TRUE;
00181 #endif
00182 }
00183 
00184 
00185 // The autodial info is set in Control Panel | Internet Options | Connections.
00186 // The values are stored in the registry. This function gets those values from
00187 // the registry and determines if we should never dial, always dial, or dial
00188 // when there is no network found.
00189 int nsRASAutodial::QueryAutodialBehavior()
00190 {
00191 #ifndef WINCE
00192     if (IsAutodialServiceRunning())
00193     {
00194         if (!LoadRASapi32DLL())
00195             return AUTODIAL_NEVER;
00196 
00197         // Is Autodial service enabled for the current login session?
00198         DWORD disabled = 0;
00199         DWORD size = sizeof(DWORD);
00200         if ((*mpRasGetAutodialParam)(RASADP_LoginSessionDisable, &disabled, &size) == ERROR_SUCCESS)
00201         {
00202             if (!disabled)
00203             {
00204                 // If current dialing location has autodial on, we'll let the service dial.
00205                 mAutodialServiceDialingLocation = GetCurrentLocation();
00206                 if (IsAutodialServiceEnabled(mAutodialServiceDialingLocation))
00207                 {
00208                     return AUTODIAL_USE_SERVICE;
00209                 }
00210             }
00211         }
00212     }
00213 
00214     // If we get to here, then the service is not going to dial on error, so we
00215     // can dial ourselves if the control panel settings are set up that way.
00216     HKEY hKey = 0;
00217     LONG result = ::RegOpenKeyEx(
00218                     HKEY_CURRENT_USER, 
00219                     "Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings", 
00220                     0, 
00221                     KEY_READ, 
00222                     &hKey);
00223 
00224     if (result != ERROR_SUCCESS)
00225     {
00226         LOGE(("Autodial: Error opening reg key Internet Settings"));
00227         return AUTODIAL_NEVER;
00228     }
00229 
00230     DWORD entryType = 0;
00231     DWORD autodial = 0;
00232     DWORD onDemand = 0;
00233     DWORD paramSize = sizeof(DWORD);
00234 
00235     result = ::RegQueryValueEx(hKey, "EnableAutodial", nsnull, &entryType, (LPBYTE)&autodial, &paramSize);
00236     if (result != ERROR_SUCCESS)
00237     {
00238         ::RegCloseKey(hKey);
00239         LOGE(("Autodial: Error reading reg value EnableAutodial."));
00240         return AUTODIAL_NEVER;
00241     }
00242 
00243     result = ::RegQueryValueEx(hKey, "NoNetAutodial", nsnull, &entryType, (LPBYTE)&onDemand, &paramSize);
00244     if (result != ERROR_SUCCESS)
00245     {
00246         ::RegCloseKey(hKey);
00247         LOGE(("Autodial: Error reading reg value NoNetAutodial."));
00248         return AUTODIAL_NEVER;
00249     }
00250   
00251     ::RegCloseKey(hKey);
00252 
00253     if (!autodial)
00254     {
00255         return AUTODIAL_NEVER;
00256     }
00257     else 
00258     {
00259         if (onDemand)
00260         {
00261             return AUTODIAL_ON_NETWORKERROR;
00262         }
00263         else
00264         {
00265             return AUTODIAL_ALWAYS;
00266         }
00267     }
00268 #else
00269     return AUTODIAL_DEFAULT;
00270 #endif
00271 }
00272 
00273 
00274 #ifdef WINCE
00275 static nsresult DoPPCConnection()
00276 {
00277     static HANDLE    gConnectionHandle = NULL;
00278 
00279     // Make the connection to the new network
00280     CONNMGR_CONNECTIONINFO conn_info;
00281     memset(&conn_info, 0, sizeof(CONNMGR_CONNECTIONINFO));
00282 
00283     conn_info.cbSize      = sizeof(CONNMGR_CONNECTIONINFO);
00284     conn_info.dwParams    = CONNMGR_PARAM_GUIDDESTNET;
00285     conn_info.dwPriority  = CONNMGR_PRIORITY_USERINTERACTIVE;
00286     conn_info.guidDestNet = IID_DestNetInternet;
00287     conn_info.bExclusive  = FALSE;
00288     conn_info.bDisabled   = FALSE;
00289 
00290     HANDLE tempConnectionHandle;
00291     DWORD status;
00292     HRESULT result = ConnMgrEstablishConnectionSync(&conn_info, 
00293                                                     &tempConnectionHandle, 
00294                                                     60000,
00295                                                     &status);
00296 
00297     if (result != S_OK)
00298     {
00299       return NS_ERROR_FAILURE;
00300     }
00301 
00302     if (status != CONNMGR_STATUS_CONNECTED)
00303     {
00304       // could not connect to this network.  release the
00305       // temp connection.
00306       ConnMgrReleaseConnection(tempConnectionHandle, 0);
00307       return NS_ERROR_FAILURE;
00308     }
00309 
00310     // At this point, we have a new connection, so release
00311     // the old connection
00312     if (gConnectionHandle)
00313       ConnMgrReleaseConnection(gConnectionHandle, 0);
00314       
00315     gConnectionHandle = tempConnectionHandle;
00316     return NS_OK;
00317 }
00318 
00319 #endif
00320 
00321 // If the RAS autodial service is running, use it. Otherwise, dial
00322 // the default RAS connection. There are two possible RAS dialogs:
00323 // one that dials a single entry, and one that lets the user choose which
00324 // to dial. If there is only one connection entry in the phone book, or
00325 // there are multiple entries but one is defined as the default, we'll use
00326 // the single entry dial dialog. If there are multiple connection entries,
00327 // and none is specified as default, we'll bring up the diallog which lets
00328 // the user select the connection entry to use.
00329 //
00330 // Return values:
00331 //  NS_OK: dialing was successful and caller should retry
00332 //  all other values indicate that the caller should not retry
00333 nsresult nsRASAutodial::DialDefault(const char* hostName)
00334 {
00335 #ifndef WINCE
00336     mDontRetryUntil = 0;
00337 
00338     if (mAutodialBehavior == AUTODIAL_NEVER)
00339     {
00340         return NS_ERROR_FAILURE;    // don't retry the network error
00341     }
00342 
00343     // If already a RAS connection, bail.
00344     if (IsRASConnected())
00345     {
00346         LOGD(("Autodial: Not dialing: active connection."));
00347         return NS_ERROR_FAILURE;    // don't retry
00348     }
00349 
00350     // If no dialup connections configured, bail.
00351     if (mNumRASConnectionEntries <= 0)
00352     {
00353         LOGD(("Autodial: Not dialing: no entries."));
00354         return NS_ERROR_FAILURE;    // don't retry
00355     }
00356 
00357 
00358     // If autodial service is running, let it dial. In order for it to dial more
00359     // reliably, we have to add the target address to the autodial database.
00360     // This is the only way the autodial service dial if there is a network
00361     // adapter installed. But even then it might not dial. We have to assume that
00362     // it will though, or we could end up with two attempts to dial on the same
00363     // network error if the user cancels the first one: one from the service and
00364     // one from us.
00365     // See http://msdn.microsoft.com/library/default.asp?url=/library/en-us/rras/ras4over_3dwl.asp
00366     if (mAutodialBehavior == AUTODIAL_USE_SERVICE)
00367     {
00368         AddAddressToAutodialDirectory(hostName);
00369         return NS_ERROR_FAILURE;    // don't retry
00370     }
00371 
00372     // Do the dialing ourselves.
00373     else
00374     {
00375         // Don't need to load the dll before this.
00376         if (!LoadRASdlgDLL())
00377             return NS_ERROR_NULL_POINTER;
00378 
00379         // If a default dial entry is configured, use it.
00380         if (mDefaultEntryName[0] != '\0') 
00381         {
00382             LOGD(("Autodial: Dialing default: %s.",mDefaultEntryName));
00383 
00384             RASDIALDLG rasDialDlg;
00385             memset(&rasDialDlg, 0, sizeof(RASDIALDLG));
00386             rasDialDlg.dwSize = sizeof(RASDIALDLG);
00387 
00388             PRBool dialed = 
00389              (*mpRasDialDlg)(nsnull, mDefaultEntryName, nsnull, &rasDialDlg);
00390 
00391             if (!dialed)
00392             {
00393                 if (rasDialDlg.dwError != 0)
00394                 {
00395                     LOGE(("Autodial ::RasDialDlg failed: Error: %d.", 
00396                      rasDialDlg.dwError));
00397                 }
00398                 else
00399                 {
00400                     mDontRetryUntil = PR_IntervalNow() + PR_SecondsToInterval(NO_RETRY_PERIOD_SEC);
00401                     LOGD(("Autodial: User cancelled dial."));
00402                 }
00403                 return NS_ERROR_FAILURE;    // don't retry
00404             }
00405 
00406             LOGD(("Autodial: RAS dialup connection successful."));
00407         }
00408 
00409         // If no default connection specified, open the dialup dialog that lets
00410         // the user specifiy which connection to dial.
00411         else
00412         {
00413             LOGD(("Autodial: Prompting for phonebook entry."));
00414 
00415             RASPBDLG rasPBDlg;
00416             memset(&rasPBDlg, 0, sizeof(RASPBDLG));
00417             rasPBDlg.dwSize = sizeof(RASPBDLG);
00418  
00419             PRBool dialed = (*mpRasPhonebookDlg)(nsnull, nsnull, &rasPBDlg);
00420 
00421             if (!dialed)
00422             {
00423                 if (rasPBDlg.dwError != 0)
00424                 {
00425                     LOGE(("Autodial: ::RasPhonebookDlg failed: Error = %d.", 
00426                      rasPBDlg.dwError));
00427                 }
00428                 else
00429                 {
00430                     mDontRetryUntil = PR_IntervalNow() + PR_SecondsToInterval(NO_RETRY_PERIOD_SEC);
00431                     LOGD(("Autodial: User cancelled dial."));
00432                 }
00433 
00434                 return NS_ERROR_FAILURE;    // don't retry
00435             }
00436 
00437             LOGD(("Autodial: RAS dialup connection successful."));
00438         }
00439     }
00440 
00441     // Retry because we just established a dialup connection.
00442     return NS_OK;
00443 
00444 #else
00445     return  DoPPCConnection();
00446 #endif
00447 }
00448 
00449 
00450 // Check to see if RAS is already connected.
00451 PRBool nsRASAutodial::IsRASConnected()
00452 {
00453     DWORD connections;
00454     RASCONN rasConn;
00455     rasConn.dwSize = sizeof(RASCONN);
00456     DWORD structSize = sizeof(RASCONN);
00457 
00458     if (!LoadRASapi32DLL())
00459         return NS_ERROR_NULL_POINTER;
00460 
00461     DWORD result = (*mpRasEnumConnections)(&rasConn, &structSize, &connections);
00462 
00463     // ERROR_BUFFER_TOO_SMALL is OK because we only need one struct.
00464     if (result == ERROR_SUCCESS || result == ERROR_BUFFER_TOO_SMALL)
00465     {
00466         return (connections > 0);
00467     }
00468 
00469     LOGE(("Autodial: ::RasEnumConnections failed: Error = %d", result));
00470     return PR_FALSE;
00471 }
00472 
00473 // Get the first RAS dial entry name from the phonebook.
00474 nsresult nsRASAutodial::GetFirstEntryName(char* entryName, int bufferSize)
00475 {
00476     // Need to load the DLL if not loaded yet.
00477     if (!LoadRASapi32DLL())
00478         return NS_ERROR_NULL_POINTER;
00479 
00480     RASENTRYNAME rasEntryName;
00481     rasEntryName.dwSize = sizeof(RASENTRYNAME);
00482     DWORD cb = sizeof(RASENTRYNAME);
00483     DWORD cEntries = 0;
00484 
00485     DWORD result = 
00486      (*mpRasEnumEntries)(nsnull, nsnull, &rasEntryName, &cb, &cEntries);
00487 
00488     // ERROR_BUFFER_TOO_SMALL is OK because we only need one struct.
00489     if (result == ERROR_SUCCESS || result == ERROR_BUFFER_TOO_SMALL)
00490     {
00491 #ifndef WINCE
00492         strncpy(entryName, rasEntryName.szEntryName, bufferSize);
00493 #endif
00494         return NS_OK;
00495     }
00496 
00497     return NS_ERROR_FAILURE;
00498 }
00499 
00500 // Get the number of RAS dial entries in the phonebook.
00501 int nsRASAutodial::NumRASEntries()
00502 {
00503     // Need to load the DLL if not loaded yet.
00504     if (!LoadRASapi32DLL())
00505         return 0;
00506 
00507     RASENTRYNAME rasEntryName;
00508     rasEntryName.dwSize = sizeof(RASENTRYNAME);
00509     DWORD cb = sizeof(RASENTRYNAME);
00510     DWORD cEntries = 0;
00511 
00512 
00513     DWORD result = 
00514      (*mpRasEnumEntries)(nsnull, nsnull, &rasEntryName, &cb, &cEntries);
00515 
00516     // ERROR_BUFFER_TOO_SMALL is OK because we only need one struct.
00517     if (result == ERROR_SUCCESS || result == ERROR_BUFFER_TOO_SMALL)
00518     {
00519         return (int)cEntries;
00520     }
00521 
00522     return 0;
00523 }
00524 
00525 // Get the name of the default dial entry.
00526 nsresult nsRASAutodial::GetDefaultEntryName(char* entryName, int bufferSize)
00527 {
00528     // No RAS dialup entries. 
00529     if (mNumRASConnectionEntries <= 0)
00530     {
00531         return NS_ERROR_FAILURE;
00532     }
00533 
00534     // Single RAS dialup entry. Use it as the default to autodial.
00535     if (mNumRASConnectionEntries == 1)
00536     {
00537         return GetFirstEntryName(entryName, bufferSize);
00538     }
00539 
00540     // Multiple RAS dialup entries. If a default configured in the registry,
00541     // use it. 
00542     //
00543     // For Windows XP: HKCU/Software/Microsoft/RAS Autodial/Default/DefaultInternet.
00544     //              or HKLM/Software/Microsoft/RAS Autodial/Default/DefaultInternet.
00545     // For Windows 2K: HKCU/RemoteAccess/InternetProfile.
00546 
00547     char* key = nsnull;
00548     char* val = nsnull;
00549 
00550     HKEY hKey = 0;
00551     LONG result = 0;
00552 
00553     // Windows NT and 2000
00554     if ((mOSVerInfo.dwMajorVersion == 4) // Windows NT
00555      || ((mOSVerInfo.dwMajorVersion == 5) && (mOSVerInfo.dwMinorVersion == 0))) // Windows 2000
00556     {
00557         key = "RemoteAccess";
00558         val = "InternetProfile";
00559 
00560         result = ::RegOpenKeyEx(
00561                     HKEY_CURRENT_USER, 
00562                     key, 
00563                     0, 
00564                     KEY_READ, 
00565                     &hKey);
00566 
00567         if (result != ERROR_SUCCESS)
00568         {
00569             return NS_ERROR_FAILURE;
00570         }
00571     }
00572     else  // Windows XP
00573     {
00574         key = "Software\\Microsoft\\RAS Autodial\\Default";
00575         val = "DefaultInternet";
00576 
00577         
00578         // Try HKCU first.
00579         result = ::RegOpenKeyEx(
00580                     HKEY_CURRENT_USER, 
00581                     key, 
00582                     0, 
00583                     KEY_READ, 
00584                     &hKey);
00585 
00586         if (result != ERROR_SUCCESS)
00587         {
00588             // If not present, try HKLM.
00589             result = ::RegOpenKeyEx(
00590                         HKEY_LOCAL_MACHINE, 
00591                         key, 
00592                         0, 
00593                         KEY_READ, 
00594                         &hKey);
00595 
00596             if (result != ERROR_SUCCESS)
00597             {
00598                 return NS_ERROR_FAILURE;
00599             }
00600         }
00601     }
00602 
00603 
00604     DWORD entryType = 0;
00605     DWORD buffSize = bufferSize;
00606 
00607     result = ::RegQueryValueEx(hKey, 
00608                                 val, 
00609                                 nsnull, 
00610                                 &entryType, 
00611                                 (LPBYTE)entryName, 
00612                                 &buffSize);
00613 
00614     ::RegCloseKey(hKey);
00615 
00616 
00617     if (result != ERROR_SUCCESS)
00618     {
00619         // Results in a prompt for which to use at dial time.
00620         return NS_ERROR_FAILURE;
00621     }
00622 
00623     return NS_OK;
00624 }
00625 
00626 
00627 // Determine if the autodial service is running on this PC.
00628 PRBool nsRASAutodial::IsAutodialServiceRunning()
00629 {
00630 #ifndef WINCE
00631     SC_HANDLE hSCManager = 
00632       OpenSCManager(nsnull, SERVICES_ACTIVE_DATABASE, SERVICE_QUERY_STATUS);
00633 
00634     if (hSCManager == nsnull)
00635     {
00636         LOGE(("Autodial: failed to open service control manager. Error %d.", 
00637           ::GetLastError()));
00638 
00639         return PR_FALSE;
00640     }
00641 
00642     SC_HANDLE hService = 
00643       OpenService(hSCManager, "RasAuto", SERVICE_QUERY_STATUS);
00644 
00645     if (hSCManager == nsnull)
00646     {
00647         LOGE(("Autodial: failed to open RasAuto service."));
00648         return PR_FALSE;
00649     }
00650 
00651     SERVICE_STATUS status;
00652     if (!QueryServiceStatus(hService, &status))
00653     {
00654         LOGE(("Autodial: ::QueryServiceStatus() failed. Error: %d", 
00655           ::GetLastError()));
00656 
00657         return PR_FALSE;
00658     }
00659 
00660     return (status.dwCurrentState == SERVICE_RUNNING);
00661 #else
00662     return PR_TRUE;
00663 #endif
00664 }
00665 
00666 // Add the specified address to the autodial directory.
00667 PRBool nsRASAutodial::AddAddressToAutodialDirectory(const char* hostName)
00668 {
00669     // Need to load the DLL if not loaded yet.
00670     if (!LoadRASapi32DLL())
00671         return PR_FALSE;
00672 
00673     // First see if there is already a db entry for this address. 
00674     RASAUTODIALENTRY autodialEntry;
00675     autodialEntry.dwSize = sizeof(RASAUTODIALENTRY);
00676     DWORD size = sizeof(RASAUTODIALENTRY);
00677     DWORD entries = 0;
00678 
00679     DWORD result = (*mpRasGetAutodialAddress)(hostName, 
00680                                     nsnull, 
00681                                     &autodialEntry, 
00682                                     &size, 
00683                                     &entries);
00684 
00685     // If there is already at least 1 entry in db for this address, return.
00686     if (result != ERROR_FILE_NOT_FOUND)
00687     {
00688         LOGD(("Autodial: Address %s already in autodial db.", hostName));
00689         return PR_FALSE;
00690     }
00691 
00692     autodialEntry.dwSize = sizeof(RASAUTODIALENTRY);
00693     autodialEntry.dwFlags = 0;
00694     autodialEntry.dwDialingLocation = mAutodialServiceDialingLocation;
00695     GetDefaultEntryName(autodialEntry.szEntry, RAS_MaxEntryName);
00696 
00697     result = (*mpRasSetAutodialAddress)(hostName, 
00698                                     0, 
00699                                     &autodialEntry, 
00700                                     sizeof(RASAUTODIALENTRY), 
00701                                     1);
00702 
00703     if (result != ERROR_SUCCESS)
00704     {
00705         LOGE(("Autodial ::RasSetAutodialAddress failed result %d.", result));
00706         return PR_FALSE;
00707     }
00708 
00709     LOGD(("Autodial: Added address %s to RAS autodial db for entry %s.",
00710      hostName, autodialEntry.szEntry));
00711 
00712     return PR_TRUE;
00713 }
00714 
00715 // Get the current TAPI dialing location.
00716 int nsRASAutodial::GetCurrentLocation()
00717 {
00718     HKEY hKey = 0;
00719     LONG result = ::RegOpenKeyEx(
00720                     HKEY_LOCAL_MACHINE, 
00721                     "Software\\Microsoft\\Windows\\CurrentVersion\\Telephony\\Locations", 
00722                     0, 
00723                     KEY_READ, 
00724                     &hKey);
00725 
00726     if (result != ERROR_SUCCESS)
00727     {
00728         LOGE(("Autodial: Error opening reg key ...CurrentVersion\\Telephony\\Locations"));
00729         return -1;
00730     }
00731 
00732     DWORD entryType = 0;
00733     DWORD location = 0;
00734     DWORD paramSize = sizeof(DWORD);
00735 
00736     result = ::RegQueryValueEx(hKey, "CurrentID", nsnull, &entryType, (LPBYTE)&location, &paramSize);
00737     if (result != ERROR_SUCCESS)
00738     {
00739         ::RegCloseKey(hKey);
00740         LOGE(("Autodial: Error reading reg value CurrentID."));
00741         return -1;
00742     }
00743 
00744     ::RegCloseKey(hKey);
00745     return location;
00746 
00747 }
00748 
00749 // Check to see if autodial for the specified location is enabled. 
00750 PRBool nsRASAutodial::IsAutodialServiceEnabled(int location)
00751 {
00752     if (location < 0)
00753         return PR_FALSE;
00754 
00755     if (!LoadRASapi32DLL())
00756         return PR_FALSE;
00757 
00758     PRBool enabled;
00759     if ((*mpRasGetAutodialEnable)(location, &enabled) != ERROR_SUCCESS)
00760     {
00761         LOGE(("Autodial: Error calling RasGetAutodialEnable()"));
00762         return PR_FALSE;
00763     }
00764 
00765     return enabled;
00766 }
00767 
00768 
00769 
00770 PRBool nsRASAutodial::LoadRASapi32DLL()
00771 {
00772     if (!mhRASapi32)
00773     {
00774         mhRASapi32 = ::LoadLibrary("rasapi32.dll");
00775         if ((UINT)mhRASapi32 > 32)
00776         {
00777             // RasEnumConnections
00778             mpRasEnumConnections = (tRASENUMCONNECTIONS)
00779              ::GetProcAddress(mhRASapi32, "RasEnumConnectionsA");
00780 
00781             // RasEnumEntries
00782             mpRasEnumEntries = (tRASENUMENTRIES)
00783              ::GetProcAddress(mhRASapi32, "RasEnumEntriesA");
00784 
00785             // RasSetAutodialAddress
00786             mpRasSetAutodialAddress = (tRASSETAUTODIALADDRESS)
00787                 ::GetProcAddress(mhRASapi32, "RasSetAutodialAddressA");
00788 
00789             // RasGetAutodialAddress
00790             mpRasGetAutodialAddress = (tRASGETAUTODIALADDRESS)
00791              ::GetProcAddress(mhRASapi32, "RasGetAutodialAddressA");
00792 
00793             // RasGetAutodialEnable
00794             mpRasGetAutodialEnable = (tRASGETAUTODIALENABLE)
00795              ::GetProcAddress(mhRASapi32, "RasGetAutodialEnableA");
00796 
00797             // RasGetAutodialParam
00798             mpRasGetAutodialParam = (tRASGETAUTODIALPARAM)
00799              ::GetProcAddress(mhRASapi32, "RasGetAutodialParamA");
00800         }
00801 
00802     }
00803 
00804     if (!mhRASapi32 
00805         || !mpRasEnumConnections 
00806         || !mpRasEnumEntries 
00807         || !mpRasSetAutodialAddress
00808         || !mpRasGetAutodialAddress
00809         || !mpRasGetAutodialEnable
00810         || !mpRasGetAutodialParam)
00811     {
00812         LOGE(("Autodial: Error loading RASAPI32.DLL."));
00813         return PR_FALSE;
00814     }
00815 
00816     return PR_TRUE;
00817 }
00818 
00819 PRBool nsRASAutodial::LoadRASdlgDLL()
00820 {
00821     if (!mhRASdlg)
00822     {
00823         mhRASdlg = ::LoadLibrary("rasdlg.dll");
00824         if ((UINT)mhRASdlg > 32)
00825         {
00826             // RasPhonebookDlg
00827             mpRasPhonebookDlg =
00828              (tRASPHONEBOOKDLG)::GetProcAddress(mhRASdlg, "RasPhonebookDlgA");
00829 
00830             // RasDialDlg
00831             mpRasDialDlg =
00832              (tRASDIALDLG)::GetProcAddress(mhRASdlg, "RasDialDlgA");
00833 
00834         }
00835     }
00836 
00837     if (!mhRASdlg || !mpRasPhonebookDlg || !mpRasDialDlg)
00838     {
00839         LOGE(("Autodial: Error loading RASDLG.DLL."));
00840         return PR_FALSE;
00841     }
00842 
00843     return PR_TRUE;
00844 }
00845