642 lines
17 KiB
C++
642 lines
17 KiB
C++
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
|
*
|
|
* The contents of this file are subject to the Netscape Public
|
|
* License Version 1.1 (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/NPL/
|
|
*
|
|
* 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 mozilla.org code.
|
|
*
|
|
* The Initial Developer of the Original Code is Netscape
|
|
* Communications Corporation. Portions created by Netscape are
|
|
* Copyright (C) 1998 Netscape Communications Corporation. All
|
|
* Rights Reserved.
|
|
*
|
|
* Contributor(s):
|
|
*/
|
|
|
|
#include "MUC.h"
|
|
#include "LMUCHandler.h"
|
|
#include <CodeFragments.h>
|
|
#include <PPobClasses.h>
|
|
#include <UDrawingState.h>
|
|
#include <Gestalt.h>
|
|
#include <ToolUtils.h>
|
|
#include <OpenTransport.h>
|
|
#include "ppp.h"
|
|
#include "ppp.interface.h"
|
|
#include "ppp_prefs_types.h"
|
|
#include "LNetworkPrefs.h"
|
|
#include "OTTCPPriv.h" // in the RestartTCP project
|
|
|
|
// error codes that the OT configuration stub might report back to us
|
|
// undocumented from Apple
|
|
enum kOTConfigurationErrorCodes
|
|
{
|
|
kOTErr_noErr = 0,
|
|
|
|
kOTErr_UnsupportedSelector = -1,
|
|
// The specified selector code is not supported in this version
|
|
|
|
kOTErr_SelectorInvalidWhileConnected = -2,
|
|
// Some operations are not supported while a connection is open
|
|
|
|
kOTErr_UnknownConfigurationError = -3,
|
|
// Tried to select an unknown configuration
|
|
|
|
kOTErr_PrefsAccessError = -4,
|
|
// Got an error trying to access the prefs file
|
|
|
|
kOTErr_PrefsMemoryError = -5,
|
|
// Not enough memory to build the prefs name list
|
|
|
|
kOTErr_OTConfigurationNotPresent = -6,
|
|
// The requested configuration is not present in OT. If the FreePPP Account
|
|
// is configured to switch OT settings automatically and this error is
|
|
// returned when selecting the Account it also means that FreePPP was not
|
|
// able to create the OT config.
|
|
|
|
kOTErr_OTConfigurationInterrupts = -7,
|
|
// The configuration change will interrupt OT connections
|
|
|
|
kOTErr_OTConfigurationRequiresReboot = -8,
|
|
// The configuration change will require a reboot
|
|
|
|
kOTErr_CantLoadNeededResourcesError = -9,
|
|
// General error for when we can't find a needed resource (or resource file)
|
|
|
|
kOTErr_OTConfigInfoMissingError = -10,
|
|
// Missing DNS or Search Domain info in the Account config so no OT config
|
|
// can be created
|
|
|
|
kOTErr_EndSelector
|
|
};
|
|
|
|
LMUCHandler* gMUCHandler = NULL;
|
|
Int16 gRefNum = refNum_Undefined;
|
|
FSSpec gRsrcFile;
|
|
|
|
static long MUC_DeleteDialConfiguration( PPPConfigureStruct* data );
|
|
static long MUC_CreateModifyDialConfiguration( PPPConfigureStruct* data );
|
|
static long MUC_OpenDialConnection( void* );
|
|
static long MUC_CloseDialConnection( void* );
|
|
static long MUC_GetActiveDialConfiguration( Str255* configName );
|
|
static long MUC_SetActiveDialConfiguration( Str255* configName );
|
|
static long MUC_GetActiveOTConfiguration( Str255* configName );
|
|
static long MUC_SetActiveOTConfiguration( Str255* configName );
|
|
static long MUC_GetDialConnectionState( Boolean* connected );
|
|
static long MUC_GetAutoConnectState( Boolean* allowsAutoConnect );
|
|
static long MUC_SetAutoConnectState( Boolean* allowsAutoConnect );
|
|
static long MUC_GetModemsList( Str255** modemsList );
|
|
static long MUC_GetActiveModemName( Str255* modemName );
|
|
static long MUC_GetReceivedIPPacketCount( unsigned long* packetCount );
|
|
|
|
|
|
static OSErr InitConfigStrList( configStringArray configStrList, PPPConfigureStruct* data,
|
|
Boolean* configureTCP, Boolean* configureIC );
|
|
static void AddressToString( unsigned long address, StringPtr string );
|
|
unsigned long AddressToLong( StringPtr addressStr );
|
|
static Boolean OTAvailable();
|
|
|
|
extern pascal OSErr __muc_initialize( const CFragInitBlock* block );
|
|
extern pascal void __muc_terminate( void );
|
|
extern pascal OSErr __initialize( const CFragInitBlock *theInitBlock );
|
|
extern pascal void __terminate( void );
|
|
|
|
long PE_PluginFunc( long selectorCode, void* pb, void* returnData )
|
|
{
|
|
long returnCode = 0;
|
|
|
|
gRefNum = ::FSpOpenResFile( &gRsrcFile, fsRdPerm );
|
|
switch ( selectorCode )
|
|
{
|
|
// ¥Êfill in the version in pb
|
|
case kGetPluginVersion:
|
|
*(long*)pb = 0x00010000;
|
|
*(long*)returnData = NULL;
|
|
returnCode = 0;
|
|
break;
|
|
|
|
case kCreateNewDialConfig:
|
|
case kModifyDialConfig:
|
|
returnCode = MUC_CreateModifyDialConfiguration( (PPPConfigureStruct*)pb );
|
|
break;
|
|
|
|
case kDeleteDialConfig:
|
|
returnCode = MUC_DeleteDialConfiguration( (PPPConfigureStruct*)pb );
|
|
break;
|
|
|
|
case kOpenConnection:
|
|
returnCode = MUC_OpenDialConnection( pb );
|
|
break;
|
|
|
|
case kCloseConnection:
|
|
returnCode = MUC_CloseDialConnection( pb );
|
|
break;
|
|
|
|
case kGetActivePPPConfig:
|
|
returnCode = MUC_GetActiveDialConfiguration( (Str255*)pb );
|
|
break;
|
|
|
|
case kSetActivePPPConfig:
|
|
returnCode = MUC_SetActiveDialConfiguration( (Str255*)pb );
|
|
break;
|
|
|
|
case kGetActiveOTConfig:
|
|
returnCode = MUC_GetActiveOTConfiguration( (Str255*)pb );
|
|
break;
|
|
|
|
case kSetActiveOTConfig:
|
|
returnCode = MUC_SetActiveOTConfiguration( (Str255*)pb );
|
|
break;
|
|
|
|
case kGetConnectionState:
|
|
returnCode = MUC_GetDialConnectionState( (Boolean*)pb );
|
|
break;
|
|
|
|
case kGetAutoConnectState:
|
|
returnCode = MUC_GetAutoConnectState( (Boolean*)pb );
|
|
break;
|
|
|
|
case kSetAutoConnectState:
|
|
returnCode = MUC_SetAutoConnectState( (Boolean*)pb );
|
|
break;
|
|
|
|
case kGetModemsList:
|
|
returnCode = MUC_GetModemsList( (Str255**)pb );
|
|
break;
|
|
|
|
case kGetActiveModemName:
|
|
returnCode = MUC_GetActiveModemName( (Str255*)pb );
|
|
break;
|
|
|
|
case kGetReceivedIPPacketCount:
|
|
returnCode = MUC_GetReceivedIPPacketCount( (unsigned long*)pb );
|
|
break;
|
|
|
|
case kSelectDialConfig:
|
|
if ( gMUCHandler )
|
|
{
|
|
returnCode = gMUCHandler->SelectProfile( (FSSpec*)pb, false );
|
|
if ( returnCode == errNeedToRunAccountSetup )
|
|
{
|
|
// ¥Êcopy local file URL of AS into returnData
|
|
}
|
|
}
|
|
break;
|
|
|
|
case kAutoSelectDialConfig:
|
|
if ( gMUCHandler )
|
|
{
|
|
returnCode = gMUCHandler->SelectProfile( (FSSpec*)pb, true );
|
|
if ( returnCode == errNeedToRunAccountSetup )
|
|
{
|
|
}
|
|
}
|
|
break;
|
|
|
|
case kEditDialConfig:
|
|
if ( gMUCHandler )
|
|
returnCode = gMUCHandler->EditProfile( (FSSpec*)pb );
|
|
break;
|
|
|
|
case kGetDialConfig:
|
|
if ( gMUCHandler )
|
|
returnCode = gMUCHandler->GetProfile( (FSSpec*)pb, (FreePPPInfo*)returnData );
|
|
break;
|
|
|
|
case kSetDialConfig:
|
|
if ( gMUCHandler )
|
|
returnCode = gMUCHandler->SetProfile( (FSSpec*)pb, (FreePPPInfo*)returnData );
|
|
break;
|
|
|
|
case kNewProfileSelect:
|
|
if ( gMUCHandler )
|
|
returnCode = gMUCHandler->ProfileSelectionChanged( (FSSpec*)pb );
|
|
break;
|
|
|
|
case kClearProfileSelect:
|
|
if ( gMUCHandler )
|
|
returnCode = gMUCHandler->ProfileSelectionChanged( NULL );
|
|
break;
|
|
|
|
case kInitListener:
|
|
if ( gMUCHandler )
|
|
gMUCHandler->InitDialog( (LDialogBox*)pb );
|
|
break;
|
|
|
|
}
|
|
::CloseResFile( gRefNum );
|
|
return returnCode;
|
|
}
|
|
|
|
pascal OSErr __muc_initialize( const CFragInitBlock* block )
|
|
{
|
|
OSErr err;
|
|
|
|
err = __initialize( block );
|
|
|
|
if ( err == noErr )
|
|
{
|
|
if ( !gMUCHandler )
|
|
gMUCHandler = new LMUCHandler;
|
|
|
|
if ( !gMUCHandler )
|
|
|
|
#ifdef CWGOLD11
|
|
return fragNoMem;
|
|
#else
|
|
return cfragInitFunctionErr;
|
|
#endif
|
|
|
|
gMUCHandler->RegisterClasses();
|
|
|
|
#ifdef CWGOLD11
|
|
CFragHFSLocator location;
|
|
#else
|
|
CFragSystem7Locator location;
|
|
#endif
|
|
location = block->fragLocator;
|
|
if ( location.where == kDataForkCFragLocator )
|
|
gRsrcFile = *(location.u.onDisk.fileSpec);
|
|
}
|
|
return err;
|
|
}
|
|
|
|
pascal void __muc_terminate()
|
|
{
|
|
if ( gMUCHandler )
|
|
delete gMUCHandler;
|
|
gMUCHandler = NULL;
|
|
__terminate();
|
|
}
|
|
|
|
static long MUC_CreateModifyDialConfiguration( PPPConfigureStruct* data )
|
|
{
|
|
long configError = noErr;
|
|
|
|
Boolean configureTCP;
|
|
Boolean configureIC;
|
|
ConfigStringArray configStrList;
|
|
|
|
if ( gRefNum == -1 )
|
|
return fnfErr;
|
|
|
|
configError = InitConfigStrList( configStrList, data, &configureTCP, &configureIC );
|
|
if ( configError == noErr )
|
|
{
|
|
Try_
|
|
{
|
|
ThrowIfOSErr_( CallPPPRequest( eNewConfigureRequest, (void*)data ) );
|
|
CreateModifyPrefs( configStrList, gRefNum, configureTCP, configureIC, OTAvailable() );
|
|
}
|
|
Catch_( e )
|
|
{
|
|
configError = e;
|
|
}
|
|
}
|
|
|
|
if ( !OTAvailable() && configError == noErr )
|
|
{
|
|
// No OpenTransport, we might need to reboot
|
|
if ( gMacTCPDirty )
|
|
configError = 1;
|
|
}
|
|
// If configError < 0 (An error occured)
|
|
// If configError == 0 noError, no reboot required
|
|
// If configError > 0 and MacTCP is running, noError And Reboot required
|
|
return configError;
|
|
}
|
|
|
|
static long MUC_DeleteDialConfiguration( PPPConfigureStruct* data )
|
|
{
|
|
Boolean dummy;
|
|
short configError = noErr; // This should be global
|
|
ConfigStringArray configStrList;
|
|
|
|
if ( !OTAvailable() )
|
|
return 0;
|
|
|
|
configError = InitConfigStrList( configStrList, data, &dummy, &dummy );
|
|
if ( configError == noErr )
|
|
{
|
|
Try_
|
|
{
|
|
ThrowIfOSErr_( CallPPPRequest( eDeleteConfiguration, (void*)data ) );
|
|
DeleteConfig( configStrList );
|
|
}
|
|
Catch_( e )
|
|
{
|
|
configError = e;
|
|
}
|
|
}
|
|
|
|
return configError;
|
|
}
|
|
|
|
static long MUC_OpenDialConnection( void* )
|
|
{
|
|
return OpenFreePPP();
|
|
}
|
|
|
|
static long MUC_CloseDialConnection( void* )
|
|
{
|
|
return CloseFreePPP();
|
|
}
|
|
|
|
static long MUC_GetActiveDialConfiguration( Str255* pppConfig )
|
|
{
|
|
GetCurrentAccountName( pppConfig );
|
|
return noErr;
|
|
}
|
|
|
|
static long MUC_SetActiveDialConfiguration( Str255* pppConfig )
|
|
{
|
|
return SetCurrentAccountName( pppConfig );
|
|
}
|
|
|
|
static long MUC_GetActiveOTConfiguration( Str255* otConfig )
|
|
{
|
|
return noErr;
|
|
}
|
|
|
|
static long MUC_SetActiveOTConfiguration( Str255* otConfig )
|
|
{
|
|
long err;
|
|
OTChangeConfigPB pb;
|
|
Handle resource;
|
|
OTConfigProcUPP thing;
|
|
|
|
// ¥ this is our safe FAT resource (an 'sdes')
|
|
resource = ::Get1Resource( 'COTC', 128 );
|
|
|
|
if ( !resource )
|
|
return errCantLoadNeededResources;
|
|
|
|
DetachResource( resource );
|
|
HLock( resource );
|
|
|
|
pb.selector = kOTChangeSelector_CheckChange;
|
|
LString::CopyPStr( (unsigned char*)&pb.configurationName, (unsigned char*)otConfig );
|
|
thing = (OTConfigProcUPP)*resource;
|
|
err = CallOTConfigProc( thing, &pb );
|
|
if ( err == noErr )
|
|
{
|
|
// ¥Êassume it's benign to go bitch-slap OT
|
|
pb.selector = kOTChangeSelector_Reconfigure;
|
|
err = CallOTConfigProc( thing, &pb );
|
|
}
|
|
else if ( err == kOTErr_OTConfigurationNotPresent )
|
|
{
|
|
// ¥ fill in the OTChangeConfigPB with the rest of the relevant stuff from
|
|
// the AccountSpecDef, and call back into the code resource to create it
|
|
}
|
|
|
|
DisposeHandle( resource ); // Get rid of the OT reconfig glue
|
|
|
|
return err;
|
|
|
|
}
|
|
|
|
static long MUC_GetDialConnectionState( Boolean* connected )
|
|
{
|
|
*connected = IsFreePPPOpen();
|
|
return noErr;
|
|
}
|
|
|
|
static long MUC_GetAutoConnectState( Boolean* allowsAutoConnect )
|
|
{
|
|
*allowsAutoConnect = GetAutoConnectState();
|
|
return noErr;
|
|
}
|
|
|
|
static long MUC_SetAutoConnectState( Boolean* allowsAutoConnect )
|
|
{
|
|
return SetAutoConnectState( *allowsAutoConnect );
|
|
}
|
|
|
|
static long MUC_GetModemsList( Str255** modemsList )
|
|
{
|
|
return GetModemsList( modemsList );
|
|
}
|
|
|
|
static long MUC_GetActiveModemName( Str255* modemName )
|
|
{
|
|
GetCurrentModemName( modemName );
|
|
return noErr;
|
|
}
|
|
|
|
static long MUC_GetReceivedIPPacketCount( unsigned long* packetCount )
|
|
{
|
|
return GetReceivedIPPacketCount( packetCount );
|
|
}
|
|
|
|
static OSErr InitConfigStrList( ConfigStringArray configStrList, PPPConfigureStruct* data,
|
|
Boolean* configureTCP, Boolean* configureIC )
|
|
{
|
|
Str255 empty="\p";
|
|
long dns1 = 0;
|
|
long dns2 = 0; // Used to avoid duplicate DNS settings
|
|
|
|
int i;
|
|
|
|
if ( ( configStrList == NULL ) || ( data == NULL ) )
|
|
return fnfErr;
|
|
|
|
*configureTCP = false;
|
|
*configureIC = false;
|
|
|
|
// Initialize the data
|
|
for ( i = 0; i < eNumConfigStrings; i++ )
|
|
LString::CopyPStr( empty, configStrList[ i ] );
|
|
AddressToString( 0UL, configStrList[ eDNSAddress ] ); // These need to be initialized to 0.0.0.0
|
|
AddressToString( 0UL, configStrList[ eAltDNSAddress ] ); // These need to be initialized to 0.0.0.0
|
|
AddressToString( 0UL, configStrList[ eBackupDNSAddress ] ); // These need to be initialized to 0.0.0.0
|
|
|
|
i = 0;
|
|
while ( data[ i ].id != 0 )
|
|
{
|
|
switch ( data[ i ].id )
|
|
{
|
|
// TCP prefs
|
|
case kAccountID:
|
|
DebugNumStr( "\pAccountID", data[ i ].value );
|
|
LString::CopyPStr( (unsigned char*)data[ i ].value, configStrList[ eSiteName ] );
|
|
break;
|
|
|
|
case kAsearchDomain:
|
|
DebugNumStr( "\p kAsearchDomain", data[ i ].value );
|
|
LString::CopyPStr( (unsigned char*)data[ i ].value, configStrList[ eDomainName ] );
|
|
*configureTCP = true;
|
|
break;
|
|
|
|
case kAprimaryDNS:
|
|
DebugNumStr( "\p kAprimaryDNS", data[ i ].value );
|
|
dns1 = (long)data[ i ].value;
|
|
AddressToString( (unsigned long)data[ i ].value, configStrList[ eDNSAddress ] );
|
|
*configureTCP = true;
|
|
break;
|
|
|
|
case kAsecondaryDNS:
|
|
dns2 = (long)data[ i ].value;
|
|
if ( (long)data[ i ].value == dns1 ) // Avoid the DNS duplicates
|
|
AddressToString( 0UL, configStrList[ eAltDNSAddress ] );
|
|
else
|
|
AddressToString( (unsigned long)data[ i ].value, configStrList[ eAltDNSAddress ] );
|
|
*configureTCP = true;
|
|
break;
|
|
|
|
case kAbackupDNS:
|
|
DebugNumStr( "\p kAbackupDNS", data[ i ].value );
|
|
if ( ( (long)data[ i ].value == dns1 ) || ( (long)data[ i ].value == dns2 ) )
|
|
AddressToString( 0UL, configStrList[ eBackupDNSAddress ] );
|
|
else
|
|
AddressToString( (unsigned long)data[ i ].value, configStrList[ eBackupDNSAddress ] );
|
|
*configureTCP = true;
|
|
break;
|
|
|
|
// IC prefs
|
|
case kConfigPluginLogin:
|
|
DebugNumStr( "\p kConfigPluginLogin", data[ i ].value );
|
|
LString::CopyPStr( (unsigned char*)data[ i ].value, configStrList[ eUserLogin ] );
|
|
*configureIC = true;
|
|
break;
|
|
case kConfigPluginPassword:
|
|
DebugNumStr( "\p kConfigPluginPassword", data[ i ].value );
|
|
LString::CopyPStr( (unsigned char*)data[ i ].value, configStrList[ eUserPassword ] );
|
|
*configureIC = true;
|
|
break;
|
|
case kConfigPluginPopLogin:
|
|
DebugNumStr( "\p kConfigPluginPopLogin", data[ i ].value );
|
|
LString::CopyPStr( (unsigned char*)data[ i ].value, configStrList[ eEMailLogin ] );
|
|
*configureIC = true;
|
|
break;
|
|
case kConfigPluginPopPassword:
|
|
DebugNumStr( "\p kConfigPluginPopPassword", data[ i ].value);
|
|
LString::CopyPStr( (unsigned char*)data[ i ].value, configStrList[ eEMailPassword ] );
|
|
*configureIC = true;
|
|
break;
|
|
case kConfigPluginReturnAddress:
|
|
DebugNumStr( "\p kConfigPluginReturnAddress", data[ i ].value );
|
|
LString::CopyPStr( (unsigned char*)data[ i ].value, configStrList[ eEMailReturnAddress ] );
|
|
*configureIC = true;
|
|
break;
|
|
case kConfigPluginPopServer:
|
|
DebugNumStr( "\p kConfigPluginPopServer", data[ i ].value );
|
|
LString::CopyPStr( (unsigned char*)data[ i ].value, configStrList[ eEMailPOPServer ] );
|
|
*configureIC = true;
|
|
break;
|
|
case kConfigPluginNNTPHost:
|
|
DebugNumStr( "\p kConfigPluginNNTPHost", data[ i ].value );
|
|
LString::CopyPStr( (unsigned char*)data[ i ].value, configStrList[ eNNTPHost ] );
|
|
*configureIC = true;
|
|
break;
|
|
case kConfigPluginSMTPHost:
|
|
DebugNumStr( "\p kConfigPluginSMTPHost", data[ i ].value );
|
|
LString::CopyPStr( (unsigned char*)data[ i ].value, configStrList[ eSMTPHost ] );
|
|
*configureIC = true;
|
|
break;
|
|
default:
|
|
DebugNumStr("\p Dunno", data[i].value);
|
|
// It is OK, we ignore the unknown prefss
|
|
break;
|
|
}
|
|
i++;
|
|
}
|
|
|
|
return noErr;
|
|
}
|
|
|
|
void AddressToString( unsigned long address, StringPtr string )
|
|
{
|
|
Str255 aString;
|
|
unsigned char net;
|
|
unsigned char subnet1;
|
|
unsigned char subnet2;
|
|
unsigned char node;
|
|
|
|
string[ 0 ] = 0;
|
|
|
|
net = ( address & 0xff000000 ) >> 24;
|
|
subnet1 = ( address & 0x00ff0000 ) >> 16;
|
|
subnet2 = ( address & 0x0000ff00 ) >> 8;
|
|
node = address & 0x000000ff;
|
|
|
|
NumToString( (long)net, aString );
|
|
LString::CopyPStr( aString, string );
|
|
|
|
LString::AppendPStr( string,"\p." );
|
|
|
|
NumToString( (long)subnet1, aString);
|
|
LString::AppendPStr( string, aString );
|
|
LString::AppendPStr( string, "\p." );
|
|
|
|
NumToString( (long)subnet2, aString );
|
|
LString::AppendPStr( string, aString );
|
|
LString::AppendPStr( string, "\p." );
|
|
|
|
NumToString( (long)node, aString );
|
|
LString::AppendPStr( string, aString );
|
|
}
|
|
|
|
unsigned long AddressToLong( StringPtr addressStr )
|
|
{
|
|
unsigned long address = 0;
|
|
long offset = 1;
|
|
long i;
|
|
long count;
|
|
unsigned char buffer[ 5 ];
|
|
long addressLen = addressStr[ 0 ];
|
|
|
|
long shiftValue = 24;
|
|
|
|
for ( count = 0; count < 4; count++ )
|
|
{
|
|
buffer[ 0 ] = 0;
|
|
for ( i = 1; i < 4 ; i++, offset++ )
|
|
{
|
|
if ( offset > addressLen )
|
|
break;
|
|
|
|
if ( addressStr[ offset ] == '.' )
|
|
break;
|
|
|
|
buffer[ i ] = addressStr[ offset ] ;
|
|
buffer[ 0 ] += 1;
|
|
}
|
|
buffer[ i ] = 0;
|
|
offset++;
|
|
|
|
::StringToNum( (StringPtr)buffer, &i );
|
|
address |= (unsigned char)i << shiftValue;
|
|
shiftValue -= 8;
|
|
}
|
|
|
|
return address;
|
|
}
|
|
|
|
static Boolean OTAvailable()
|
|
{
|
|
// Does system have OpenTransport TCP?
|
|
OSErr error;
|
|
long response;
|
|
|
|
// Check for Open Transport.
|
|
// gestaltOpenTpt = 'otan'
|
|
// gestaltOpenTptPresent = 0x00000001
|
|
// gestaltOpenTptTCPPresent = 0x00000010
|
|
error = Gestalt( gestaltOpenTpt, &response);
|
|
if ( !error )
|
|
return ( ( response & 0x00000011 ) ? true : false );
|
|
else
|
|
return false;
|
|
}
|
|
|
|
|
|
|