remconn.cxx
上传用户:hzhsqp
上传日期:2007-01-06
资源大小:1600k
文件大小:18k
- /*
- * remconn.cxx
- *
- * Remote Networking Connection class implmentation for Win32 RAS.
- *
- * Portable Windows Library
- *
- * Copyright (c) 1993-1998 Equivalence Pty. Ltd.
- *
- * The contents of this file are subject to the Mozilla Public License
- * Version 1.0 (the "License"); you may not use this file except in
- * compliance with the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS"
- * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
- * the License for the specific language governing rights and limitations
- * under the License.
- *
- * The Original Code is Portable Windows Library.
- *
- * The Initial Developer of the Original Code is Equivalence Pty. Ltd.
- *
- * Portions are Copyright (C) 1993 Free Software Foundation, Inc.
- * All Rights Reserved.
- *
- * Contributor(s): ______________________________________.
- *
- * $Log: remconn.cxx,v $
- * Revision 1.27 2000/03/07 01:43:29 robertj
- * Removed double include of ras.h as no longer works with later versions.
- *
- * Revision 1.26 1999/06/27 04:21:59 robertj
- * Added more debugging to GetStatus() error reporting.
- *
- * Revision 1.25 1999/02/16 08:08:07 robertj
- * MSVC 6.0 compatibility changes.
- *
- * Revision 1.24 1998/11/30 04:50:16 robertj
- * New directory structure
- *
- * Revision 1.23 1998/10/15 05:41:51 robertj
- * New memory leak check code.
- *
- * Revision 1.22 1998/09/24 03:30:55 robertj
- * Added open software license.
- *
- * Revision 1.21 1998/07/24 06:51:56 robertj
- * Added ability to get IP number of RAS connection.
- *
- * Revision 1.20 1998/03/05 12:49:54 robertj
- * MemCheck fixes.
- *
- * Revision 1.19 1998/02/03 06:16:44 robertj
- * Added more error codes.
- *
- * Revision 1.18 1998/01/26 00:54:58 robertj
- * Added function to PRemoteConnection to get at OS error code.
- *
- * Revision 1.17 1997/04/06 07:45:28 robertj
- * Fixed bug in dialling already connected remotes.
- *
- * Revision 1.16 1997/04/01 06:00:06 robertj
- * Added Remove Configuration.
- *
- * Revision 1.15 1997/02/05 11:47:25 robertj
- * Fixed NT 3.51 support, again! (PAP compatibility)
- *
- * Revision 1.14 1997/01/25 02:22:47 robertj
- * Fixed backward compatibilty with NT3.51 and Win'95
- *
- * Revision 1.13 1997/01/12 04:14:39 robertj
- * Added ability to add/change new connections.
- *
- * Revision 1.12 1996/12/01 07:01:28 robertj
- * Changed debugging asserts to simple PError output.
- *
- * Revision 1.11 1996/11/16 10:53:17 robertj
- * Added missing SetlastError() so assert has correct error value.
- *
- * Revision 1.10 1996/11/10 21:02:46 robertj
- * Try doing double sample before flagging a RAS connection disconnected.
- *
- * Revision 1.9 1996/11/04 09:45:26 robertj
- * Yet more debugging.
- *
- * Revision 1.8 1996/11/04 03:37:23 robertj
- * Added more debugging for remote drop outs.
- *
- * Revision 1.7 1996/10/31 12:39:53 robertj
- * Added RCS keywords.
- *
- */
- #include <ptlib.h>
- #include <ptlib/remconn.h>
- #define SizeWin400_RAS_MaxEntryName 256
- #define SizeWin400_RAS_MaxPhoneNumber 128
- #define SizeWin400_RAS_MaxCallbackNumber SizeWin400_RAS_MaxPhoneNumber
- #define SizeWin400_RAS_MaxDeviceType 16
- #define SizeWin400_RAS_MaxDeviceName 128
- #define SizeWin400_RASCONN (sizeof(DWORD) +
- sizeof(HRASCONN) +
- SizeWin400_RAS_MaxEntryName + 1)
- #define SizeWin400_RASDIALPARAMS (sizeof(DWORD) +
- SizeWin400_RAS_MaxEntryName + 1 +
- SizeWin400_RAS_MaxPhoneNumber + 1 +
- SizeWin400_RAS_MaxCallbackNumber + 1 +
- UNLEN + 1 +
- PWLEN + 1 +
- DNLEN + 1)
- #define SizeWin400_RASCONNSTATUS (sizeof(DWORD) +
- sizeof(RASCONNSTATE) +
- sizeof(DWORD) +
- SizeWin400_RAS_MaxDeviceType + 1 +
- SizeWin400_RAS_MaxDeviceName + 1)
- class PRASDLL : public PDynaLink
- {
- PCLASSINFO(PRASDLL, PDynaLink)
- public:
- PRASDLL();
- DWORD (FAR PASCAL *Dial)(LPRASDIALEXTENSIONS,LPTSTR,LPRASDIALPARAMS,DWORD,LPVOID,LPHRASCONN);
- DWORD (FAR PASCAL *HangUp)(HRASCONN);
- DWORD (FAR PASCAL *GetConnectStatus)(HRASCONN,LPRASCONNSTATUS);
- DWORD (FAR PASCAL *EnumConnections)(LPRASCONN,LPDWORD,LPDWORD);
- DWORD (FAR PASCAL *EnumEntries)(LPTSTR,LPTSTR,LPRASENTRYNAME,LPDWORD,LPDWORD);
- DWORD (FAR PASCAL *GetEntryProperties)(LPTSTR, LPTSTR, LPRASENTRY, LPDWORD, LPBYTE, LPDWORD);
- DWORD (FAR PASCAL *SetEntryProperties)(LPTSTR, LPTSTR, LPRASENTRY, DWORD, LPBYTE, DWORD);
- DWORD (FAR PASCAL *DeleteEntry)(LPTSTR, LPTSTR);
- DWORD (FAR PASCAL *ValidateEntryName)(LPTSTR, LPTSTR);
- DWORD (FAR PASCAL *GetProjectionInfo)(HRASCONN, RASPROJECTION, LPVOID, LPDWORD);
- } Ras;
- PRASDLL::PRASDLL()
- #ifdef _WIN32
- : PDynaLink("RASAPI32.DLL")
- #else
- : PDynaLink("RASAPI16.DLL")
- #endif
- {
- if (!GetFunction("RasDialA", (Function &)Dial) ||
- !GetFunction("RasHangUpA", (Function &)HangUp) ||
- !GetFunction("RasGetConnectStatusA", (Function &)GetConnectStatus) ||
- !GetFunction("RasEnumConnectionsA", (Function &)EnumConnections) ||
- !GetFunction("RasEnumEntriesA", (Function &)EnumEntries))
- Close();
- GetFunction("RasGetEntryPropertiesA", (Function &)GetEntryProperties);
- GetFunction("RasSetEntryPropertiesA", (Function &)SetEntryProperties);
- GetFunction("RasDeleteEntryA", (Function &)DeleteEntry);
- GetFunction("RasValidateEntryNameA", (Function &)ValidateEntryName);
- GetFunction("RasGetProjectionInfoA", (Function &)GetProjectionInfo);
- }
- #define new PNEW
- static BOOL IsWinVer401()
- {
- OSVERSIONINFO verinf;
- verinf.dwOSVersionInfoSize = sizeof(verinf);
- GetVersionEx(&verinf);
- if (verinf.dwPlatformId != VER_PLATFORM_WIN32_NT)
- return FALSE;
- if (verinf.dwMajorVersion < 4)
- return FALSE;
- return TRUE;
- }
- PRemoteConnection::PRemoteConnection()
- {
- Construct();
- }
- PRemoteConnection::PRemoteConnection(const PString & name)
- : remoteName(name)
- {
- Construct();
- }
- PRemoteConnection::~PRemoteConnection()
- {
- Close();
- }
- BOOL PRemoteConnection::Open(const PString & name,
- const PString & user,
- const PString & pass,
- BOOL existing)
- {
- if (name != remoteName) {
- Close();
- remoteName = name;
- }
- userName = user;
- password = pass;
- return Open(existing);
- }
- BOOL PRemoteConnection::Open(const PString & name, BOOL existing)
- {
- if (name != remoteName) {
- Close();
- remoteName = name;
- }
- return Open(existing);
- }
- PObject::Comparison PRemoteConnection::Compare(const PObject & obj) const
- {
- PAssert(obj.IsDescendant(PRemoteConnection::Class()), PInvalidCast);
- return remoteName.Compare(((const PRemoteConnection &)obj).remoteName);
- }
- PINDEX PRemoteConnection::HashFunction() const
- {
- return remoteName.HashFunction();
- }
- void PRemoteConnection::Construct()
- {
- rasConnection = NULL;
- osError = SUCCESS;
- }
- BOOL PRemoteConnection::Open(BOOL existing)
- {
- Close();
- if (!Ras.IsLoaded())
- return FALSE;
- BOOL isVer401 = IsWinVer401();
- RASCONN connection;
- connection.dwSize = isVer401 ? sizeof(RASCONN) : SizeWin400_RASCONN;
- LPRASCONN connections = &connection;
- DWORD size = sizeof(connection);
- DWORD numConnections;
- osError = Ras.EnumConnections(connections, &size, &numConnections);
- if (osError == ERROR_BUFFER_TOO_SMALL) {
- connections = new RASCONN[size/connection.dwSize];
- connections[0].dwSize = connection.dwSize;
- osError = Ras.EnumConnections(connections, &size, &numConnections);
- }
- if (osError == 0) {
- for (DWORD i = 0; i < numConnections; i++) {
- if (remoteName == connections[i].szEntryName) {
- rasConnection = connections[i].hrasconn;
- break;
- }
- }
- }
- if (connections != &connection)
- delete [] connections;
- if (rasConnection != NULL && GetStatus() == Connected) {
- osError = 0;
- return TRUE;
- }
- rasConnection = NULL;
- if (existing)
- return FALSE;
- RASDIALPARAMS params;
- memset(¶ms, 0, sizeof(params));
- params.dwSize = isVer401 ? sizeof(params) : SizeWin400_RASDIALPARAMS;
- if (remoteName[0] != '.') {
- PAssert(remoteName.GetLength() < sizeof(params.szEntryName)-1, PInvalidParameter);
- strcpy(params.szEntryName, remoteName);
- }
- else {
- PAssert(remoteName.GetLength() < sizeof(params.szPhoneNumber), PInvalidParameter);
- strcpy(params.szPhoneNumber, remoteName(1, P_MAX_INDEX));
- }
- strcpy(params.szUserName, userName);
- strcpy(params.szPassword, password);
- osError = Ras.Dial(NULL, NULL, ¶ms, 0, NULL, &rasConnection);
- if (osError == 0)
- return TRUE;
- if (rasConnection != NULL) {
- Ras.HangUp(rasConnection);
- rasConnection = NULL;
- }
- SetLastError(osError);
- return FALSE;
- }
- void PRemoteConnection::Close()
- {
- if (rasConnection != NULL) {
- Ras.HangUp(rasConnection);
- rasConnection = NULL;
- }
- }
- static int GetRasStatus(HRASCONN rasConnection, DWORD & rasError)
- {
- RASCONNSTATUS status;
- status.dwSize = IsWinVer401() ? sizeof(status) : SizeWin400_RASCONNSTATUS;
- rasError = Ras.GetConnectStatus(rasConnection, &status);
- if (rasError == ERROR_INVALID_HANDLE) {
- PError << "RAS Connection Status invalid handle, retrying.";
- rasError = Ras.GetConnectStatus(rasConnection, &status);
- }
- if (rasError == 0) {
- rasError = status.dwError;
- SetLastError(rasError);
- return status.rasconnstate;
- }
- PError << "RAS Connection Status failed (" << rasError << "), retrying.";
- rasError = Ras.GetConnectStatus(rasConnection, &status);
- if (rasError == 0)
- rasError = status.dwError;
- SetLastError(rasError);
- return -1;
- }
- PRemoteConnection::Status PRemoteConnection::GetStatus() const
- {
- if (!Ras.IsLoaded())
- return NotInstalled;
- if (rasConnection == NULL) {
- switch (osError) {
- case SUCCESS :
- return Idle;
- case ERROR_CANNOT_FIND_PHONEBOOK_ENTRY :
- return NoNameOrNumber;
- case ERROR_LINE_BUSY :
- return LineBusy;
- case ERROR_NO_DIALTONE :
- return NoDialTone;
- case ERROR_NO_ANSWER :
- case ERROR_NO_CARRIER :
- return NoAnswer;
- case ERROR_PORT_ALREADY_OPEN :
- case ERROR_PORT_NOT_AVAILABLE :
- return PortInUse;
- case ERROR_ACCESS_DENIED :
- case ERROR_NO_DIALIN_PERMISSION :
- case ERROR_AUTHENTICATION_FAILURE :
- return AccessDenied;
- case ERROR_HARDWARE_FAILURE :
- case ERROR_PORT_OR_DEVICE :
- return HardwareFailure;
- }
- return GeneralFailure;
- }
- switch (GetRasStatus(rasConnection, ((PRemoteConnection*)this)->osError)) {
- case RASCS_Connected :
- return Connected;
- case RASCS_Disconnected :
- break;
- case -1 :
- return ConnectionLost;
- default :
- return InProgress;
- }
- PError << "RAS Connection Status disconnected, retrying.";
- switch (GetRasStatus(rasConnection, ((PRemoteConnection*)this)->osError)) {
- case RASCS_Connected :
- return Connected;
- case RASCS_Disconnected :
- return Idle;
- case -1 :
- return ConnectionLost;
- }
- return InProgress;
- }
- PString PRemoteConnection::GetAddress()
- {
- if (Ras.GetProjectionInfo == NULL) {
- osError = ERROR_CALL_NOT_IMPLEMENTED;
- return PString();
- }
- if (rasConnection == NULL) {
- osError = ERROR_INVALID_HANDLE;
- return PString();
- }
- RASPPPIP ip;
- ip.dwSize = sizeof(ip);
- DWORD size = sizeof(ip);
- osError = Ras.GetProjectionInfo(rasConnection, RASP_PppIp, &ip, &size);
- if (osError != ERROR_SUCCESS)
- return PString();
- osError = ip.dwError;
- if (osError != ERROR_SUCCESS)
- return PString();
- return ip.szIpAddress;
- }
- PStringArray PRemoteConnection::GetAvailableNames()
- {
- PStringArray array;
- if (!Ras.IsLoaded())
- return array;
- RASENTRYNAME entry;
- entry.dwSize = sizeof(RASENTRYNAME);
- LPRASENTRYNAME entries = &entry;
- DWORD size = sizeof(entry);
- DWORD numEntries;
- DWORD rasError = Ras.EnumEntries(NULL, NULL, entries, &size, &numEntries);
- if (rasError == ERROR_BUFFER_TOO_SMALL) {
- entries = new RASENTRYNAME[size/sizeof(RASENTRYNAME)];
- entries[0].dwSize = sizeof(RASENTRYNAME);
- rasError = Ras.EnumEntries(NULL, NULL, entries, &size, &numEntries);
- }
- if (rasError == 0) {
- array.SetSize(numEntries);
- for (DWORD i = 0; i < numEntries; i++)
- array[i] = entries[i].szEntryName;
- }
- if (entries != &entry)
- delete [] entries;
- return array;
- }
- PRemoteConnection::Status
- PRemoteConnection::GetConfiguration(Configuration & config)
- {
- return GetConfiguration(remoteName, config);
- }
- static DWORD MyRasGetEntryProperties(const char * name, PBYTEArray & entrybuf)
- {
- LPRASENTRY entry = (LPRASENTRY)entrybuf.GetPointer(sizeof(RASENTRY));
- entry->dwSize = sizeof(RASENTRY);
- DWORD entrySize = sizeof(RASENTRY);
- DWORD error = Ras.GetEntryProperties(NULL, (char *)name, entry, &entrySize, NULL, 0);
- if (error == ERROR_BUFFER_TOO_SMALL) {
- entry = (LPRASENTRY)entrybuf.GetPointer(entrySize);
- error = Ras.GetEntryProperties(NULL, (char *)name, entry, &entrySize, NULL, 0);
- }
- return error;
- }
- PRemoteConnection::Status
- PRemoteConnection::GetConfiguration(const PString & name,
- Configuration & config)
- {
- if (!Ras.IsLoaded() || Ras.GetEntryProperties == NULL)
- return NotInstalled;
- PBYTEArray entrybuf;
- switch (MyRasGetEntryProperties(name, entrybuf)) {
- case 0 :
- break;
- case ERROR_CANNOT_FIND_PHONEBOOK_ENTRY :
- return NoNameOrNumber;
- default :
- return GeneralFailure;
- }
- LPRASENTRY entry = (LPRASENTRY)(const BYTE *)entrybuf;
- config.device = entry->szDeviceType + PString("/") + entry->szDeviceName;
- if ((entry->dwfOptions&RASEO_UseCountryAndAreaCodes) == 0)
- config.phoneNumber = entry->szLocalPhoneNumber;
- else
- config.phoneNumber = psprintf("+%u %s %s",
- entry->dwCountryCode, entry->szAreaCode, entry->szLocalPhoneNumber);
- if ((entry->dwfOptions&RASEO_SpecificIpAddr) == 0)
- config.ipAddress = "";
- else
- config.ipAddress = psprintf("%u.%u.%u.%u",
- entry->ipaddr.a, entry->ipaddr.b,
- entry->ipaddr.c, entry->ipaddr.d);
- if ((entry->dwfOptions&RASEO_SpecificNameServers) == 0)
- config.dnsAddress = "";
- else
- config.dnsAddress = psprintf("%u.%u.%u.%u",
- entry->ipaddrDns.a, entry->ipaddrDns.b,
- entry->ipaddrDns.c, entry->ipaddrDns.d);
- config.script = entry->szScript;
-
- config.subEntries = entry->dwSubEntries;
- config.dialAllSubEntries = entry->dwDialMode == RASEDM_DialAll;
- return Connected;
- }
- PRemoteConnection::Status
- PRemoteConnection::SetConfiguration(const Configuration & config, BOOL create)
- {
- return SetConfiguration(remoteName, config, create);
- }
- PRemoteConnection::Status
- PRemoteConnection::SetConfiguration(const PString & name,
- const Configuration & config,
- BOOL create)
- {
- if (!Ras.IsLoaded() || Ras.SetEntryProperties == NULL || Ras.ValidateEntryName == NULL)
- return NotInstalled;
- PBYTEArray entrybuf;
- switch (MyRasGetEntryProperties(name, entrybuf)) {
- case 0 :
- break;
- case ERROR_CANNOT_FIND_PHONEBOOK_ENTRY :
- if (!create)
- return NoNameOrNumber;
- if (Ras.ValidateEntryName(NULL, (char *)(const char *)name) != 0)
- return GeneralFailure;
- break;
- default :
- return GeneralFailure;
- }
- LPRASENTRY entry = (LPRASENTRY)(const BYTE *)entrybuf;
- PINDEX barpos = config.device.Find('/');
- if (barpos == P_MAX_INDEX)
- strncpy(entry->szDeviceName, config.device, sizeof(entry->szDeviceName)-1);
- else {
- strncpy(entry->szDeviceType, config.device.Left(barpos), sizeof(entry->szDeviceType)-1);
- strncpy(entry->szDeviceName, config.device.Mid(barpos+1), sizeof(entry->szDeviceName)-1);
- }
- strncpy(entry->szLocalPhoneNumber, config.phoneNumber, sizeof(entry->szLocalPhoneNumber)-1);
- PStringArray dots = config.ipAddress.Tokenise('.');
- if (dots.GetSize() != 4)
- entry->dwfOptions &= ~RASEO_SpecificIpAddr;
- else {
- entry->dwfOptions |= RASEO_SpecificIpAddr;
- entry->ipaddr.a = (BYTE)dots[0].AsInteger();
- entry->ipaddr.b = (BYTE)dots[1].AsInteger();
- entry->ipaddr.c = (BYTE)dots[2].AsInteger();
- entry->ipaddr.d = (BYTE)dots[3].AsInteger();
- }
- dots = config.dnsAddress.Tokenise('.');
- if (dots.GetSize() != 4)
- entry->dwfOptions &= ~RASEO_SpecificNameServers;
- else {
- entry->dwfOptions |= RASEO_SpecificNameServers;
- entry->ipaddrDns.a = (BYTE)dots[0].AsInteger();
- entry->ipaddrDns.b = (BYTE)dots[1].AsInteger();
- entry->ipaddrDns.c = (BYTE)dots[2].AsInteger();
- entry->ipaddrDns.d = (BYTE)dots[3].AsInteger();
- }
- strncpy(entry->szScript, config.script, sizeof(entry->szScript-1));
- entry->dwDialMode = config.dialAllSubEntries ? RASEDM_DialAll : RASEDM_DialAsNeeded;
- if (Ras.SetEntryProperties(NULL, (char *)(const char *)name,
- entry, entrybuf.GetSize(), NULL, 0) != 0)
- return GeneralFailure;
- return Connected;
- }
- PRemoteConnection::Status
- PRemoteConnection::RemoveConfiguration(const PString & name)
- {
- if (!Ras.IsLoaded() || Ras.SetEntryProperties == NULL || Ras.ValidateEntryName == NULL)
- return NotInstalled;
- switch (Ras.DeleteEntry(NULL, (char *)(const char *)name)) {
- case 0 :
- return Connected;
- case ERROR_INVALID_NAME :
- return NoNameOrNumber;
- }
- return GeneralFailure;
- }
- // End of File ////////////////////////////////////////////////////////////////