remconn.cxx
上传用户:hzhsqp
上传日期:2007-01-06
资源大小:1600k
文件大小:18k
源码类别:

IP电话/视频会议

开发平台:

Visual C++

  1. /*
  2.  * remconn.cxx
  3.  *
  4.  * Remote Networking Connection class implmentation for Win32 RAS.
  5.  *
  6.  * Portable Windows Library
  7.  *
  8.  * Copyright (c) 1993-1998 Equivalence Pty. Ltd.
  9.  *
  10.  * The contents of this file are subject to the Mozilla Public License
  11.  * Version 1.0 (the "License"); you may not use this file except in
  12.  * compliance with the License. You may obtain a copy of the License at
  13.  * http://www.mozilla.org/MPL/
  14.  *
  15.  * Software distributed under the License is distributed on an "AS IS"
  16.  * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
  17.  * the License for the specific language governing rights and limitations
  18.  * under the License.
  19.  *
  20.  * The Original Code is Portable Windows Library.
  21.  *
  22.  * The Initial Developer of the Original Code is Equivalence Pty. Ltd.
  23.  *
  24.  * Portions are Copyright (C) 1993 Free Software Foundation, Inc.
  25.  * All Rights Reserved.
  26.  *
  27.  * Contributor(s): ______________________________________.
  28.  *
  29.  * $Log: remconn.cxx,v $
  30.  * Revision 1.27  2000/03/07 01:43:29  robertj
  31.  * Removed double include of ras.h as no longer works with later versions.
  32.  *
  33.  * Revision 1.26  1999/06/27 04:21:59  robertj
  34.  * Added more debugging to GetStatus() error reporting.
  35.  *
  36.  * Revision 1.25  1999/02/16 08:08:07  robertj
  37.  * MSVC 6.0 compatibility changes.
  38.  *
  39.  * Revision 1.24  1998/11/30 04:50:16  robertj
  40.  * New directory structure
  41.  *
  42.  * Revision 1.23  1998/10/15 05:41:51  robertj
  43.  * New memory leak check code.
  44.  *
  45.  * Revision 1.22  1998/09/24 03:30:55  robertj
  46.  * Added open software license.
  47.  *
  48.  * Revision 1.21  1998/07/24 06:51:56  robertj
  49.  * Added ability to get IP number of RAS connection.
  50.  *
  51.  * Revision 1.20  1998/03/05 12:49:54  robertj
  52.  * MemCheck fixes.
  53.  *
  54.  * Revision 1.19  1998/02/03 06:16:44  robertj
  55.  * Added more error codes.
  56.  *
  57.  * Revision 1.18  1998/01/26 00:54:58  robertj
  58.  * Added function to PRemoteConnection to get at OS error code.
  59.  *
  60.  * Revision 1.17  1997/04/06 07:45:28  robertj
  61.  * Fixed bug in dialling already connected remotes.
  62.  *
  63.  * Revision 1.16  1997/04/01 06:00:06  robertj
  64.  * Added Remove Configuration.
  65.  *
  66.  * Revision 1.15  1997/02/05 11:47:25  robertj
  67.  * Fixed NT 3.51 support, again! (PAP compatibility)
  68.  *
  69.  * Revision 1.14  1997/01/25 02:22:47  robertj
  70.  * Fixed backward compatibilty with NT3.51 and Win'95
  71.  *
  72.  * Revision 1.13  1997/01/12 04:14:39  robertj
  73.  * Added ability to add/change new connections.
  74.  *
  75.  * Revision 1.12  1996/12/01 07:01:28  robertj
  76.  * Changed debugging asserts to simple PError output.
  77.  *
  78.  * Revision 1.11  1996/11/16 10:53:17  robertj
  79.  * Added missing SetlastError() so assert has correct error value.
  80.  *
  81.  * Revision 1.10  1996/11/10 21:02:46  robertj
  82.  * Try doing double sample before flagging a RAS connection disconnected.
  83.  *
  84.  * Revision 1.9  1996/11/04 09:45:26  robertj
  85.  * Yet more debugging.
  86.  *
  87.  * Revision 1.8  1996/11/04 03:37:23  robertj
  88.  * Added more debugging for remote drop outs.
  89.  *
  90.  * Revision 1.7  1996/10/31 12:39:53  robertj
  91.  * Added RCS keywords.
  92.  *
  93.  */
  94. #include <ptlib.h>
  95. #include <ptlib/remconn.h>
  96. #define SizeWin400_RAS_MaxEntryName 256
  97. #define SizeWin400_RAS_MaxPhoneNumber 128
  98. #define SizeWin400_RAS_MaxCallbackNumber SizeWin400_RAS_MaxPhoneNumber
  99. #define SizeWin400_RAS_MaxDeviceType 16
  100. #define SizeWin400_RAS_MaxDeviceName 128
  101. #define SizeWin400_RASCONN (sizeof(DWORD) + 
  102.                             sizeof(HRASCONN) + 
  103.                             SizeWin400_RAS_MaxEntryName + 1)
  104. #define SizeWin400_RASDIALPARAMS (sizeof(DWORD) + 
  105.                                   SizeWin400_RAS_MaxEntryName + 1 + 
  106.                                   SizeWin400_RAS_MaxPhoneNumber + 1 + 
  107.                                   SizeWin400_RAS_MaxCallbackNumber + 1 + 
  108.                                   UNLEN + 1 + 
  109.                                   PWLEN + 1 + 
  110.                                   DNLEN + 1)
  111. #define SizeWin400_RASCONNSTATUS (sizeof(DWORD) + 
  112.                                   sizeof(RASCONNSTATE) + 
  113.                                   sizeof(DWORD) + 
  114.                                   SizeWin400_RAS_MaxDeviceType + 1 + 
  115.                                   SizeWin400_RAS_MaxDeviceName + 1)
  116. class PRASDLL : public PDynaLink
  117. {
  118.   PCLASSINFO(PRASDLL, PDynaLink)
  119.   public:
  120.     PRASDLL();
  121.   DWORD (FAR PASCAL *Dial)(LPRASDIALEXTENSIONS,LPTSTR,LPRASDIALPARAMS,DWORD,LPVOID,LPHRASCONN);
  122.   DWORD (FAR PASCAL *HangUp)(HRASCONN);
  123.   DWORD (FAR PASCAL *GetConnectStatus)(HRASCONN,LPRASCONNSTATUS);
  124.   DWORD (FAR PASCAL *EnumConnections)(LPRASCONN,LPDWORD,LPDWORD);
  125.   DWORD (FAR PASCAL *EnumEntries)(LPTSTR,LPTSTR,LPRASENTRYNAME,LPDWORD,LPDWORD);
  126.   DWORD (FAR PASCAL *GetEntryProperties)(LPTSTR, LPTSTR, LPRASENTRY, LPDWORD, LPBYTE, LPDWORD);
  127.   DWORD (FAR PASCAL *SetEntryProperties)(LPTSTR, LPTSTR, LPRASENTRY, DWORD, LPBYTE, DWORD);
  128.   DWORD (FAR PASCAL *DeleteEntry)(LPTSTR, LPTSTR);
  129.   DWORD (FAR PASCAL *ValidateEntryName)(LPTSTR, LPTSTR);
  130.   DWORD (FAR PASCAL *GetProjectionInfo)(HRASCONN, RASPROJECTION, LPVOID, LPDWORD);
  131. } Ras;
  132. PRASDLL::PRASDLL()
  133. #ifdef _WIN32
  134.   : PDynaLink("RASAPI32.DLL")
  135. #else
  136.   : PDynaLink("RASAPI16.DLL")
  137. #endif
  138. {
  139.   if (!GetFunction("RasDialA", (Function &)Dial) ||
  140.       !GetFunction("RasHangUpA", (Function &)HangUp) ||
  141.       !GetFunction("RasGetConnectStatusA", (Function &)GetConnectStatus) ||
  142.       !GetFunction("RasEnumConnectionsA", (Function &)EnumConnections) ||
  143.       !GetFunction("RasEnumEntriesA", (Function &)EnumEntries))
  144.     Close();
  145.   GetFunction("RasGetEntryPropertiesA", (Function &)GetEntryProperties);
  146.   GetFunction("RasSetEntryPropertiesA", (Function &)SetEntryProperties);
  147.   GetFunction("RasDeleteEntryA", (Function &)DeleteEntry);
  148.   GetFunction("RasValidateEntryNameA", (Function &)ValidateEntryName);
  149.   GetFunction("RasGetProjectionInfoA", (Function &)GetProjectionInfo);
  150. }
  151. #define new PNEW
  152. static BOOL IsWinVer401()
  153. {
  154.   OSVERSIONINFO verinf;
  155.   verinf.dwOSVersionInfoSize = sizeof(verinf);
  156.   GetVersionEx(&verinf);
  157.   if (verinf.dwPlatformId != VER_PLATFORM_WIN32_NT)
  158.     return FALSE;
  159.   if (verinf.dwMajorVersion < 4)
  160.     return FALSE;
  161.   return TRUE;
  162. }
  163. PRemoteConnection::PRemoteConnection()
  164. {
  165.   Construct();
  166. }
  167. PRemoteConnection::PRemoteConnection(const PString & name)
  168.   : remoteName(name)
  169. {
  170.   Construct();
  171. }
  172. PRemoteConnection::~PRemoteConnection()
  173. {
  174.   Close();
  175. }
  176. BOOL PRemoteConnection::Open(const PString & name,
  177.                              const PString & user,
  178.                              const PString & pass,
  179.                              BOOL existing)
  180. {
  181.   if (name != remoteName) {
  182.     Close();
  183.     remoteName = name;
  184.   }
  185.   userName = user;
  186.   password = pass;
  187.   return Open(existing);
  188. }
  189. BOOL PRemoteConnection::Open(const PString & name, BOOL existing)
  190. {
  191.   if (name != remoteName) {
  192.     Close();
  193.     remoteName = name;
  194.   }
  195.   return Open(existing);
  196. }
  197. PObject::Comparison PRemoteConnection::Compare(const PObject & obj) const
  198. {
  199.   PAssert(obj.IsDescendant(PRemoteConnection::Class()), PInvalidCast);
  200.   return remoteName.Compare(((const PRemoteConnection &)obj).remoteName);
  201. }
  202. PINDEX PRemoteConnection::HashFunction() const
  203. {
  204.   return remoteName.HashFunction();
  205. }
  206. void PRemoteConnection::Construct()
  207. {
  208.   rasConnection = NULL;
  209.   osError = SUCCESS;
  210. }
  211. BOOL PRemoteConnection::Open(BOOL existing)
  212. {
  213.   Close();
  214.   if (!Ras.IsLoaded())
  215.     return FALSE;
  216.   BOOL isVer401 = IsWinVer401();
  217.   RASCONN connection;
  218.   connection.dwSize = isVer401 ? sizeof(RASCONN) : SizeWin400_RASCONN;
  219.   LPRASCONN connections = &connection;
  220.   DWORD size = sizeof(connection);
  221.   DWORD numConnections;
  222.   osError = Ras.EnumConnections(connections, &size, &numConnections);
  223.   if (osError == ERROR_BUFFER_TOO_SMALL) {
  224.     connections = new RASCONN[size/connection.dwSize];
  225.     connections[0].dwSize = connection.dwSize;
  226.     osError = Ras.EnumConnections(connections, &size, &numConnections);
  227.   }
  228.   if (osError == 0) {
  229.     for (DWORD i = 0; i < numConnections; i++) {
  230.       if (remoteName == connections[i].szEntryName) {
  231.         rasConnection = connections[i].hrasconn;
  232.         break;
  233.       }
  234.     }
  235.   }
  236.   if (connections != &connection)
  237.     delete [] connections;
  238.   if (rasConnection != NULL && GetStatus() == Connected) {
  239.     osError = 0;
  240.     return TRUE;
  241.   }
  242.   rasConnection = NULL;
  243.   if (existing)
  244.     return FALSE;
  245.   RASDIALPARAMS params;
  246.   memset(&params, 0, sizeof(params));
  247.   params.dwSize = isVer401 ? sizeof(params) : SizeWin400_RASDIALPARAMS;
  248.   if (remoteName[0] != '.') {
  249.     PAssert(remoteName.GetLength() < sizeof(params.szEntryName)-1, PInvalidParameter);
  250.     strcpy(params.szEntryName, remoteName);
  251.   }
  252.   else {
  253.     PAssert(remoteName.GetLength() < sizeof(params.szPhoneNumber), PInvalidParameter);
  254.     strcpy(params.szPhoneNumber, remoteName(1, P_MAX_INDEX));
  255.   }
  256.   strcpy(params.szUserName, userName);
  257.   strcpy(params.szPassword, password);
  258.   osError = Ras.Dial(NULL, NULL, &params, 0, NULL, &rasConnection);
  259.   if (osError == 0)
  260.     return TRUE;
  261.   if (rasConnection != NULL) {
  262.     Ras.HangUp(rasConnection);
  263.     rasConnection = NULL;
  264.   }
  265.   SetLastError(osError);
  266.   return FALSE;
  267. }
  268. void PRemoteConnection::Close()
  269. {
  270.   if (rasConnection != NULL) {
  271.     Ras.HangUp(rasConnection);
  272.     rasConnection = NULL;
  273.   }
  274. }
  275. static int GetRasStatus(HRASCONN rasConnection, DWORD & rasError)
  276. {
  277.   RASCONNSTATUS status;
  278.   status.dwSize = IsWinVer401() ? sizeof(status) : SizeWin400_RASCONNSTATUS;
  279.   rasError = Ras.GetConnectStatus(rasConnection, &status);
  280.   if (rasError == ERROR_INVALID_HANDLE) {
  281.     PError << "RAS Connection Status invalid handle, retrying.";
  282.     rasError = Ras.GetConnectStatus(rasConnection, &status);
  283.   }
  284.   if (rasError == 0) {
  285.     rasError = status.dwError;
  286.     SetLastError(rasError);
  287.     return status.rasconnstate;
  288.   }
  289.   PError << "RAS Connection Status failed (" << rasError << "), retrying.";
  290.   rasError = Ras.GetConnectStatus(rasConnection, &status);
  291.   if (rasError == 0)
  292.     rasError = status.dwError;
  293.   SetLastError(rasError);
  294.   return -1;
  295. }
  296. PRemoteConnection::Status PRemoteConnection::GetStatus() const
  297. {
  298.   if (!Ras.IsLoaded())
  299.     return NotInstalled;
  300.   if (rasConnection == NULL) {
  301.     switch (osError) {
  302.       case SUCCESS :
  303.         return Idle;
  304.       case ERROR_CANNOT_FIND_PHONEBOOK_ENTRY :
  305.         return NoNameOrNumber;
  306.       case ERROR_LINE_BUSY :
  307.         return LineBusy;
  308.       case ERROR_NO_DIALTONE :
  309.         return NoDialTone;
  310.       case ERROR_NO_ANSWER :
  311.       case ERROR_NO_CARRIER :
  312.         return NoAnswer;
  313.       case ERROR_PORT_ALREADY_OPEN :
  314.       case ERROR_PORT_NOT_AVAILABLE :
  315.         return PortInUse;
  316.       case ERROR_ACCESS_DENIED :
  317.       case ERROR_NO_DIALIN_PERMISSION :
  318.       case ERROR_AUTHENTICATION_FAILURE :
  319.         return AccessDenied;
  320.       case ERROR_HARDWARE_FAILURE :
  321.       case ERROR_PORT_OR_DEVICE :
  322.         return HardwareFailure;
  323.     }
  324.     return GeneralFailure;
  325.   }
  326.   switch (GetRasStatus(rasConnection, ((PRemoteConnection*)this)->osError)) {
  327.     case RASCS_Connected :
  328.       return Connected;
  329.     case RASCS_Disconnected :
  330.       break;
  331.     case -1 :
  332.       return ConnectionLost;
  333.     default :
  334.       return InProgress;
  335.   }
  336.   PError << "RAS Connection Status disconnected, retrying.";
  337.   switch (GetRasStatus(rasConnection, ((PRemoteConnection*)this)->osError)) {
  338.     case RASCS_Connected :
  339.       return Connected;
  340.     case RASCS_Disconnected :
  341.       return Idle;
  342.     case -1 :
  343.       return ConnectionLost;
  344.   }
  345.   return InProgress;
  346. }
  347. PString PRemoteConnection::GetAddress()
  348. {
  349.   if (Ras.GetProjectionInfo == NULL) {
  350.     osError = ERROR_CALL_NOT_IMPLEMENTED;
  351.     return PString();
  352.   }
  353.   if (rasConnection == NULL) {
  354.     osError = ERROR_INVALID_HANDLE;
  355.     return PString();
  356.   }
  357.   RASPPPIP ip;
  358.   ip.dwSize = sizeof(ip);
  359.   DWORD size = sizeof(ip);
  360.   osError = Ras.GetProjectionInfo(rasConnection, RASP_PppIp, &ip, &size);
  361.   if (osError != ERROR_SUCCESS)
  362.     return PString();
  363.   osError = ip.dwError;
  364.   if (osError != ERROR_SUCCESS)
  365.     return PString();
  366.   return ip.szIpAddress;
  367. }
  368. PStringArray PRemoteConnection::GetAvailableNames()
  369. {
  370.   PStringArray array;
  371.   if (!Ras.IsLoaded())
  372.     return array;
  373.   RASENTRYNAME entry;
  374.   entry.dwSize = sizeof(RASENTRYNAME);
  375.   LPRASENTRYNAME entries = &entry;
  376.   DWORD size = sizeof(entry);
  377.   DWORD numEntries;
  378.   DWORD rasError = Ras.EnumEntries(NULL, NULL, entries, &size, &numEntries);
  379.   if (rasError == ERROR_BUFFER_TOO_SMALL) {
  380.     entries = new RASENTRYNAME[size/sizeof(RASENTRYNAME)];
  381.     entries[0].dwSize = sizeof(RASENTRYNAME);
  382.     rasError = Ras.EnumEntries(NULL, NULL, entries, &size, &numEntries);
  383.   }
  384.   if (rasError == 0) {
  385.     array.SetSize(numEntries);
  386.     for (DWORD i = 0; i < numEntries; i++)
  387.       array[i] = entries[i].szEntryName;
  388.   }
  389.   if (entries != &entry)
  390.     delete [] entries;
  391.   return array;
  392. }
  393. PRemoteConnection::Status
  394.       PRemoteConnection::GetConfiguration(Configuration & config)
  395. {
  396.   return GetConfiguration(remoteName, config);
  397. }
  398. static DWORD MyRasGetEntryProperties(const char * name, PBYTEArray & entrybuf)
  399. {
  400.   LPRASENTRY entry = (LPRASENTRY)entrybuf.GetPointer(sizeof(RASENTRY));
  401.   entry->dwSize = sizeof(RASENTRY);
  402.   DWORD entrySize = sizeof(RASENTRY);
  403.   DWORD error = Ras.GetEntryProperties(NULL, (char *)name, entry, &entrySize, NULL, 0);
  404.   if (error == ERROR_BUFFER_TOO_SMALL) {
  405.     entry = (LPRASENTRY)entrybuf.GetPointer(entrySize);
  406.     error = Ras.GetEntryProperties(NULL, (char *)name, entry, &entrySize, NULL, 0);
  407.   }
  408.   return error;
  409. }
  410. PRemoteConnection::Status
  411.       PRemoteConnection::GetConfiguration(const PString & name,
  412.                                           Configuration & config)
  413. {
  414.   if (!Ras.IsLoaded() || Ras.GetEntryProperties == NULL)
  415.     return NotInstalled;
  416.   PBYTEArray entrybuf;
  417.   switch (MyRasGetEntryProperties(name, entrybuf)) {
  418.     case 0 :
  419.       break;
  420.     case ERROR_CANNOT_FIND_PHONEBOOK_ENTRY :
  421.       return NoNameOrNumber;
  422.     default :
  423.       return GeneralFailure;
  424.   }
  425.   LPRASENTRY entry = (LPRASENTRY)(const BYTE *)entrybuf;
  426.   config.device = entry->szDeviceType + PString("/") + entry->szDeviceName;
  427.   if ((entry->dwfOptions&RASEO_UseCountryAndAreaCodes) == 0)
  428.     config.phoneNumber = entry->szLocalPhoneNumber;
  429.   else
  430.     config.phoneNumber = psprintf("+%u %s %s",
  431.                        entry->dwCountryCode, entry->szAreaCode, entry->szLocalPhoneNumber);
  432.   if ((entry->dwfOptions&RASEO_SpecificIpAddr) == 0)
  433.     config.ipAddress = "";
  434.   else
  435.     config.ipAddress = psprintf("%u.%u.%u.%u",
  436.                                 entry->ipaddr.a, entry->ipaddr.b,
  437.                                 entry->ipaddr.c, entry->ipaddr.d);
  438.   if ((entry->dwfOptions&RASEO_SpecificNameServers) == 0)
  439.     config.dnsAddress = "";
  440.   else
  441.     config.dnsAddress = psprintf("%u.%u.%u.%u",
  442.                                  entry->ipaddrDns.a, entry->ipaddrDns.b,
  443.                                  entry->ipaddrDns.c, entry->ipaddrDns.d);
  444.   config.script = entry->szScript;
  445.   
  446.   config.subEntries = entry->dwSubEntries;
  447.   config.dialAllSubEntries = entry->dwDialMode == RASEDM_DialAll;
  448.   return Connected;
  449. }
  450. PRemoteConnection::Status
  451.       PRemoteConnection::SetConfiguration(const Configuration & config, BOOL create)
  452. {
  453.   return SetConfiguration(remoteName, config, create);
  454. }
  455. PRemoteConnection::Status
  456.       PRemoteConnection::SetConfiguration(const PString & name,
  457.                                           const Configuration & config,
  458.                                           BOOL create)
  459. {
  460.   if (!Ras.IsLoaded() || Ras.SetEntryProperties == NULL || Ras.ValidateEntryName == NULL)
  461.     return NotInstalled;
  462.   PBYTEArray entrybuf;
  463.   switch (MyRasGetEntryProperties(name, entrybuf)) {
  464.     case 0 :
  465.       break;
  466.     case ERROR_CANNOT_FIND_PHONEBOOK_ENTRY :
  467.       if (!create)
  468.         return NoNameOrNumber;
  469.       if (Ras.ValidateEntryName(NULL, (char *)(const char *)name) != 0)
  470.         return GeneralFailure;
  471.       break;
  472.     default :
  473.       return GeneralFailure;
  474.   }
  475.   LPRASENTRY entry = (LPRASENTRY)(const BYTE *)entrybuf;
  476.   PINDEX barpos = config.device.Find('/');
  477.   if (barpos == P_MAX_INDEX)
  478.     strncpy(entry->szDeviceName, config.device, sizeof(entry->szDeviceName)-1);
  479.   else {
  480.     strncpy(entry->szDeviceType, config.device.Left(barpos),  sizeof(entry->szDeviceType)-1);
  481.     strncpy(entry->szDeviceName, config.device.Mid(barpos+1), sizeof(entry->szDeviceName)-1);
  482.   }
  483.   strncpy(entry->szLocalPhoneNumber, config.phoneNumber, sizeof(entry->szLocalPhoneNumber)-1);
  484.   PStringArray dots = config.ipAddress.Tokenise('.');
  485.   if (dots.GetSize() != 4)
  486.     entry->dwfOptions &= ~RASEO_SpecificIpAddr;
  487.   else {
  488.     entry->dwfOptions |= RASEO_SpecificIpAddr;
  489.     entry->ipaddr.a = (BYTE)dots[0].AsInteger();
  490.     entry->ipaddr.b = (BYTE)dots[1].AsInteger();
  491.     entry->ipaddr.c = (BYTE)dots[2].AsInteger();
  492.     entry->ipaddr.d = (BYTE)dots[3].AsInteger();
  493.   }
  494.   dots = config.dnsAddress.Tokenise('.');
  495.   if (dots.GetSize() != 4)
  496.     entry->dwfOptions &= ~RASEO_SpecificNameServers;
  497.   else {
  498.     entry->dwfOptions |= RASEO_SpecificNameServers;
  499.     entry->ipaddrDns.a = (BYTE)dots[0].AsInteger();
  500.     entry->ipaddrDns.b = (BYTE)dots[1].AsInteger();
  501.     entry->ipaddrDns.c = (BYTE)dots[2].AsInteger();
  502.     entry->ipaddrDns.d = (BYTE)dots[3].AsInteger();
  503.   }
  504.   strncpy(entry->szScript, config.script, sizeof(entry->szScript-1));
  505.   entry->dwDialMode = config.dialAllSubEntries ? RASEDM_DialAll : RASEDM_DialAsNeeded;
  506.   if (Ras.SetEntryProperties(NULL, (char *)(const char *)name,
  507.                              entry, entrybuf.GetSize(), NULL, 0) != 0)
  508.     return GeneralFailure;
  509.   return Connected;
  510. }
  511. PRemoteConnection::Status
  512.                   PRemoteConnection::RemoveConfiguration(const PString & name)
  513. {
  514.   if (!Ras.IsLoaded() || Ras.SetEntryProperties == NULL || Ras.ValidateEntryName == NULL)
  515.     return NotInstalled;
  516.   switch (Ras.DeleteEntry(NULL, (char *)(const char *)name)) {
  517.     case 0 :
  518.       return Connected;
  519.     case ERROR_INVALID_NAME :
  520.       return NoNameOrNumber;
  521.   }
  522.   return GeneralFailure;
  523. }
  524. // End of File ////////////////////////////////////////////////////////////////