Merge mozilla-central and tracemonkey. (a=blockers)
[mozilla-central.git] / netwerk / base / src / nsAutodialWin.cpp
blob3504fdfa6cccbf9ec50873fe1fb23c16e62c150a
1 /* ***** BEGIN LICENSE BLOCK *****
2 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
4 * The contents of this file are subject to the Mozilla Public License Version
5 * 1.1 (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 * http://www.mozilla.org/MPL/
9 * Software distributed under the License is distributed on an "AS IS" basis,
10 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
11 * for the specific language governing rights and limitations under the
12 * License.
14 * The Original Code is Mozilla.
16 * The Initial Developer of the Original Code is
17 * Netscape Communications Corporation.
18 * Portions created by the Initial Developer are Copyright (C) 2002
19 * the Initial Developer. All Rights Reserved.
21 * Contributor(s):
22 * Steve Meredith <smeredith@netscape.com>
24 * Alternatively, the contents of this file may be used under the terms of
25 * either the GNU General Public License Version 2 or later (the "GPL"), or
26 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
27 * in which case the provisions of the GPL or the LGPL are applicable instead
28 * of those above. If you wish to allow use of your version of this file only
29 * under the terms of either the GPL or the LGPL, and not to allow others to
30 * use your version of this file under the terms of the MPL, indicate your
31 * decision by deleting the provisions above and replace them with the notice
32 * and other provisions required by the GPL or the LGPL. If you do not delete
33 * the provisions above, a recipient may use your version of this file under
34 * the terms of any one of the MPL, the GPL or the LGPL.
36 * ***** END LICENSE BLOCK ***** */
38 // This source is mostly a bunch of Windows API calls. It is only compiled for
39 // Windows builds.
41 // Registry entries for Autodial mappings are located here:
42 // HKEY_CURRENT_USER\Software\Microsoft\RAS Autodial\Addresses
44 #include <windows.h>
45 #include <winsvc.h>
46 #include "nsString.h"
47 #include "nsAutodialWin.h"
48 #include "prlog.h"
50 #define AUTODIAL_DEFAULT AUTODIAL_NEVER
53 // Log module for autodial logging...
55 // To enable logging (see prlog.h for full details):
57 // set NSPR_LOG_MODULES=Autodial:5
58 // set NSPR_LOG_FILE=nspr.log
60 // this enables PR_LOG_DEBUG level information and places all output in
61 // the file nspr.log
64 #ifdef PR_LOGGING
65 static PRLogModuleInfo* gLog = nsnull;
66 #endif
68 #define LOGD(args) PR_LOG(gLog, PR_LOG_DEBUG, args)
69 #define LOGE(args) PR_LOG(gLog, PR_LOG_ERROR, args)
71 // Don't try to dial again within a few seconds of when user pressed cancel.
72 #define NO_RETRY_PERIOD_SEC 5
73 PRIntervalTime nsAutodial::mDontRetryUntil = 0;
76 tRASPHONEBOOKDLG nsAutodial::mpRasPhonebookDlg = nsnull;
77 tRASENUMCONNECTIONS nsAutodial::mpRasEnumConnections = nsnull;
78 tRASENUMENTRIES nsAutodial::mpRasEnumEntries = nsnull;
79 tRASDIALDLG nsAutodial::mpRasDialDlg = nsnull;
80 tRASSETAUTODIALADDRESS nsAutodial::mpRasSetAutodialAddress = nsnull;
81 tRASGETAUTODIALADDRESS nsAutodial::mpRasGetAutodialAddress = nsnull;
82 tRASGETAUTODIALENABLE nsAutodial::mpRasGetAutodialEnable = nsnull;
83 tRASGETAUTODIALPARAM nsAutodial::mpRasGetAutodialParam = nsnull;
85 HINSTANCE nsAutodial::mhRASdlg = nsnull;
86 HINSTANCE nsAutodial::mhRASapi32 = nsnull;
88 // ctor.
89 nsAutodial::nsAutodial()
90 : mAutodialBehavior(AUTODIAL_DEFAULT),
91 mNumRASConnectionEntries(0),
92 mAutodialServiceDialingLocation(-1)
94 mOSVerInfo.dwOSVersionInfoSize = sizeof(mOSVerInfo);
95 GetVersionEx(&mOSVerInfo);
97 // Initializations that can be made again since RAS OS settings can
98 // change.
99 Init();
102 // dtor
103 nsAutodial::~nsAutodial()
108 // Get settings from the OS. These are settings that might change during
109 // the OS session. Call Init() again to pick up those changes if required.
110 // Returns NS_ERROR_FAILURE if error or NS_OK if success.
111 nsresult nsAutodial::Init()
113 #ifdef PR_LOGGING
114 if (!gLog)
115 gLog = PR_NewLogModule("Autodial");
116 #endif
118 mDefaultEntryName[0] = '\0';
119 mNumRASConnectionEntries = 0;
120 mAutodialBehavior = QueryAutodialBehavior();
122 // No need to continue in this case.
123 if (mAutodialBehavior == AUTODIAL_NEVER)
125 return NS_OK;
129 // Get the number of dialup entries in the phonebook.
130 mNumRASConnectionEntries = NumRASEntries();
132 // Get the name of the default entry.
133 nsresult result = GetDefaultEntryName(mDefaultEntryName,
134 sizeof(mDefaultEntryName));
136 return result;
140 // Should we attempt to dial on a network error? Yes if the Internet Options
141 // configured as such. Yes if the RAS autodial service is running (we'll try to
142 // force it to dial in that case by adding the network address to its db.)
143 PRBool nsAutodial::ShouldDialOnNetworkError()
145 // Don't try to dial again within a few seconds of when user pressed cancel.
146 if (mDontRetryUntil)
148 PRIntervalTime intervalNow = PR_IntervalNow();
149 if (intervalNow < mDontRetryUntil)
151 LOGD(("Autodial: Not dialing: too soon."));
152 return PR_FALSE;
157 return ((mAutodialBehavior == AUTODIAL_ALWAYS)
158 || (mAutodialBehavior == AUTODIAL_ON_NETWORKERROR)
159 || (mAutodialBehavior == AUTODIAL_USE_SERVICE));
163 // The autodial info is set in Control Panel | Internet Options | Connections.
164 // The values are stored in the registry. This function gets those values from
165 // the registry and determines if we should never dial, always dial, or dial
166 // when there is no network found.
167 int nsAutodial::QueryAutodialBehavior()
169 if (IsAutodialServiceRunning())
171 if (!LoadRASapi32DLL())
172 return AUTODIAL_NEVER;
174 // Is Autodial service enabled for the current login session?
175 DWORD disabled = 0;
176 DWORD size = sizeof(DWORD);
177 if ((*mpRasGetAutodialParam)(RASADP_LoginSessionDisable, &disabled, &size) == ERROR_SUCCESS)
179 if (!disabled)
181 // If current dialing location has autodial on, we'll let the service dial.
182 mAutodialServiceDialingLocation = GetCurrentLocation();
183 if (IsAutodialServiceEnabled(mAutodialServiceDialingLocation))
185 return AUTODIAL_USE_SERVICE;
191 // If we get to here, then the service is not going to dial on error, so we
192 // can dial ourselves if the control panel settings are set up that way.
193 HKEY hKey = 0;
194 LONG result = ::RegOpenKeyExW(
195 HKEY_CURRENT_USER,
196 L"Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings",
198 KEY_READ,
199 &hKey);
201 if (result != ERROR_SUCCESS)
203 LOGE(("Autodial: Error opening reg key Internet Settings"));
204 return AUTODIAL_NEVER;
207 DWORD entryType = 0;
208 DWORD autodial = 0;
209 DWORD onDemand = 0;
210 DWORD paramSize = sizeof(DWORD);
212 result = ::RegQueryValueExW(hKey, L"EnableAutodial", nsnull, &entryType, (LPBYTE)&autodial, &paramSize);
213 if (result != ERROR_SUCCESS)
215 ::RegCloseKey(hKey);
216 LOGE(("Autodial: Error reading reg value EnableAutodial."));
217 return AUTODIAL_NEVER;
220 result = ::RegQueryValueExW(hKey, L"NoNetAutodial", nsnull, &entryType, (LPBYTE)&onDemand, &paramSize);
221 if (result != ERROR_SUCCESS)
223 ::RegCloseKey(hKey);
224 LOGE(("Autodial: Error reading reg value NoNetAutodial."));
225 return AUTODIAL_NEVER;
228 ::RegCloseKey(hKey);
230 if (!autodial)
232 return AUTODIAL_NEVER;
234 else
236 if (onDemand)
238 return AUTODIAL_ON_NETWORKERROR;
240 else
242 return AUTODIAL_ALWAYS;
247 // If the RAS autodial service is running, use it. Otherwise, dial
248 // the default RAS connection. There are two possible RAS dialogs:
249 // one that dials a single entry, and one that lets the user choose which
250 // to dial. If there is only one connection entry in the phone book, or
251 // there are multiple entries but one is defined as the default, we'll use
252 // the single entry dial dialog. If there are multiple connection entries,
253 // and none is specified as default, we'll bring up the diallog which lets
254 // the user select the connection entry to use.
256 // Return values:
257 // NS_OK: dialing was successful and caller should retry
258 // all other values indicate that the caller should not retry
259 nsresult nsAutodial::DialDefault(const PRUnichar* hostName)
261 mDontRetryUntil = 0;
263 if (mAutodialBehavior == AUTODIAL_NEVER)
265 return NS_ERROR_FAILURE; // don't retry the network error
268 // If already a RAS connection, bail.
269 if (IsRASConnected())
271 LOGD(("Autodial: Not dialing: active connection."));
272 return NS_ERROR_FAILURE; // don't retry
275 // If no dialup connections configured, bail.
276 if (mNumRASConnectionEntries <= 0)
278 LOGD(("Autodial: Not dialing: no entries."));
279 return NS_ERROR_FAILURE; // don't retry
283 // If autodial service is running, let it dial. In order for it to dial more
284 // reliably, we have to add the target address to the autodial database.
285 // This is the only way the autodial service dial if there is a network
286 // adapter installed. But even then it might not dial. We have to assume that
287 // it will though, or we could end up with two attempts to dial on the same
288 // network error if the user cancels the first one: one from the service and
289 // one from us.
290 // See http://msdn.microsoft.com/library/default.asp?url=/library/en-us/rras/ras4over_3dwl.asp
291 if (mAutodialBehavior == AUTODIAL_USE_SERVICE)
293 AddAddressToAutodialDirectory(hostName);
294 return NS_ERROR_FAILURE; // don't retry
297 // Do the dialing ourselves.
298 else
300 // Don't need to load the dll before this.
301 if (!LoadRASdlgDLL())
302 return NS_ERROR_NULL_POINTER;
304 // If a default dial entry is configured, use it.
305 if (mDefaultEntryName[0] != '\0')
307 LOGD(("Autodial: Dialing default: %s.",mDefaultEntryName));
309 RASDIALDLG rasDialDlg;
310 memset(&rasDialDlg, 0, sizeof(rasDialDlg));
311 rasDialDlg.dwSize = sizeof(rasDialDlg);
313 PRBool dialed =
314 (*mpRasDialDlg)(nsnull, mDefaultEntryName, nsnull, &rasDialDlg);
316 if (!dialed)
318 if (rasDialDlg.dwError != 0)
320 LOGE(("Autodial ::RasDialDlg failed: Error: %d.",
321 rasDialDlg.dwError));
323 else
325 mDontRetryUntil = PR_IntervalNow() + PR_SecondsToInterval(NO_RETRY_PERIOD_SEC);
326 LOGD(("Autodial: User cancelled dial."));
328 return NS_ERROR_FAILURE; // don't retry
331 LOGD(("Autodial: RAS dialup connection successful."));
334 // If no default connection specified, open the dialup dialog that lets
335 // the user specifiy which connection to dial.
336 else
338 LOGD(("Autodial: Prompting for phonebook entry."));
340 RASPBDLG rasPBDlg;
341 memset(&rasPBDlg, 0, sizeof(rasPBDlg));
342 rasPBDlg.dwSize = sizeof(rasPBDlg);
344 PRBool dialed = (*mpRasPhonebookDlg)(nsnull, nsnull, &rasPBDlg);
346 if (!dialed)
348 if (rasPBDlg.dwError != 0)
350 LOGE(("Autodial: ::RasPhonebookDlg failed: Error = %d.",
351 rasPBDlg.dwError));
353 else
355 mDontRetryUntil = PR_IntervalNow() + PR_SecondsToInterval(NO_RETRY_PERIOD_SEC);
356 LOGD(("Autodial: User cancelled dial."));
359 return NS_ERROR_FAILURE; // don't retry
362 LOGD(("Autodial: RAS dialup connection successful."));
366 // Retry because we just established a dialup connection.
367 return NS_OK;
371 // Check to see if RAS is already connected.
372 PRBool nsAutodial::IsRASConnected()
374 DWORD connections;
375 RASCONN rasConn;
376 rasConn.dwSize = sizeof(rasConn);
377 DWORD structSize = sizeof(rasConn);
379 if (!LoadRASapi32DLL())
380 return NS_ERROR_NULL_POINTER;
382 DWORD result = (*mpRasEnumConnections)(&rasConn, &structSize, &connections);
384 // ERROR_BUFFER_TOO_SMALL is OK because we only need one struct.
385 if (result == ERROR_SUCCESS || result == ERROR_BUFFER_TOO_SMALL)
387 return (connections > 0);
390 LOGE(("Autodial: ::RasEnumConnections failed: Error = %d", result));
391 return PR_FALSE;
394 // Get the first RAS dial entry name from the phonebook.
395 nsresult nsAutodial::GetFirstEntryName(PRUnichar* entryName, int bufferSize)
397 // Need to load the DLL if not loaded yet.
398 if (!LoadRASapi32DLL())
399 return NS_ERROR_NULL_POINTER;
401 RASENTRYNAMEW rasEntryName;
402 rasEntryName.dwSize = sizeof(rasEntryName);
403 DWORD cb = sizeof(rasEntryName);
404 DWORD cEntries = 0;
406 DWORD result =
407 (*mpRasEnumEntries)(nsnull, nsnull, &rasEntryName, &cb, &cEntries);
409 // ERROR_BUFFER_TOO_SMALL is OK because we only need one struct.
410 if (result == ERROR_SUCCESS || result == ERROR_BUFFER_TOO_SMALL)
412 wcsncpy(entryName, rasEntryName.szEntryName,
413 bufferSize / sizeof(*entryName));
414 return NS_OK;
417 return NS_ERROR_FAILURE;
420 // Get the number of RAS dial entries in the phonebook.
421 int nsAutodial::NumRASEntries()
423 // Need to load the DLL if not loaded yet.
424 if (!LoadRASapi32DLL())
425 return 0;
427 RASENTRYNAMEW rasEntryName;
428 rasEntryName.dwSize = sizeof(rasEntryName);
429 DWORD cb = sizeof(rasEntryName);
430 DWORD cEntries = 0;
433 DWORD result =
434 (*mpRasEnumEntries)(nsnull, nsnull, &rasEntryName, &cb, &cEntries);
436 // ERROR_BUFFER_TOO_SMALL is OK because we only need one struct.
437 if (result == ERROR_SUCCESS || result == ERROR_BUFFER_TOO_SMALL)
439 return (int)cEntries;
442 return 0;
445 // Get the name of the default dial entry.
446 nsresult nsAutodial::GetDefaultEntryName(PRUnichar* entryName, int bufferSize)
448 // No RAS dialup entries.
449 if (mNumRASConnectionEntries <= 0)
451 return NS_ERROR_FAILURE;
454 // Single RAS dialup entry. Use it as the default to autodial.
455 if (mNumRASConnectionEntries == 1)
457 return GetFirstEntryName(entryName, bufferSize);
460 // Multiple RAS dialup entries. If a default configured in the registry,
461 // use it.
463 // For Windows XP: HKCU/Software/Microsoft/RAS Autodial/Default/DefaultInternet.
464 // or HKLM/Software/Microsoft/RAS Autodial/Default/DefaultInternet.
465 // For Windows 2K: HKCU/RemoteAccess/InternetProfile.
467 const PRUnichar* key = nsnull;
468 const PRUnichar* val = nsnull;
470 HKEY hKey = 0;
471 LONG result = 0;
473 // Windows NT and 2000
474 if ((mOSVerInfo.dwMajorVersion == 4) // Windows NT
475 || ((mOSVerInfo.dwMajorVersion == 5) && (mOSVerInfo.dwMinorVersion == 0))) // Windows 2000
477 key = L"RemoteAccess";
478 val = L"InternetProfile";
480 result = ::RegOpenKeyExW(
481 HKEY_CURRENT_USER,
482 key,
484 KEY_READ,
485 &hKey);
487 if (result != ERROR_SUCCESS)
489 return NS_ERROR_FAILURE;
492 else // Windows XP
494 key = L"Software\\Microsoft\\RAS Autodial\\Default";
495 val = L"DefaultInternet";
498 // Try HKCU first.
499 result = ::RegOpenKeyExW(
500 HKEY_CURRENT_USER,
501 key,
503 KEY_READ,
504 &hKey);
506 if (result != ERROR_SUCCESS)
508 // If not present, try HKLM.
509 result = ::RegOpenKeyExW(
510 HKEY_LOCAL_MACHINE,
511 key,
513 KEY_READ,
514 &hKey);
516 if (result != ERROR_SUCCESS)
518 return NS_ERROR_FAILURE;
524 DWORD entryType = 0;
525 DWORD buffSize = bufferSize;
527 result = ::RegQueryValueExW(hKey,
528 val,
529 nsnull,
530 &entryType,
531 (LPBYTE)entryName,
532 &buffSize);
534 ::RegCloseKey(hKey);
537 if (result != ERROR_SUCCESS)
539 // Results in a prompt for which to use at dial time.
540 return NS_ERROR_FAILURE;
543 return NS_OK;
547 // Determine if the autodial service is running on this PC.
548 PRBool nsAutodial::IsAutodialServiceRunning()
550 SC_HANDLE hSCManager =
551 OpenSCManager(nsnull, SERVICES_ACTIVE_DATABASE, SERVICE_QUERY_STATUS);
553 if (hSCManager == nsnull)
555 LOGE(("Autodial: failed to open service control manager. Error %d.",
556 ::GetLastError()));
558 return PR_FALSE;
561 SC_HANDLE hService =
562 OpenServiceW(hSCManager, L"RasAuto", SERVICE_QUERY_STATUS);
564 if (hSCManager == nsnull)
566 LOGE(("Autodial: failed to open RasAuto service."));
567 return PR_FALSE;
570 SERVICE_STATUS status;
571 if (!QueryServiceStatus(hService, &status))
573 LOGE(("Autodial: ::QueryServiceStatus() failed. Error: %d",
574 ::GetLastError()));
576 return PR_FALSE;
579 return (status.dwCurrentState == SERVICE_RUNNING);
582 // Add the specified address to the autodial directory.
583 PRBool nsAutodial::AddAddressToAutodialDirectory(const PRUnichar* hostName)
585 // Need to load the DLL if not loaded yet.
586 if (!LoadRASapi32DLL())
587 return PR_FALSE;
589 // First see if there is already a db entry for this address.
590 RASAUTODIALENTRYW autodialEntry;
591 autodialEntry.dwSize = sizeof(autodialEntry);
592 DWORD size = sizeof(autodialEntry);
593 DWORD entries = 0;
595 DWORD result = (*mpRasGetAutodialAddress)(hostName,
596 nsnull,
597 &autodialEntry,
598 &size,
599 &entries);
601 // If there is already at least 1 entry in db for this address, return.
602 if (result != ERROR_FILE_NOT_FOUND)
604 LOGD(("Autodial: Address %s already in autodial db.", hostName));
605 return PR_FALSE;
608 autodialEntry.dwSize = sizeof(autodialEntry);
609 autodialEntry.dwFlags = 0;
610 autodialEntry.dwDialingLocation = mAutodialServiceDialingLocation;
611 GetDefaultEntryName(autodialEntry.szEntry, sizeof(autodialEntry.szEntry));
613 result = (*mpRasSetAutodialAddress)(hostName,
615 &autodialEntry,
616 sizeof(autodialEntry),
619 if (result != ERROR_SUCCESS)
621 LOGE(("Autodial ::RasSetAutodialAddress failed result %d.", result));
622 return PR_FALSE;
625 LOGD(("Autodial: Added address %s to RAS autodial db for entry %s.",
626 hostName, NS_ConvertUTF16toUTF8(autodialEntry.szEntry).get()));
628 return PR_TRUE;
631 // Get the current TAPI dialing location.
632 int nsAutodial::GetCurrentLocation()
634 HKEY hKey = 0;
635 LONG result = ::RegOpenKeyExW(
636 HKEY_LOCAL_MACHINE,
637 L"Software\\Microsoft\\Windows\\CurrentVersion\\Telephony\\Locations",
639 KEY_READ,
640 &hKey);
642 if (result != ERROR_SUCCESS)
644 LOGE(("Autodial: Error opening reg key ...CurrentVersion\\Telephony\\Locations"));
645 return -1;
648 DWORD entryType = 0;
649 DWORD location = 0;
650 DWORD paramSize = sizeof(DWORD);
652 result = ::RegQueryValueExW(hKey, L"CurrentID", nsnull, &entryType, (LPBYTE)&location, &paramSize);
653 if (result != ERROR_SUCCESS)
655 ::RegCloseKey(hKey);
656 LOGE(("Autodial: Error reading reg value CurrentID."));
657 return -1;
660 ::RegCloseKey(hKey);
661 return location;
665 // Check to see if autodial for the specified location is enabled.
666 PRBool nsAutodial::IsAutodialServiceEnabled(int location)
668 if (location < 0)
669 return PR_FALSE;
671 if (!LoadRASapi32DLL())
672 return PR_FALSE;
674 PRBool enabled;
675 if ((*mpRasGetAutodialEnable)(location, &enabled) != ERROR_SUCCESS)
677 LOGE(("Autodial: Error calling RasGetAutodialEnable()"));
678 return PR_FALSE;
681 return enabled;
686 PRBool nsAutodial::LoadRASapi32DLL()
688 if (!mhRASapi32)
690 mhRASapi32 = ::LoadLibraryW(L"rasapi32.dll");
691 if ((UINT_PTR)mhRASapi32 > 32)
693 // RasEnumConnections
694 mpRasEnumConnections = (tRASENUMCONNECTIONS)
695 ::GetProcAddress(mhRASapi32, "RasEnumConnectionsW");
697 // RasEnumEntries
698 mpRasEnumEntries = (tRASENUMENTRIES)
699 ::GetProcAddress(mhRASapi32, "RasEnumEntriesW");
701 // RasSetAutodialAddress
702 mpRasSetAutodialAddress = (tRASSETAUTODIALADDRESS)
703 ::GetProcAddress(mhRASapi32, "RasSetAutodialAddressW");
705 // RasGetAutodialAddress
706 mpRasGetAutodialAddress = (tRASGETAUTODIALADDRESS)
707 ::GetProcAddress(mhRASapi32, "RasGetAutodialAddressW");
709 // RasGetAutodialEnable
710 mpRasGetAutodialEnable = (tRASGETAUTODIALENABLE)
711 ::GetProcAddress(mhRASapi32, "RasGetAutodialEnableW");
713 // RasGetAutodialParam
714 mpRasGetAutodialParam = (tRASGETAUTODIALPARAM)
715 ::GetProcAddress(mhRASapi32, "RasGetAutodialParamW");
720 if (!mhRASapi32
721 || !mpRasEnumConnections
722 || !mpRasEnumEntries
723 || !mpRasSetAutodialAddress
724 || !mpRasGetAutodialAddress
725 || !mpRasGetAutodialEnable
726 || !mpRasGetAutodialParam)
728 LOGE(("Autodial: Error loading RASAPI32.DLL."));
729 return PR_FALSE;
732 return PR_TRUE;
735 PRBool nsAutodial::LoadRASdlgDLL()
737 if (!mhRASdlg)
739 mhRASdlg = ::LoadLibraryW(L"rasdlg.dll");
740 if ((UINT_PTR)mhRASdlg > 32)
742 // RasPhonebookDlg
743 mpRasPhonebookDlg =
744 (tRASPHONEBOOKDLG)::GetProcAddress(mhRASdlg, "RasPhonebookDlgW");
746 // RasDialDlg
747 mpRasDialDlg =
748 (tRASDIALDLG)::GetProcAddress(mhRASdlg, "RasDialDlgW");
753 if (!mhRASdlg || !mpRasPhonebookDlg || !mpRasDialDlg)
755 LOGE(("Autodial: Error loading RASDLG.DLL."));
756 return PR_FALSE;
759 return PR_TRUE;