/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- * * The contents of this file are subject to the Mozilla 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/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 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): */ //#define VC_EXTRALEAN // Exclude rarely-used stuff from Windows headers #include // MFC core and standard components #include // MFC extensions #include #include #include #include #include #include #include #include #include #include #include #include #include #include "dialshr.h" #include "resource.h" #include "xp_mem.h" #include "prefapi.h" #define trace #define MAX_ENTRIES 20 // Navigator quit message (see QuitNavigator) #define ID_APP_SUPER_EXIT 34593 // The number of times we try to dial #define NUM_ATTEMPTS 3 #define IDDISCONNECTED 31 enum CallState { StateIdle, StateConnecting, StateConnected, StateDisconnecting }; CallState gCallState = StateIdle; UINT gDialAttempts = 0; // keeps the total number of dialing count HRASCONN gRasConn; // handle to the current ras connection RASCONNSTATE gRASstate; // current connection's ras state RASDIALPARAMS gDialParams; // keeps the current connection info HWND gHwndStatus = NULL; // handle to our connection status window BOOL gCancelled = FALSE; // assume connection will be there unless user cancels BOOL gLineDrop = FALSE; BOOL gDeviceErr = FALSE; // assume no hardware err HWND gHwndNavigator = NULL; HANDLE gRasMon = NULL; // process handle to RasMon on WinNT HINSTANCE m_hRasInst = NULL; // NT/95 entrypoints RASDIAL m_lpfnRasDial; RASHANGUP m_lpfnRasHangUp; RASGETERRORSTRING m_lpfnRasGetErrorString; RASSETENTRYPROPERTIES m_lpfnRasSetEntryProperties; RASSETENTRYDIALPARAMS m_lpfnRasSetEntryDialParams; RASGETCOUNTRYINFO m_lpfnRasGetCountryInfo; RASENUMCONNECTIONS m_lpfnRasEnumConnections; RASENUMENTRIES m_lpfnRasEnumEntries; RASENUMDEVICES m_lpfnRasEnumDevices; RASGETENTRYPROPERTIES m_lpfnRasGetEntryProperties; RASVALIDATEENTRYNAME m_lpfnRasValidateEntryName; RASDELETEENTRY m_lpfnRasDeleteEntry; // NT entrypoints RASSETAUTODIALENABLE m_lpfnRasSetAutodialEnable; RASSETAUTODIALADDRESS m_lpfnRasSetAutodialAddress; RASGETAUTODIALADDRESS m_lpfnRasGetAutodialAddress; RASSETAUTODIALPARAM m_lpfnRasSetAutodialParam; RASENUMAUTODIALADDRESSES m_lpfnRasEnumAutodialAddresses; RASSETCREDENTIALS m_lpfnRasSetCredentials; size_t stRASENTRY; size_t stRASCONN; size_t stRASCTRYINFO; size_t stRASDIALPARAMS; size_t stRASDEVINFO; size_t stRASENTRYNAME; //******************************************************************************** // LoadRasFunctions() //******************************************************************************** BOOL LoadRasFunctions( LPCSTR lpszLibrary ) { // ASSERT(!m_hRasInst); m_hRasInst = ::LoadLibrary( lpszLibrary ); if ( (UINT)m_hRasInst > 32 ) { m_lpfnRasSetEntryProperties = (RASSETENTRYPROPERTIES)::GetProcAddress( m_hRasInst, "RasSetEntryProperties" ); m_lpfnRasGetCountryInfo = (RASGETCOUNTRYINFO)::GetProcAddress( m_hRasInst, "RasGetCountryInfo" ); m_lpfnRasEnumDevices = (RASENUMDEVICES)::GetProcAddress( m_hRasInst, "RasEnumDevices" ); m_lpfnRasGetEntryProperties = (RASGETENTRYPROPERTIES)::GetProcAddress( m_hRasInst, "RasGetEntryProperties"); m_lpfnRasValidateEntryName = (RASVALIDATEENTRYNAME)::GetProcAddress( m_hRasInst,"RasValidateEntryName" ); m_lpfnRasDeleteEntry = (RASDELETEENTRY)::GetProcAddress( m_hRasInst, "RasDeleteEntry" ); m_lpfnRasHangUp = (RASHANGUP)::GetProcAddress( m_hRasInst, "RasHangUpA" ); m_lpfnRasDial = (RASDIAL)::GetProcAddress( m_hRasInst, "RasDialA" ); m_lpfnRasEnumConnections = (RASENUMCONNECTIONS)::GetProcAddress( m_hRasInst, "RasEnumConnectionsA" ); m_lpfnRasSetEntryDialParams = (RASSETENTRYDIALPARAMS)::GetProcAddress( m_hRasInst, "RasSetEntryDialParamsA" ); m_lpfnRasEnumEntries = (RASENUMENTRIES)::GetProcAddress( m_hRasInst, "RasEnumEntriesA" ); SizeofRAS95(); return TRUE; } else { MessageBox( NULL, "Please install Dial-up Networking", "Netscape", MB_ICONSTOP ); ::FreeLibrary( m_hRasInst ); m_hRasInst = NULL; return FALSE; } } //******************************************************************************** // LoadRasFunctionsNT() //******************************************************************************** BOOL LoadRasFunctionsNT( LPCSTR lpszLibrary ) { m_hRasInst = ::LoadLibrary( lpszLibrary ); if ( (UINT)m_hRasInst > 32 ) { m_lpfnRasSetEntryProperties = (RASSETENTRYPROPERTIES)::GetProcAddress( m_hRasInst, "RasSetEntryPropertiesA" ); m_lpfnRasGetCountryInfo = (RASGETCOUNTRYINFO)::GetProcAddress( m_hRasInst, "RasGetCountryInfoA" ); m_lpfnRasEnumDevices = (RASENUMDEVICES)::GetProcAddress( m_hRasInst, "RasEnumDevicesA" ); m_lpfnRasGetEntryProperties = (RASGETENTRYPROPERTIES)::GetProcAddress( m_hRasInst, "RasGetEntryPropertiesA" ); m_lpfnRasValidateEntryName = (RASVALIDATEENTRYNAME)::GetProcAddress( m_hRasInst, "RasValidateEntryNameA" ); m_lpfnRasDeleteEntry = (RASDELETEENTRY)::GetProcAddress( m_hRasInst, "RasDeleteEntryA" ); m_lpfnRasEnumEntries = (RASENUMENTRIES)::GetProcAddress( m_hRasInst, "RasEnumEntriesA" ); m_lpfnRasHangUp = (RASHANGUP)::GetProcAddress( m_hRasInst, "RasHangUpA" ); m_lpfnRasDial = (RASDIAL)::GetProcAddress( m_hRasInst, "RasDialA" ); m_lpfnRasEnumConnections = (RASENUMCONNECTIONS)::GetProcAddress( m_hRasInst, "RasEnumConnectionsA" ); m_lpfnRasSetEntryDialParams = (RASSETENTRYDIALPARAMS)::GetProcAddress(m_hRasInst, "RasSetEntryDialParamsA" ); // AUTODIAL m_lpfnRasSetAutodialEnable = (RASSETAUTODIALENABLE)::GetProcAddress( m_hRasInst, "RasSetAutodialEnableA" ); m_lpfnRasSetAutodialAddress = (RASSETAUTODIALADDRESS)::GetProcAddress( m_hRasInst, "RasSetAutodialAddressA" ); m_lpfnRasGetAutodialAddress = (RASGETAUTODIALADDRESS)::GetProcAddress( m_hRasInst, "RasGetAutodialAddressA" ); m_lpfnRasSetAutodialParam = (RASSETAUTODIALPARAM)::GetProcAddress( m_hRasInst, "RasSetAutodialParamA" ); m_lpfnRasSetCredentials = (RASSETCREDENTIALS)::GetProcAddress( m_hRasInst, "RasSetCredentialsA" ); m_lpfnRasEnumAutodialAddresses = (RASENUMAUTODIALADDRESSES)::GetProcAddress( m_hRasInst, "RasEnumAutodialAddressesA" ); SizeofRASNT40(); return TRUE; } else { MessageBox( NULL, "Please install Dial-up Networking", "Netscape", MB_ICONSTOP ); ::FreeLibrary( m_hRasInst ); m_hRasInst = NULL; return FALSE; } } //******************************************************************************** // FreeRasFunctions() //******************************************************************************** void FreeRasFunctions() { if ( (UINT)m_hRasInst > 32 ) FreeLibrary( m_hRasInst ); } //******************************************************************************** // GetModemList (s/b GetModems) // Returns list of modems available for use ('installed' by the user). For Win95 // this list come from the OS, and each entry contains 2 strings - the first is // the Modem Name, and the second is the device type (both are needed to select // the device to use to make a Dial-up connection). //******************************************************************************** BOOL GetModemList( char*** resultModemList, int* numDevices ) { DWORD dwBytes = 0, dwDevices; LPRASDEVINFO lpRnaDevInfo; // First find out how much memory to allocate (*m_lpfnRasEnumDevices)( NULL, &dwBytes, &dwDevices ); lpRnaDevInfo = (LPRASDEVINFO)malloc( dwBytes ); if ( !lpRnaDevInfo ) return (FALSE); lpRnaDevInfo->dwSize = stRASDEVINFO; (*m_lpfnRasEnumDevices)( lpRnaDevInfo, &dwBytes, &dwDevices ); // copy all entries to the char array *resultModemList = new char* [dwDevices+1]; if ( *resultModemList == NULL ) return FALSE; *numDevices = dwDevices; for ( unsigned short i=0; i < dwDevices; i++ ) { (*resultModemList)[i] = new char[ strlen( lpRnaDevInfo[ i ].szDeviceName) + 1 ]; if ( ( *resultModemList)[ i ] == NULL ) return FALSE; strcpy( ( *resultModemList)[ i ], lpRnaDevInfo[ i ].szDeviceName ); } return TRUE; } //******************************************************************************** // GetModemType // Returns the type for the selected modem. //******************************************************************************** BOOL GetModemType( char *strModemName, char *strModemType) { DWORD dwBytes = 0, dwDevices; LPRASDEVINFO lpRnaDevInfo; // First get Modem (okay - Device) info from Win95 // find out how much memory to allocate (*m_lpfnRasEnumDevices)( NULL, &dwBytes, &dwDevices ); lpRnaDevInfo = (LPRASDEVINFO)malloc( dwBytes ); if ( !lpRnaDevInfo ) return NULL; lpRnaDevInfo->dwSize = stRASDEVINFO; (*m_lpfnRasEnumDevices)( lpRnaDevInfo, &dwBytes, &dwDevices ); // If match the modem given from JS then return the associated Type for ( unsigned short i = 0; i < dwDevices; i++ ) { if ( 0 == strcmp(strModemName, lpRnaDevInfo[i].szDeviceName ) ) { strModemType = new char[ strlen( lpRnaDevInfo[ i ].szDeviceType ) + 1 ]; strcpy( strModemType, lpRnaDevInfo[ i ].szDeviceType ); return TRUE; } } return FALSE; } //******************************************************************************** // EnableDialOnDemand (win95) // Set the magic keys in the registry to enable dial on demand //******************************************************************************** void EnableDialOnDemand95( LPSTR lpProfileName, BOOL flag ) { HKEY hKey; DWORD dwDisposition; long result; char* szData; // We need to tell windows about dialing on demand result = RegCreateKeyEx( HKEY_LOCAL_MACHINE, "System\\CurrentControlSet\\Services\\Winsock\\Autodial", NULL, NULL, NULL, KEY_ALL_ACCESS, NULL, &hKey, &dwDisposition ); // err, oops if ( result != ERROR_SUCCESS ) return; szData = "url.dll"; result = RegSetValueEx( hKey, "AutodialDllName32", NULL, REG_SZ, (LPBYTE)szData, strlen( szData ) ); szData = "AutodialHookCallback"; result = RegSetValueEx( hKey, "AutodialFcnName32", NULL, REG_SZ, (LPBYTE)szData, strlen( szData ) ); RegCloseKey( hKey ); // set the autodial flag first result = RegCreateKeyEx( HKEY_CURRENT_USER, "Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings", NULL, NULL, NULL, KEY_ALL_ACCESS, NULL, &hKey, &dwDisposition ); // err, oops if ( result != ERROR_SUCCESS ) return; // set the autodial and idle-time disconnect DWORD dwValue = flag; result = RegSetValueEx( hKey, "EnableAutodial", NULL, REG_DWORD, (LPBYTE)&dwValue, sizeof( DWORD ) ); // try setting autodisconnect here dwValue = 1; result = RegSetValueEx( hKey, "EnableAutoDisconnect", NULL, REG_DWORD, (LPBYTE)&dwValue, sizeof( DWORD ) ); // default auto-disconnect after 5 minutes dwValue = 5; result = RegSetValueEx( hKey, "DisconnectIdleTime", NULL, REG_DWORD, (LPBYTE)&dwValue, sizeof( DWORD ) ); RegCloseKey( hKey ); // set the autodisconnect flags here too result = RegCreateKeyEx( HKEY_CURRENT_USER, "Software\\Microsoft\\Windows\\Internet Settings", NULL, NULL, NULL, KEY_ALL_ACCESS, NULL, &hKey, &dwDisposition ); // err, oops if ( result != ERROR_SUCCESS ) return; dwValue = 1; result = RegSetValueEx( hKey, "EnableAutoDisconnect", NULL, REG_DWORD, (LPBYTE)&dwValue, sizeof( DWORD ) ); // default auto-disconnect after 5 minutes dwValue = 5; result = RegSetValueEx( hKey, "DisconnectIdleTime", NULL, REG_DWORD, (LPBYTE)&dwValue, sizeof( DWORD ) ); RegCloseKey( hKey ); // OK, let's tell it which profile to autodial result = RegCreateKeyEx( HKEY_CURRENT_USER, "RemoteAccess", NULL, NULL, NULL, KEY_ALL_ACCESS, NULL, &hKey, &dwDisposition ); // err, oops if ( result != ERROR_SUCCESS ) return; if ( flag ) // enable dod { result = RegSetValueEx( hKey, "InternetProfile", NULL, REG_SZ, (LPBYTE)lpProfileName, strlen( lpProfileName ) ); result = RegSetValueEx( hKey, "Default", NULL, REG_SZ, (LPBYTE)lpProfileName, strlen( lpProfileName ) ); } else // disable dod { result = RegSetValueEx( hKey, "InternetProfile", NULL, REG_SZ, NULL, strlen( lpProfileName ) ); result = RegSetValueEx( hKey, "Default", NULL, REG_SZ, NULL, strlen( lpProfileName ) ); } RegCloseKey( hKey ); } //******************************************************************************** // // lineCallbackFuncNT (winNT40) // // Sets the RAS structure for Dial on Demand, NT40 doesn't use registry like win95 //******************************************************************************** void FAR PASCAL lineCallbackFuncNT(DWORD /* hDevice */, DWORD /* dwMsg */, DWORD /* dwCallbackInstance */, DWORD /* dwParam1 */, DWORD /* dwParam2 */, DWORD /* dwParam3 */) { } void EnableDialOnDemandNT(LPSTR lpProfileName, BOOL flag) { RASAUTODIALENTRY rasAutodialEntry; DWORD dwBytes = 0; DWORD dwNumDevs; HLINEAPP lineApp; DWORD dwApiVersion; LINEINITIALIZEEXPARAMS lineInitExParams; LINETRANSLATECAPS lineTranslateCaps; int rtn; // Initialize TAPI. We need to do this in order to get the dialable // number and to bring up the location dialog dwApiVersion = 0x00020000; lineInitExParams.dwOptions = LINEINITIALIZEEXOPTION_USEEVENT; lineInitExParams.dwTotalSize = sizeof( LINEINITIALIZEEXPARAMS ); lineInitExParams.dwNeededSize = sizeof (LINEINITIALIZEEXPARAMS ); rtn = lineInitializeEx( &lineApp, gDLL, lineCallbackFuncNT, NULL, &dwNumDevs, &dwApiVersion, &lineInitExParams ); if ( rtn == 0) { lineTranslateCaps.dwTotalSize = sizeof( LINETRANSLATECAPS ); lineTranslateCaps.dwNeededSize = sizeof( LINETRANSLATECAPS ); rtn = lineGetTranslateCaps( lineApp, dwApiVersion, &lineTranslateCaps ); } rasAutodialEntry.dwFlags = 0; rasAutodialEntry.dwDialingLocation = lineTranslateCaps.dwCurrentLocationID; strcpy( rasAutodialEntry.szEntry, lpProfileName ); rasAutodialEntry.dwSize = sizeof( RASAUTODIALENTRY ); // set auto dial params int val = flag; rtn = ( *m_lpfnRasSetAutodialParam )( RASADP_DisableConnectionQuery, &val, sizeof( int ) ); if ( rtn == ERROR_INVALID_PARAMETER ) { trace( "dialer.cpp : EnableDialOnDemandNT - Invalid Parameter. Can't set Autodial Parameters. (r)" ); return; } else if ( rtn == ERROR_INVALID_SIZE ) { trace( "dialer.cpp : EnableDialOnDemandNT - Invalid size. Can't set Autodial Parameters. (r)" ); return; } else if ( rtn ) { trace( "dialer.cpp : EnableDialOnDemandNT - Can't set Autodial Parameters. Error %d. (r)", rtn ); return; } if ( flag ) // set dod entry if the flag is enabled { rtn = ( *m_lpfnRasSetAutodialAddress )( "www.netscape.com", 0, &rasAutodialEntry, sizeof(RASAUTODIALENTRY), 1); if ( rtn == ERROR_INVALID_PARAMETER ) { trace( "dialer.cpp : EnableDialOnDemandNT - Invalid Parameter. Can't set Autodial Address. (r)" ); return; } else if ( rtn == ERROR_INVALID_SIZE ) { trace( "dialer.cpp : EnableDialOnDemandNT - Invalid size. Can't set Autodial Address. (r)" ); return; } else if ( rtn ) { trace( "dialer.cpp : EnableDialOnDemandNT - Can't set Autodial Address. Error %d. (r)", rtn ); return; } } rtn = ( *m_lpfnRasSetAutodialEnable )( rasAutodialEntry.dwDialingLocation, flag ); if ( rtn ) { trace( "dialer.cpp : EnableDialOnDemandNT - Can't set Autodial Enable. Error %d. (r)", rtn ); return; } return; } //******************************************************************************** // utility function // sameStrings // checks for string equality between a STRRET and a LPCTSTR //******************************************************************************** static BOOL sameStrings( LPITEMIDLIST pidl, STRRET& lpStr1, LPCTSTR lpStr2 ) { char buf[ MAX_PATH ]; char* mystr; int cch; switch ( lpStr1.uType ) { case STRRET_WSTR: cch = WideCharToMultiByte( CP_ACP, WC_SEPCHARS | WC_COMPOSITECHECK, lpStr1.pOleStr, -1, buf, MAX_PATH, NULL, NULL ); cch = GetLastError(); return strcmp( lpStr2, buf ) == 0; case STRRET_OFFSET: mystr = ((char*)pidl) + lpStr1.uOffset; return strcmp( lpStr2, ((char*)pidl) + lpStr1.uOffset ) == 0; case STRRET_CSTR: mystr = lpStr1.cStr; return strcmp( lpStr2, lpStr1.cStr ) == 0; } return FALSE; } //******************************************************************************** // utility function // procStrings //******************************************************************************** static BOOL procStrings( LPITEMIDLIST pidl, STRRET& lpStr1, char* lpStr2 ) { char* mystr; int cch; switch ( lpStr1.uType ) { case STRRET_WSTR: cch = WideCharToMultiByte( CP_ACP, WC_SEPCHARS | WC_COMPOSITECHECK, lpStr1.pOleStr, -1, lpStr2, MAX_PATH, NULL, NULL ); return TRUE; case STRRET_OFFSET: mystr = ((char*)pidl) + lpStr1.uOffset; strcpy( lpStr2, ((char*)pidl) + lpStr1.uOffset ); return TRUE; case STRRET_CSTR: mystr = lpStr1.cStr; strcpy( lpStr2, lpStr1.cStr ); return TRUE; } return FALSE; } //******************************************************************************** // utility function // next //******************************************************************************** static LPITEMIDLIST next( LPCITEMIDLIST pidl ) { LPSTR lpMem=(LPSTR)pidl; lpMem += pidl->mkid.cb; return (LPITEMIDLIST)lpMem; } //******************************************************************************** // utility function // getSize //******************************************************************************** static UINT getSize(LPCITEMIDLIST pidl) { UINT cbTotal = 0; if ( pidl ) { cbTotal += sizeof( pidl->mkid.cb ); while ( pidl->mkid.cb ) { cbTotal += pidl->mkid.cb; pidl = next( pidl ); } } return cbTotal; } //******************************************************************************** // utility function // create //******************************************************************************** static LPITEMIDLIST create( UINT cbSize ) { IMalloc* pMalloc; LPITEMIDLIST pidl = 0; if ( FAILED( SHGetMalloc( &pMalloc ) ) ) return 0; pidl = (LPITEMIDLIST)pMalloc->Alloc( cbSize ); if ( pidl ) memset( pidl, 0, cbSize ); pMalloc->Release(); return pidl; } //******************************************************************************** // utility function // ConcatPidls //******************************************************************************** static LPITEMIDLIST concatPidls( LPCITEMIDLIST pidl1, LPCITEMIDLIST pidl2 ) { UINT cb1 = getSize( pidl1 ) - sizeof( pidl1->mkid.cb ); UINT cb2 = getSize( pidl2 ); LPITEMIDLIST pidlNew = create( cb1 + cb2 ); if ( pidlNew ) { memcpy( pidlNew, pidl1, cb1 ); memcpy( ((LPSTR)pidlNew ) + cb1, pidl2, cb2 ); } return pidlNew; } //******************************************************************************** // GetMyComputerFolder // This routine returns the ISHellFolder for the virtual My Computer folder, // and also returns the PIDL. //******************************************************************************** HRESULT GetMyComputerFolder( LPSHELLFOLDER* ppshf, LPITEMIDLIST* ppidl ) { IMalloc* pMalloc; HRESULT hres; hres = SHGetMalloc( &pMalloc ); if ( FAILED( hres ) ) return hres; // Get the PIDL for "My Computer" hres = SHGetSpecialFolderLocation( /*pWndOwner->m_hWnd*/NULL, CSIDL_DRIVES, ppidl ); if ( SUCCEEDED( hres ) ) { IShellFolder* pshf; hres = SHGetDesktopFolder( &pshf ); if ( SUCCEEDED( hres ) ) { // Get the shell folder for "My Computer" hres = pshf->BindToObject( *ppidl, NULL, IID_IShellFolder, (LPVOID *)ppshf ); pshf->Release(); } } pMalloc->Release(); return hres; } //******************************************************************************** // GetDialupNetworkingFolder // This routine returns the ISHellFolder for the virtual Dial-up Networking // folder, and also returns the PIDL. //******************************************************************************** static HRESULT getDialUpNetworkingFolder(LPSHELLFOLDER *ppshf, LPITEMIDLIST *ppidl) { HRESULT hres; IMalloc* pMalloc = NULL; IShellFolder* pmcf = NULL; LPITEMIDLIST pidlmc; char szDialupName[ 256 ]; HKEY hKey; DWORD cbData; // Poke around in the registry to find out what the Dial-Up Networking // folder is called on this machine szDialupName[ 0 ] = '\0'; if ( ERROR_SUCCESS == RegOpenKeyEx(HKEY_CLASSES_ROOT, "CLSID\\{992CFFA0-F557-101A-88EC-00DD010CCC48}", NULL, KEY_QUERY_VALUE, &hKey ) ) { cbData = sizeof( szDialupName ); RegQueryValueEx( hKey, "", NULL, NULL, (LPBYTE)szDialupName, &cbData ); } // if we didn't get anything just use the default if( szDialupName[ 0 ] == '\0' ) { char* strText; strText = "Dial-Up Networking"; //CString strText; //strText.LoadString(IDS_DIAL_UP_NW); strcpy( szDialupName, (LPCSTR)strText ); } RegCloseKey( hKey ); // OK, now look for that folder hres = SHGetMalloc( &pMalloc ); if ( FAILED( hres ) ) return hres; // Get the virtual folder for My Computer hres = GetMyComputerFolder( &pmcf, &pidlmc ); if ( SUCCEEDED( hres ) ) { IEnumIDList* pEnumIDList; // Now we need to find the "Dial-Up Networking" folder hres = pmcf->EnumObjects( NULL, SHCONTF_FOLDERS | SHCONTF_NONFOLDERS, &pEnumIDList ); if ( SUCCEEDED( hres ) ) { LPITEMIDLIST pidl; int flag = 1; STRRET name; while ( ( NOERROR == ( hres = pEnumIDList->Next( 1, &pidl, NULL ) ) ) && ( flag ) ) { memset( &name, 0, sizeof( STRRET ) ); name.uType = STRRET_CSTR; // preferred choice hres = pmcf->GetDisplayNameOf( pidl, SHGDN_INFOLDER, &name ); if ( FAILED( hres ) ) { pMalloc->Free( pidl ); flag = 0; //break; } if ( sameStrings( pidl, name, szDialupName ) ) { *ppidl = concatPidls(pidlmc, pidl); hres = pmcf->BindToObject( pidl, NULL, IID_IShellFolder, (LPVOID*)ppshf ); int rtn = GetLastError(); pMalloc->Free( pidl ); flag = 0; //break; } if ( flag ) pMalloc->Free( pidl ); } pEnumIDList->Release(); } pmcf->Release(); pMalloc->Free( pidlmc ); } pMalloc->Release(); return hres; } //******************************************************************************** // GetDialUpConnection //******************************************************************************** BOOL GetDialUpConnection95( CONNECTIONPARAMS** connectionNames, int* numNames ) { HRESULT hres; IMalloc* pMalloc = NULL; IShellFolder* pshf = NULL; LPITEMIDLIST pidldun; LPITEMIDLIST pidl; STRRET name; char temp[ MAX_PATH ]; int flag = 1; int i =0; // Initialize out parameter hres = SHGetMalloc( &pMalloc ); if ( FAILED( hres ) ) return FALSE; // First get the Dial-Up Networking virtual folder hres = getDialUpNetworkingFolder( &pshf, &pidldun ); if ( SUCCEEDED( hres ) && ( pshf != NULL ) ) { IEnumIDList* pEnumIDList; // Enumerate the files looking for the desired connection hres = pshf->EnumObjects( NULL, SHCONTF_FOLDERS | SHCONTF_NONFOLDERS, &pEnumIDList ); if ( SUCCEEDED( hres ) ) { *numNames = 0; while ( NOERROR == ( hres = pEnumIDList->Next( 1, &pidl, NULL ) ) ) (*numNames)++; pEnumIDList->Reset(); *connectionNames = new CONNECTIONPARAMS[ *numNames ]; if( *connectionNames == NULL ) return FALSE; while ( ( NOERROR == ( hres = pEnumIDList->Next( 1, &pidl, NULL ) ) ) && ( flag ) ) { name.uType = STRRET_CSTR; // preferred choice hres = pshf->GetDisplayNameOf( pidl, SHGDN_INFOLDER, &name ); if ( FAILED( hres ) ) { pMalloc->Free( pidl ); flag = 0; //break; } procStrings( pidl, name, temp ); if( strcmp( temp, "Make New Connection" ) !=0 ) { strcpy( (*connectionNames)[ i ].szEntryName, temp ); (*connectionNames)[ i ].pidl = concatPidls( pidldun, pidl ); i++; } if ( flag ) pMalloc->Free( pidl ); } pEnumIDList->Release(); } pshf->Release(); pMalloc->Free( pidldun ); } pMalloc->Release(); *numNames = i; return TRUE; } //******************************************************************************** // GetDialUpConnection //******************************************************************************** BOOL GetDialUpConnectionNT( CONNECTIONPARAMS** connectionNames, int* numNames ) { RASENTRYNAME* rasEntryName; DWORD cb; DWORD cEntries; int i; char* szPhoneBook; szPhoneBook = NULL; rasEntryName = new RASENTRYNAME[ MAX_ENTRIES ]; if( rasEntryName == NULL ) return FALSE; memset( rasEntryName, 0, MAX_ENTRIES ); rasEntryName[ 0 ].dwSize = sizeof( RASENTRYNAME ); cb = sizeof( RASENTRYNAME ) * MAX_ENTRIES; int rtn = (*m_lpfnRasEnumEntries)( NULL, szPhoneBook, rasEntryName, &cb, &cEntries ); if ( rtn !=0 ) return FALSE; *numNames = cEntries; *connectionNames = new CONNECTIONPARAMS[ *numNames + 1 ]; for( i = 0; i < *numNames; i++ ) strcpy ( (*connectionNames)[ i ].szEntryName, rasEntryName[ i ].szEntryName ); delete []rasEntryName; return TRUE; } //******************************************************************************** // getDialupConnectionPIDL //******************************************************************************** static HRESULT getDialUpConnectionPIDL( LPCTSTR lpConnectionName, LPITEMIDLIST* ppidl ) { HRESULT hres; IMalloc* pMalloc = NULL; IShellFolder* pshf = NULL; LPITEMIDLIST pidldun; // Initialize out parameter *ppidl = NULL; hres = SHGetMalloc( &pMalloc ); if ( FAILED( hres ) ) return hres; // First get the Dial-Up Networking virtual folder hres = getDialUpNetworkingFolder( &pshf, &pidldun ); if ( SUCCEEDED( hres ) && ( pshf != NULL ) ) { IEnumIDList* pEnumIDList; // Enumerate the files looking for the desired connection hres = pshf->EnumObjects( /*pWndOwner->m_hWnd*/NULL, SHCONTF_FOLDERS | SHCONTF_NONFOLDERS, &pEnumIDList ); if ( SUCCEEDED( hres ) ) { LPITEMIDLIST pidl; int flag = 1; while ( ( NOERROR == ( hres = pEnumIDList->Next( 1, &pidl, NULL ) ) ) && flag ) { STRRET name; name.uType = STRRET_CSTR; // preferred choice hres = pshf->GetDisplayNameOf( pidl, SHGDN_INFOLDER, &name ); if ( FAILED( hres ) ) { pMalloc->Free( pidl ); flag = 0; //break; } if ( sameStrings( pidl, name, lpConnectionName ) ) { *ppidl = concatPidls( pidldun, pidl ); pMalloc->Free( pidl ); flag = 0; //break; } if ( flag ) pMalloc->Free(pidl); } pEnumIDList->Release(); } pshf->Release(); pMalloc->Free( pidldun ); } pMalloc->Release(); return hres; } //******************************************************************************** // getNetscapePIDL //******************************************************************************** static void getNetscapePidl( LPITEMIDLIST* ppidl ) { char szPath[ MAX_PATH ], *p; OLECHAR olePath[ MAX_PATH ]; IShellFolder* pshf; GetModuleFileName( gDLL, szPath, sizeof( szPath ) ); //GetModuleFileName(AfxGetInstanceHandle(), szPath, sizeof(szPath)); //we need to take off \plugins\npasw.dll from the path p = strrchr( szPath, '\\' ); if ( p ) *p = '\0'; p = strrchr( szPath, '\\' ); if ( p ) *p = '\0'; strcat( szPath, "\\netscape.exe" ); HRESULT hres = SHGetDesktopFolder( &pshf ); if ( SUCCEEDED( hres ) ) { MultiByteToWideChar( CP_ACP, MB_PRECOMPOSED, (LPCSTR)szPath, -1, (LPWSTR)olePath, sizeof( olePath ) ); ULONG lEaten; pshf->ParseDisplayName( NULL, NULL, (LPOLESTR)olePath, &lEaten, ppidl, NULL ); } return; } //******************************************************************************** // getMsgString // loads a Message String from the string table //******************************************************************************** static BOOL getMsgString( char* buf, UINT uID ) { if ( !buf ) return FALSE; int ret = LoadString( gDLL, uID, buf, 255 ); return ret; } //******************************************************************************** // getSystemDirectory_1() // intended to be a more fail-safe version of GetSystemDirectory // returns: // NULL if the path cannot be obtained for any reason // otherwise, the "GetSystemDirectory" path //******************************************************************************** static char* getSystemDirectory_1() { UINT startLength = MAX_PATH; UINT sysPathLength = MAX_PATH; char* sysPath; start: sysPath = (char*)malloc( sizeof(char) * startLength ); if ( !sysPath ) return NULL; sysPathLength = ::GetSystemDirectory( sysPath, startLength ); if ( sysPathLength == 0 ) return NULL; if ( sysPathLength > startLength ) { free( sysPath ); startLength = sysPathLength; goto start; } return sysPath; } //******************************************************************************** // getPhoneBookNT() // returns the path to the NT Phone Book file (rasphone.pbk) // returns: // NULL if the path cannot be obtained for any reason // otherwise, the phone book file path //******************************************************************************** static char* getPhoneBookNT() { char* sysPath; char* pbPath; sysPath = getSystemDirectory_1(); if ( !sysPath ) return FALSE; pbPath = (char*)malloc( sizeof(char) * strlen( sysPath ) + 30 ); if ( !pbPath ) { free( sysPath ); return FALSE; } strcpy( pbPath, sysPath ); strcat( pbPath, "\\ras\\rasphone.pbk" ); strcat( pbPath, "\0" ); free( sysPath ); return pbPath; } //******************************************************************************** // startRasMonNT() // starts the "rasmon" process (rasmon.exe) // returns: // FALSE if the process cannot be started for any reason // TRUE otherwise //******************************************************************************** static BOOL startRasMonNT() { // starts up RASMON process PROCESS_INFORMATION pi; BOOL ret; STARTUPINFO sti; UINT err = ERROR_SUCCESS; char* sysPath; char* rasMonPath; sysPath = getSystemDirectory_1(); if ( !sysPath ) return FALSE; rasMonPath = (char*)malloc( sizeof(char) * strlen( sysPath ) + 30 ); if ( !rasMonPath ) { free( sysPath ); return FALSE; } strcpy( rasMonPath, sysPath ); strcat( rasMonPath, "\\rasmon.exe" ); strcat( rasMonPath, "\0" ); free( sysPath ); memset( &sti, 0, sizeof( sti ) ); sti.cb = sizeof( STARTUPINFO ); // Run the RASMON app ret = ::CreateProcess( rasMonPath, NULL, NULL, NULL, FALSE, 0, NULL, NULL, &sti, &pi ); if ( ret == TRUE ) { gRasMon = pi.hProcess; Sleep( 3000 ); } free( rasMonPath ); return ret; } static void setStatusDialogText( int iField, const char* pText ) { if ( gHwndStatus ) { HWND hField = GetDlgItem( gHwndStatus, iField ); if ( hField ) SetWindowText( hField, pText ); } } static void removeStatusDialog() { if ( gHwndStatus ) { EndDialog( gHwndStatus, TRUE ); gHwndStatus = NULL; } } static int displayErrMsgWnd( char* text, int style, HWND hwnd ) { char title[ 50 ]; getMsgString( (char*)&title, IDS_APP_NAME ); if ( hwnd == NULL ) hwnd = GetActiveWindow(); int ret = MessageBox( hwnd, text, title, style ); return ret; } static void displayDialErrorMsg( DWORD dwError ) { char szErr[ 256 ]; char szErrStr[ 256 ]; HWND wind; ASSERT( m_lpfnRasGetErrorString ); (*m_lpfnRasGetErrorString)( (UINT)dwError, szErr, sizeof(szErr) ); // some of the default error strings are pretty lame switch ( dwError ) { case ERROR_NO_DIALTONE: getMsgString( szErr, IDS_NO_DIALTONE ); break; case ERROR_LINE_BUSY: getMsgString( szErr, IDS_LINE_BUSY ); break; case ERROR_PROTOCOL_NOT_CONFIGURED: getMsgString( szErr, IDS_PROTOCOL_NOT_CONFIGURED ); default: break; } getMsgString( szErrStr, IDS_CONNECTION_FAILED ); strcat( szErrStr, szErr ); wind = gHwndStatus; if ( !wind ) wind = gHwndNavigator; displayErrMsgWnd( szErrStr, MB_OK | MB_ICONEXCLAMATION, wind ); } static void connectErr( DWORD dwError ) { char strText[ 255 ]; if ( gHwndStatus ) { getMsgString( (char*)strText, IDS_DIAL_ERR ); setStatusDialogText( IDC_DIAL_STATUS, strText ); Sleep( 1000 ); removeStatusDialog(); } gDeviceErr = TRUE; // some sort of device err displayDialErrorMsg( dwError ); } BOOL CALLBACK statusDialogCallback( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam ) { BOOL bRetval = FALSE; DWORD dwRet; if ( !gHwndStatus ) gHwndStatus = hWnd; switch ( uMsg ) { case WM_INITDIALOG: return TRUE; break; case WM_COMMAND: { WORD wNotifyCode = HIWORD( wParam ); WORD wID = LOWORD( wParam ); HWND hControl = (HWND)lParam; switch ( wID ) { case IDDISCONNECTED: // if (AfxMessageBox(IDS_LOST_CONNECTION, MB_YESNO) == IDYES) // m_pMainWnd->PostMessage(WM_COMMAND, IDC_DIAL); break; case IDCANCEL: { // RasHangUp & destroy dialog box bRetval = TRUE; gCancelled = TRUE; ASSERT( m_lpfnRasHangUp ); char strText[ 255 ]; getMsgString( strText, IDS_CANCELDIAL ); setStatusDialogText( IDC_DIAL_STATUS, strText ); dwRet = ( *m_lpfnRasHangUp )( gRasConn ); if ( dwRet == ERROR_INVALID_HANDLE) trace("dialer.cpp : statusDialogCallback - Can't hangup. Invalid Connection Handle. (r)"); else if ( dwRet && dwRet != ERROR_INVALID_HANDLE ) trace("dialer.cpp : statusDialogCallback - Can't hangup. Error %d. (r)", dwRet); Sleep( 3000 ); removeStatusDialog(); break; } } } } return bRetval; } static void setCallState( CallState newState ) { gCallState = newState; switch ( gCallState ) { case StateConnected: // destroy our connection status window removeStatusDialog(); break; case StateConnecting: // creates status dialog box HWND hwndParent = GetActiveWindow(); int nResult; nResult = DialogBox( gDLL, MAKEINTRESOURCE( IDD_STATUS ), hwndParent, (DLGPROC)statusDialogCallback ); ASSERT( nResult != -1 ); break; } } //******************************************************************************** // RasDialFunc // call back function for RasDial //******************************************************************************** void CALLBACK RasDialFunc( HRASCONN hRasConn, UINT uMsg, RASCONNSTATE rasConnState, DWORD dwError, DWORD dwExtendedError ) { if ( uMsg != WM_RASDIALEVENT ) return; // ignore all other messages gRASstate = rasConnState; char strText[ 255 ]; DWORD dwRet; switch ( rasConnState ) { case RASCS_OpenPort: // wait for status dialog to show up first while ( gHwndStatus == NULL ) Sleep( 1000 ); getMsgString( strText, IDS_OPENING_PORT ); setStatusDialogText( IDC_DIAL_STATUS, strText ); if ( dwError ) connectErr( dwError ); else Sleep( 1000 ); break; case RASCS_PortOpened: getMsgString( strText, IDS_INIT_MODEM ); setStatusDialogText( IDC_DIAL_STATUS, strText ); if ( dwError ) connectErr( dwError ); else Sleep( 1000 ); break; case RASCS_ConnectDevice: if ( gDialAttempts == 1 ) { getMsgString( strText, IDS_DIALING ); setStatusDialogText( IDC_DIAL_STATUS, strText ); } else { char szBuf[ 128 ]; getMsgString(strText, IDS_DIALING_OF); wsprintf( szBuf, (LPCSTR)strText, gDialAttempts, NUM_ATTEMPTS ); setStatusDialogText( IDC_DIAL_STATUS, strText ); } if ( dwError ) connectErr( dwError ); else Sleep( 1000 ); break; case RASCS_Authenticate: getMsgString( strText, IDS_VERIFYING ); setStatusDialogText( IDC_DIAL_STATUS, strText ); if ( dwError ) connectErr( dwError ); else Sleep( 1000 ); break; case RASCS_Authenticated: getMsgString( strText, IDS_LOGGING_ON ); setStatusDialogText( IDC_DIAL_STATUS, strText ); if ( dwError ) connectErr( dwError ); else Sleep( 1000 ); break; case RASCS_Connected: getMsgString( strText, IDS_CONNECTED ); setStatusDialogText( IDC_DIAL_STATUS, strText ); setCallState( StateConnected ); if ( dwError ) connectErr( dwError ); else Sleep( 1000 ); break; case RASCS_Disconnected: // If this is an unexpected disconnect then hangup and take // down the status dialog box if ( gCallState == StateConnected || gCallState == StateConnecting ) { ASSERT( m_lpfnRasHangUp ); dwRet = ( *m_lpfnRasHangUp )( gRasConn ); if ( dwRet == ERROR_INVALID_HANDLE ) trace("dialer.cpp : ProcessRasDialEvent (stateConnected) - Can't hangup. Invalid Connection Handle."); else if ( dwRet && dwRet != ERROR_INVALID_HANDLE ) trace("dialer.cpp : ProcessRasDialEvent (stateConnected) - Can't hangup. Error %d", dwRet); Sleep( 3000 ); if ( gCallState == StateConnecting ) { if ( dwError != SUCCESS ) { if ( gHwndStatus ) { getMsgString( strText, IDS_DISCONNECTING ); setStatusDialogText( IDC_DIAL_STATUS, strText ); } } } // here we pass redial msg if needed. removeStatusDialog(); if ( gCallState == StateConnecting ) { gLineDrop = TRUE; // remove if we ask users for redial displayDialErrorMsg( dwError ); } } setCallState( StateIdle ); break; case RASCS_WaitForModemReset: getMsgString( strText, IDS_DISCONNECTING ); setStatusDialogText( IDC_DIAL_STATUS, strText ); if ( dwError ) { trace("dialer.cpp : ProcessRasDialEvent (WaitForModemReset) - Connection Error %d", dwError); connectErr( dwError ); } else Sleep( 1000 ); break; default: if ( dwError ) { trace( "dialer.cpp : ProcessRasDialEvent (default case) - Connection Error %d", dwError ); connectErr( dwError ); } break; } } //******************************************************************************** // DialerConnect // initiates a dialer connection (used if Dial on Demand is disabled) // assumes the dialer has already been configured // returns: // FALSE if the dialer cannot be connected // TRUE if the dialer is already connected or if it was able to connect // successfully //******************************************************************************** BOOL DialerConnect() { DWORD dwError; DWORD dwRet; BOOL connectSucceed = TRUE; gHwndNavigator = GetActiveWindow(); // return if dialer already connected if ( IsDialerConnected() ) return TRUE; gDialAttempts = 1; gRasConn = NULL; // init global connection handle gCancelled = FALSE; // assume connection is not canceled by the user, unless otherwise char* pbPath = NULL; LPVOID notifierProc = NULL; DWORD notifierType = 0; notifierType = 1; notifierProc = (LPVOID)RasDialFunc; // WinNT40 find system phone book first then start RASDIAL if ( gPlatformOS == VER_PLATFORM_WIN32_NT ) { startRasMonNT(); // should check the error here, but I don't know // what to do if we fail (report that error?) pbPath = getPhoneBookNT(); } ASSERT( m_lpfnRasDial ); // do the dialing here dwError = ( *m_lpfnRasDial )( NULL, pbPath, &gDialParams, notifierType, notifierProc, &gRasConn ); if ( dwError == ERROR_NOT_ENOUGH_MEMORY ) trace( "dialer.cpp : [native] DialerConnect - Not enough memory for dialing activity. Dialing failed." ); else if ( dwError && dwError != ERROR_NOT_ENOUGH_MEMORY ) trace( "dialer.cpp : [native] DialerConnect - Dialing failed. Error code = %d", dwError ); if ( dwError == SUCCESS ) { // Dialing succeeded // display connections status dialog & dispatch window msgs... MSG msg; setCallState( StateConnecting ); while ( ( ( gRASstate != RASCS_Connected ) && ( gRASstate != RASCS_Disconnected ) ) && ( !gCancelled ) && ( !gLineDrop ) && ( !gDeviceErr) ) { if ( ::GetMessage( &msg, NULL, 0, 0 ) ) { ::TranslateMessage( &msg ); ::DispatchMessage( &msg ); } else { // WM_QUIT!!! break; } } removeStatusDialog(); if ( ( gRASstate != RASCS_Connected ) || gCancelled ) connectSucceed = FALSE; } else { // dialing failed!!!, display err msg connectSucceed = FALSE; displayDialErrorMsg( dwError ); } if ( !connectSucceed ) { // hangup connection if ( gRasConn ) { ASSERT( m_lpfnRasHangUp ); dwRet = ( *m_lpfnRasHangUp )( gRasConn ); if ( dwRet == ERROR_INVALID_HANDLE ) trace("dialer.cpp : [native] DialerConnect - Can't hangup. Invalid Connection Handle."); else if ( dwRet && dwRet != ERROR_INVALID_HANDLE ) trace("dialer.cpp : [native] DialerConnect - Can't hangup. Error %d", dwRet); // give RasHangUp some time till complete hangup removeStatusDialog(); // wait three seconds for tear-down of notification proc. // should figure out how to do this better (maybe set something // in RasDialFunc which ensures us not getting called again?) Sleep( 3000 ); } } SetActiveWindow( gHwndNavigator ); return connectSucceed; } //******************************************************************************** // DialerHangup // terminates a dialer connection // if there is an active connection, it is terminated // returns: // nothing //******************************************************************************** void DialerHangup() { RASCONN* info = NULL; RASCONN* lpTemp = NULL; DWORD code; DWORD count = 0; DWORD dSize = stRASCONN; DWORD dwRet; BOOL triedOnce = FALSE; tryAgain: // try to get a buffer to receive the connection data info = (RASCONN*)LocalAlloc( LPTR, (UINT)dSize ); if ( !info ) return; // set RAS struct size info->dwSize = dSize; ASSERT( m_lpfnRasEnumConnections); // enumerate open connections code = ( *m_lpfnRasEnumConnections )( info, &dSize, &count ); if ( code != 0 && triedOnce == TRUE ) { LocalFree( info ); return; } if ( code == ERROR_BUFFER_TOO_SMALL ) { triedOnce = TRUE; // free the old buffer & allocate a new bigger one LocalFree( info ); goto tryAgain; } // check for no connections if ( count == 0 ) { LocalFree( info ); return; } ASSERT( m_lpfnRasHangUp ); // just hang up everything for ( int i = 0; i < (int) count; i++ ) { dwRet = ( *m_lpfnRasHangUp )( info[ i ].hrasconn ); if ( dwRet == ERROR_INVALID_HANDLE ) trace( "dialer.cpp : DialerHangup - Can't hangup. Invalid Connection Handle." ); else if ( dwRet && dwRet != ERROR_INVALID_HANDLE ) trace("dialer.cpp : DialerHangup - Can't hangup. Error %d.", dwRet); Sleep( 3000 ); } LocalFree( info ); } //******************************************************************************** // findDialerData // search the javascript array for specific string value //******************************************************************************** char* findDialerData( char** dialerData, char* name ) { char** entry = dialerData; char* value; while ( *entry ) { if ( strncmp( *entry, name, strlen( name ) ) == 0 ) { value = strchr( *entry, '=' ); if ( value ) value++; break; } entry++; } return (char*)value; } //******************************************************************************** // fillAccountParameters // fill in account information, given from JS array //******************************************************************************** static void fillAccountParameters( char** dialerData, ACCOUNTPARAMS* account ) { char* value; value = findDialerData( dialerData, "AccountName" ); strcpy( account->ISPName, value ? value : "My Account" ); // file name value = findDialerData( dialerData, "FileName" ); strcpy( account->FileName, value ? value : "My Account" ); // DNS value = findDialerData( dialerData, "DNSAddress" ); strcpy( account->DNS, value ? value : "0.0.0.0" ); // DNS2 value = findDialerData( dialerData, "DNSAddress2" ); strcpy( account->DNS2, value ? value : "0.0.0.0" ); // domain name value = findDialerData( dialerData, "DomainName" ); strcpy( account->DomainName, value ? value : "" ); // login name value = findDialerData( dialerData, "LoginName" ); strcpy(account->LoginName, value ? value : ""); // password value = findDialerData( dialerData, "Password" ); strcpy( account->Password, value ? value : "" ); // script file name value = findDialerData( dialerData, "ScriptFileName" ); strcpy( account->ScriptFileName, value ? value : "" ); // script enabled? value = findDialerData( dialerData, "ScriptEnabled" ); if ( value ) { account->ScriptEnabled = ( strcmp( value, "TRUE" ) == 0 ); // get script content value = findDialerData( dialerData, "Script" ); if ( value ) { // ReggieScript = (char*) malloc(strlen(value) + 1); // strcpy(ReggieScript, value); } } else account->ScriptEnabled = 0; // need TTY window? value = findDialerData( dialerData, "NeedsTTYWindow" ); account->NeedsTTYWindow = ( value && ( strcmp( value, "TRUE" ) == 0 ) ); // VJ compression enabled? value = findDialerData( dialerData, "VJCompresssionEnabled" ); account->VJCompressionEnabled = ( value && ( strcmp( value, "TRUE" ) == 0 ) ); // International mode? value = findDialerData( dialerData, "IntlMode" ); account->IntlMode = ( value && ( strcmp( value, "TRUE" ) == 0 ) ); // dial on demand? value = findDialerData( dialerData, "DialOnDemand" ); account->DialOnDemand = ( value && ( strcmp( value, "TRUE" ) == 0 ) ); // isp phone number value = findDialerData( dialerData, "ISPPhoneNum" ); if ( value ) strcpy( account->ISPPhoneNum, value ); else strcpy( account->ISPPhoneNum, "" ); // ISDN phone number value = findDialerData( dialerData, "ISDNPhoneNum" ); if ( value ) strcpy( account->ISDNPhoneNum, value ); else strcpy( account->ISDNPhoneNum, "" ); } //******************************************************************************** // fillLocationParameters // fill in location information, given from JS array //******************************************************************************** static void fillLocationParameters( char** dialerData, LOCATIONPARAMS* location ) { char* value; // modem name value = findDialerData( dialerData, "ModemName" ); strcpy( location->ModemName, value ? value : "" ); // modem type value = findDialerData( dialerData, "ModemType" ); strcpy( location->ModemType, value ? value : "" ); // dial type value = findDialerData( dialerData, "DialType" ); location->DialType = !( value && ( strcmp( value, "TONE" ) == 0 ) ); // outside line access value = findDialerData( dialerData, "OutsideLineAccess" ); strcpy( location->OutsideLineAccess, value ? value : "" ); // disable call waiting? value = findDialerData( dialerData, "DisableCallWaiting"); location->DisableCallWaiting = ( value && ( strcmp(value, "TRUE") == 0 ) ); // disable call waiting code value = findDialerData( dialerData, "DisableCallWaitingCode" ); strcpy( location->DisableCallWaitingCode, value ? value : "" ); // user area code value = findDialerData( dialerData, "UserAreaCode" ); strcpy( location->UserAreaCode, value ? value : "" ); // user country code value = findDialerData( dialerData, "CountryCode" ); if ( value ) { char* stopstr = "\0"; location->UserCountryCode = (short)strtol( value, &stopstr, 10 ); } else location->UserCountryCode = 1; // default to US // dial as long distance? value = findDialerData( dialerData, "DialAsLongDistance"); location->DialAsLongDistance = ( value && ( strcmp( value, "TRUE" ) == 0 ) ); // long distance access value = findDialerData( dialerData, "LongDistanceAccess" ); strcpy( location->LongDistanceAccess, value ? value : "" ); // dial area code? value = findDialerData( dialerData, "DialAreaCode" ); location->DialAreaCode = ( value && ( strcmp( value, "TRUE" ) == 0 ) ); // dial prefix code value = findDialerData( dialerData, "DialPrefix" ); strcpy( location->DialPrefix, value ? value : "" ); // dial suffix code value = findDialerData( dialerData, "DialSuffix" ); strcpy( location->DialSuffix, value ? value : "" ); // use both ISDN lines? value = findDialerData( dialerData, "UseBothISDNLines" ); location->UseBothISDNLines = ( value && ( strcmp( value, "TRUE" ) == 0 ) ); // 56k ISDN? value = findDialerData( dialerData, "56kISDN" ); location->b56kISDN = ( value && ( strcmp( value, "TRUE" ) == 0 ) ); // disconnect time value = findDialerData( dialerData, "DisconnectTime" ); if ( value ) location->DisconnectTime = atoi( value ); else location->DisconnectTime = 5; } //******************************************************************************** // onlyOneSet // Just an XOR of DialAsLongDistance & DialAreaCode - if only one of them is // set then we can't use MS Locations (if neither are set then we can use // locations, but disable use of both - they just don't allow disabling of each // individually) //******************************************************************************** static BOOL onlyOneSet( const LOCATIONPARAMS& location ) { return ( location.DialAsLongDistance ? ( location.DialAreaCode ? FALSE : TRUE ) : ( location.DialAreaCode ? TRUE : FALSE ) ); } //******************************************************************************** // prefixAvail // returns: // TRUE if there are prefixes that make location unusable //******************************************************************************** static BOOL prefixAvail( const LOCATIONPARAMS& location ) { return ( location.DisableCallWaiting && location.DisableCallWaitingCode[ 0 ] != 0 ) || ( location.OutsideLineAccess && location.OutsideLineAccess[ 0 ] != 0 ); } //******************************************************************************** // parseNumber // // Parses a canonical TAPI phone number into country code, area code, and // local subscriber number //******************************************************************************** static void parseNumber( LPCSTR lpszCanonical, LPDWORD lpdwCountryCode, LPSTR lpszAreaCode, LPSTR lpszLocal) { //*** sscanf dependency removed for win16 compatibility char temp[ 256 ]; int p1, p2; // Initialize our return values *lpdwCountryCode = 1; // North America Calling Plan *lpszAreaCode = '\0'; *lpszLocal = '\0'; if ( !lpszCanonical || !*lpszCanonical ) return; // We allow three variations (two too many): // -: +1 (415) 428-3838 (TAPI canonical number) // -: (415) 428-3838 (TAPI canonical number minus country code) // -: 428-3838 (subscriber number only) // // NOTE: this approach only works if there is a city/area code. The TAPI // spec says the city/area code is optional for countries that have a flat // phone numbering system // Take my advice, always start at the beginning. p1 = 0; // Allow spaces while ( lpszCanonical[p1] == ' ' ) p1++; // Handle the country code if '+' prefix seen if ( lpszCanonical[p1] == '+' ) { p1++; if ( !isdigit( lpszCanonical[ p1 ] ) ) return; p2 = p1; while ( isdigit( lpszCanonical[ p1 ] ) ) p1++; strncpy( temp, &lpszCanonical[ p2 ], p1 - p2 ); *lpdwCountryCode = atoi( temp ); } // Allow spaces while ( lpszCanonical[p1] == ' ' ) p1++; // Handle the area code if '(' prefix seen if ( lpszCanonical[ p1 ] == '(' ) { p1++; if ( !isdigit( lpszCanonical[ p1 ] ) ) return; p2 = p1; while ( isdigit( lpszCanonical[ p1 ] ) ) p1++; strncpy( lpszAreaCode, &lpszCanonical[ p2 ], p1 - p2 ); p1++; // Skip over the trailing ')' } // Allow spaces while ( lpszCanonical[p1] == ' ' ) p1++; // Whatever's left is the subscriber number (possibly including the whole string) strcpy( lpszLocal, &lpszCanonical[ p1 ] ); } //******************************************************************************** // composeNumber // create a phone number encompassing all of the location information to hack // around dialup networking ignoring the location information if you turn off // the "dial area and country code" flag //******************************************************************************** static void composeNumber( ACCOUNTPARAMS& account, const LOCATIONPARAMS& location, char csNumber[] ) { // if they need to dial something to get an outside line next if ( location.OutsideLineAccess[ 0 ] != 0 ) { strcat( csNumber, location.OutsideLineAccess ); strcat( csNumber, " " ); } // add disable call waiting if it exists if ( location.DisableCallWaiting && location.DisableCallWaitingCode[ 0 ] != 0 ) { strcat( csNumber, location.DisableCallWaitingCode ); strcat( csNumber, " "); } if ( account.IntlMode ) { // In international mode we don't fill out the area code or // anything, just the exchange part strcat( csNumber, account.ISPPhoneNum ); } else { // lets parse the number into pieces so we can get the area code & country code DWORD nCntry; char szAreaCode[ 32 ]; char szPhoneNumber[ 32 ]; parseNumber( account.ISPPhoneNum, &nCntry, szAreaCode, szPhoneNumber ); // dial the 1 (country code) first if they want it if ( location.DialAsLongDistance ) { char cntry[ 10 ]; ultoa( nCntry, cntry, 10 ); if ( strcmp( location.LongDistanceAccess, "" ) == 0 ) strcat( csNumber, cntry ); else strcat( csNumber, location.LongDistanceAccess ); strcat( csNumber, " " ); } // dial the area code next if requested if ( location.DialAreaCode ) { strcat( csNumber, szAreaCode ); strcat( csNumber, " " ); } // dial the local part of the number strcat( csNumber, szPhoneNumber ); } } //******************************************************************************** // toNumericAddress // converts from dotted address to numeric internet address //******************************************************************************** static BOOL toNumericAddress( LPCSTR lpszAddress, DWORD& dwAddress ) { //*** sscanf dependency removed for win16 compatibility char temp[ 256 ]; int a, b, c, d; int p1, p2; strcpy( temp, lpszAddress ); p2 = p1 = 0; while ( temp[ p1 ] != '.' ) p1++; temp[ p1 ] = '\0'; a = atoi( &temp[ p2 ] ); p2 = ++p1; while ( temp[ p1 ] != '.' ) p1++; temp[ p1 ] = '\0'; b = atoi( &temp[ p2 ] ); p2 = ++p1; while ( temp[ p1 ] != '.' ) p1++; temp[ p1 ] = '\0'; c = atoi( &temp[ p2 ] ); p2 = ++p1; d = atoi( &temp[ p2 ] ); // Must be in network order (different than Intel byte ordering) LPBYTE lpByte = (LPBYTE)&dwAddress; *lpByte++ = BYTE( a ); *lpByte++ = BYTE( b ); *lpByte++ = BYTE( c ); *lpByte = BYTE( d ); return TRUE; } //******************************************************************************** // getCountryID //******************************************************************************** static BOOL getCountryID( DWORD dwCountryCode, DWORD& dwCountryID ) { ASSERT( m_lpfnRasGetCountryInfo ); if ( !m_lpfnRasGetCountryInfo ) { trace( "dialer.cpp : GetCountryID - RasGetCountryinfo func not availble. (r)" ); return FALSE; } RASCTRYINFO* pCI = NULL; BOOL bRetval = FALSE; DWORD dwSize = stRASCTRYINFO + 256; pCI = (RASCTRYINFO*)malloc( (UINT) dwSize ); if ( pCI ) { pCI->dwSize = stRASCTRYINFO; pCI->dwCountryID = 1; while ( ( *m_lpfnRasGetCountryInfo )( pCI, &dwSize ) == 0 ) { if ( pCI->dwCountryCode == dwCountryCode ) { dwCountryID = pCI->dwCountryID; bRetval = TRUE; break; } pCI->dwCountryID = pCI->dwNextCountryID; } free( pCI ); pCI = NULL; } return bRetval; } //******************************************************************************** // createLink // creates a shell shortcut to the PIDL //******************************************************************************** static HRESULT createLink( LPITEMIDLIST pidl, LPCTSTR lpszPathLink, LPCTSTR lpszDesc, char* iconPath ) { HRESULT hres; IShellLink* psl = NULL; // Get a pointer to the IShellLink interface. //CoInitialize(NULL); // work around for Nav thread lock bug hres = CoCreateInstance( CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLink, (LPVOID FAR*)&psl ); if ( SUCCEEDED( hres ) ) { IPersistFile* ppf; // Set the path to the shortcut target, and add the description. psl->SetIDList( pidl ); psl->SetDescription( lpszDesc ); if( iconPath && iconPath[ 0 ] ) psl->SetIconLocation( iconPath, 0 ); // Query IShellLink for the IPersistFile interface for saving the // shortcut in persistent storage. hres = psl->QueryInterface( IID_IPersistFile, (LPVOID FAR*)&ppf ); if ( SUCCEEDED( hres ) ) { WORD wsz[ MAX_PATH ]; // Ensure that the string is ANSI. MultiByteToWideChar( CP_ACP, 0, lpszPathLink, -1, wsz, MAX_PATH ); // Save the link by calling IPersistFile::Save. hres = ppf->Save( (LPCOLESTR)wsz, STGM_READ ); ppf->Release(); } psl->Release(); } //CoUninitialize(); return hres; } //******************************************************************************** // fileExists //******************************************************************************** static BOOL fileExists( LPCSTR lpszFileName ) { BOOL bResult = FALSE; HANDLE hFile=NULL; // opens the file for READ hFile = CreateFile(lpszFileName, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if (hFile != INVALID_HANDLE_VALUE) { // openned file is valid bResult = TRUE; CloseHandle(hFile); } return bResult; } //******************************************************************************** // processScriptLogin // generate a script file and return the name of the file. The // caller is responsible for freeing the script file name //******************************************************************************** static BOOL processScriptedLogin( LPSTR lpszBuf, const char* lpszScriptFile ) { // validate our args just for fun if (!lpszBuf || (lpszBuf[0] == '\0') || !lpszScriptFile) return(FALSE); // open the actual script file FILE * fp = fopen(lpszScriptFile, "w"); if (!fp) return(FALSE); // generate a prolog char timebuf[24]; char datebuf[24]; _strtime(timebuf); _strdate(datebuf); fprintf(fp, "; %s\n; Created: %s at %s\n;\n;\nproc main\n", lpszScriptFile, datebuf, timebuf); // Send a return to poke the server. Is this needed? fprintf(fp, "transmit \"^M\"\n"); for (int i = 0; lpszBuf; i++) { LPSTR lpszDelim; // Each event consists of two parts: // 1. string to wait for // 2. string to reply with // // The string to reply with is optional. A '|' separates the two strings // and another '|' separates each event lpszDelim = strchr(lpszBuf, '|'); if(lpszDelim) *lpszDelim = '\0'; // we are in the "wait for event" fprintf(fp, "waitfor \"%s\",matchcase until 30\n", lpszBuf); // skip to the next bit lpszBuf = lpszDelim ? lpszDelim + 1 : NULL; if (lpszBuf) { // now look for the reply event lpszDelim = strchr(lpszBuf, '|'); if(lpszDelim) *lpszDelim = '\0'; // we are in the "reply with" event // NOTE: we will want to get the ^M value from someone else // since different ISPs will probably want different ones if (!stricmp(lpszBuf, "%name")) fprintf(fp, "transmit $USERID\n"); else if(!stricmp(lpszBuf, "%password")) fprintf(fp, "transmit $PASSWORD\n"); else if(lpszBuf[0]) fprintf(fp, "transmit \"%s\"\n", lpszBuf); fprintf(fp, "transmit \"^M\"\n"); } lpszBuf = lpszDelim ? lpszDelim + 1 : NULL; } // writeout the ending bits and cleanup fprintf(fp, "endproc\n"); fclose(fp); return(TRUE); } //******************************************************************************** // createPhoneBookEntry // Create a dial-up networking profile //******************************************************************************** static BOOL createPhoneBookEntry( ACCOUNTPARAMS account, const LOCATIONPARAMS& location ) { DWORD dwRet; BOOL ret = FALSE; RASENTRY rasEntry; // abort if RAS API ptrs are invalid & mem alloc fails ASSERT( m_lpfnRasSetEntryProperties ); ASSERT( m_lpfnRasSetEntryDialParams ); if ( !m_lpfnRasSetEntryProperties || !m_lpfnRasSetEntryDialParams ) return FALSE; // Initialize the RNA struct memset( &rasEntry, 0, stRASENTRY ); rasEntry.dwSize = stRASENTRY; rasEntry.dwfOptions = RASEO_ModemLights | RASEO_RemoteDefaultGateway; // Only allow compression if reg server says its OK if ( account.VJCompressionEnabled ) rasEntry.dwfOptions |= RASEO_IpHeaderCompression | RASEO_SwCompression; if ( account.NeedsTTYWindow ) if ( gPlatformOS == VER_PLATFORM_WIN32_WINDOWS ) rasEntry.dwfOptions |= RASEO_TerminalBeforeDial; //win95 bug! RASEO_TerminalBeforeDial means terminal after dial else rasEntry.dwfOptions |= RASEO_TerminalAfterDial; // If Intl Number (not NorthAmerica), or Area Code w/o LDAccess (1) or // visa-versa, then abandon using Location - NOTE: for Intl Number we // should be able to use location, check it out! if ( account.IntlMode || onlyOneSet( location ) ) { char szNumber[ RAS_MaxPhoneNumber + 1 ]; szNumber[ 0 ] = '\0'; composeNumber( account, location, szNumber ); strcpy( rasEntry.szLocalPhoneNumber, szNumber ); strcpy( rasEntry.szAreaCode, "415" ); // hack around MS bug -- ignored rasEntry.dwCountryCode = 1; // hack around MS bug -- ignored } else { // Let Win95 decide to dial the area code or not rasEntry.dwfOptions |= RASEO_UseCountryAndAreaCodes; trace( "dialer.cpp : Use country and area codes = %d", rasEntry.dwfOptions ); // Configure the phone number parseNumber( account.ISPPhoneNum, &rasEntry.dwCountryCode, rasEntry.szAreaCode, rasEntry.szLocalPhoneNumber ); if ( !account.IntlMode ) { // if not internationalize version, check the area code and make // sure we got a valid area code, if not throw up a err msg if ( rasEntry.szAreaCode[ 0 ] == '\0' ) { // Err: The service provider's phone number is missing its area code // (or is not in TAPI cannonical form in the configuration file). // Account creation will fail until this is fixed. char* buf = (char*)malloc( sizeof(char) * 255 ); if ( buf ) { if ( getMsgString( buf, IDS_MISSING_AREA_CODE ) ) displayErrMsgWnd( buf, MB_OK | MB_ICONEXCLAMATION, gHwndNavigator ); free( buf ); } return FALSE; } } } // Now that we have the country code, we need to find the associated // country ID getCountryID( rasEntry.dwCountryCode, rasEntry.dwCountryID ); // Configure the IP data rasEntry.dwfOptions |= RASEO_SpecificNameServers; if ( account.DNS[ 0 ] ) toNumericAddress( account.DNS, *(LPDWORD)&rasEntry.ipaddrDns ); if ( account.DNS2[ 0 ] ) toNumericAddress( account.DNS2, *(LPDWORD)&rasEntry.ipaddrDnsAlt ); // Configure the protocol and device settings here: // Negotiate TCP/IP rasEntry.dwfNetProtocols = RASNP_Ip; // Point-to-Point protocol (PPP) rasEntry.dwFramingProtocol = RASFP_Ppp; // modem's information strcpy( rasEntry.szDeviceName, location.ModemName ); strcpy( rasEntry.szDeviceType, location.ModemType ); // If we have a script, then store it too if ( account.ScriptEnabled ) { BOOL rtnval = TRUE; /* // if there is script content, 'Translate' and store in file if ( ReggieScript ) { // construct script filename if it does not exists if ( strlen( account.ScriptFileName ) == 0 ) { GetProfileDirectory( account.ScriptFileName ); int nIndex = strlen( account.ScriptFileName ); strncat( account.ScriptFileName, account.ISPName, 8 ); strcat( account.ScriptFileName, ".scp" ); } rtnval = ProcessScriptedLogin( (LPSTR)ReggieScript, account.ScriptFileName ); free( ReggieScript ); } // if there really is a script file (from ISP or Reggie) then use it if ( rtnval && FileExists( account.ScriptFileName ) ) { strcpy( rasEntry.szScript, account.ScriptFileName ); // convert forward slash to backward slash int nLen = strlen( rasEntry.szScript ); for ( int i = 0; i < nLen; i++ ) if ( rasEntry.szScript[ i ] == '/' ) rasEntry.szScript[ i ] = '\\'; } */ } dwRet = ( *m_lpfnRasValidateEntryName )( NULL, (LPSTR)account.ISPName ); if ( dwRet == ERROR_ALREADY_EXISTS ) dwRet = 0; ASSERT( dwRet == 0 ); if ( dwRet == ERROR_INVALID_NAME ) { trace ("dialer.cpp : CreateRNAEntry (RasValidateEntryName) - Invalid Name. Can't set RasEntry properties. (r)"); return FALSE; } else if ( dwRet == ERROR_ALREADY_EXISTS ) { trace ("dialer.cpp : CreateRNAEntry (RasValidateEntryName) - This name already exists. (r)"); return FALSE; } else if ( dwRet ) { trace ("dialer.cpp : CreateRNAEntry (RasValidateEntryName) - Can't Validate account name. Error %d. (r)", dwRet); return FALSE; } dwRet = ( *m_lpfnRasSetEntryProperties )( NULL, (LPSTR)(LPCSTR)account.ISPName, (LPBYTE)&rasEntry, stRASENTRY, NULL, 0 ); ASSERT( dwRet == 0 ); //if ( dwRet ) //return -1; // ??? this is going to return TRUE if ( dwRet == ERROR_BUFFER_INVALID ) { trace ("dialer.cpp : CreateRNAEntry (RasSetEntryProperties) - Invalid Buffer. Can't set RasEntry properties. (r)"); return FALSE; } else if ( dwRet == ERROR_CANNOT_OPEN_PHONEBOOK ) { trace ("dialer.cpp : CreateRNAEntry (RasSetEntryProperties) - Can't open phonebook. Corrupted phonebook or missing components. Can't set RasEntry properties. (r)"); return FALSE; } else if ( dwRet ) { trace ("dialer.cpp : CreateRNAEntry (RasSetEntryProperties) - Can't set RasEntry properties. Error %d. (r)", dwRet); return FALSE; } // We need to set the login name and password with a separate call // why doesn't this work for winNT40?? memset( &gDialParams, 0, sizeof( gDialParams ) ); gDialParams.dwSize = stRASDIALPARAMS; strcpy( gDialParams.szEntryName, account.ISPName ); strcpy( gDialParams.szUserName, account.LoginName ); strcpy( gDialParams.szPassword, account.Password ); // Creating connection entry! char* pbPath = NULL; if ( gPlatformOS = VER_PLATFORM_WIN32_NT ) pbPath = getPhoneBookNT(); else pbPath = (char*)account.ISPName; dwRet = ( *m_lpfnRasSetEntryDialParams )( pbPath, &gDialParams, FALSE ); if ( dwRet == ERROR_BUFFER_INVALID ) { trace ("dialer.cpp : CreateRNAEntry (RasSetEntryDialParams) - Invalid Buffer. Can't set RasEntry Dial properties. (r)"); return FALSE; } else if ( dwRet == ERROR_CANNOT_OPEN_PHONEBOOK ) { trace ("dialer.cpp : CreateRNAEntry (RasSetEntryDialParams) - Can't open phonebook. Corrupted phonebook or missing components. Can't set RasEntry Dial properties. (r)"); return FALSE; } else if ( dwRet == ERROR_CANNOT_FIND_PHONEBOOK_ENTRY ) { trace ("dialer.cpp : CreateRNAEntry (RasSetEntryDialParams) - Phonebook entry does not exist. Can't set RasEntry Dial properties. (r)"); return FALSE; } else if ( dwRet ) { trace ("dialer.cpp : CreateRNAEntry (RasSetEntryDialParams) - Can't set RasEntry Dial properties. Error %d. (r)", dwRet); return FALSE; } ret = ( dwRet == 0 ); if ( gPlatformOS = VER_PLATFORM_WIN32_NT ) { RASCREDENTIALS credentials; // sets up user login info for new phonebook entry memset( &credentials, 0, sizeof( RASCREDENTIALS ) ); credentials.dwSize = sizeof( RASCREDENTIALS ); credentials.dwMask = RASCM_UserName | RASCM_Password; strcpy( credentials.szUserName, account.LoginName ); strcpy( credentials.szPassword, account.Password ); strcpy( credentials.szDomain, account.DomainName ); dwRet = ( *m_lpfnRasSetCredentials )( pbPath, (LPSTR)account.ISPName, &credentials, FALSE ); if ( dwRet == ERROR_INVALID_PARAMETER ) { trace( "dialer.cpp : CreateRNAEntry (RasSetCredentials) - Invalid Parameter. Can't set user credentials. (r)" ); return FALSE; } else if ( dwRet == ERROR_CANNOT_OPEN_PHONEBOOK ) { trace( "dialer.cpp : CreateRNAEntry (RasSetCredentials) - Can't open phonebook. Corrupted phonebook or missing components. Can't set user credentials. (r)" ); return FALSE; } else if ( dwRet == ERROR_CANNOT_FIND_PHONEBOOK_ENTRY ) { trace( "dialer.cpp : CreateRNAEntry (RasSetCredentials) - Phonebook entry does not exist. Can't set user credentials. (r)" ); return FALSE; } else if ( dwRet == ERROR_INVALID_SIZE ) { trace( "dialer.cpp : CreateRNAEntry (RasSetCredentials) - Invalid size value. Can't set user credentials. (r)" ); return FALSE; } else if ( dwRet ) { trace( "dialer.cpp : CreateRNAEntry (RasSetCredentials) - Can't set user credentials. Error %d. (r)", dwRet ); return FALSE; } ret = ( dwRet == 0 ); if ( pbPath ) free( pbPath ); } // dialing on demand is cool. let's do that on win95 now if ( ret == TRUE && account.DialOnDemand ) if ( gPlatformOS == VER_PLATFORM_WIN32_WINDOWS ) EnableDialOnDemand95( (LPSTR)account.ISPName, TRUE ); else if ( gPlatformOS == VER_PLATFORM_WIN32_NT ) EnableDialOnDemandNT( (LPSTR)account.ISPName, TRUE ); //SetAutoDisconnect( location.DisconnectTime ); return ret; } //******************************************************************************** // DialerConfig // // setup and configures the dialer and networking stuff // used in 3 conditions: // 1. when calling regi for a new account // 2. to configure new account from regi on users system // 3. when optionally register Navigator in existing account path //******************************************************************************** int DialerConfig( char** dialerDataArray ) { gHwndNavigator = GetActiveWindow(); ACCOUNTPARAMS account; LOCATIONPARAMS location; if ( !dialerDataArray ) return -1; // now we try to get values from the JS array and put them into corresponding // account and location parameters fillAccountParameters( dialerDataArray, &account ); fillLocationParameters( dialerDataArray, &location ); // configure & creating Dial-Up Networking profile here for Win95 & WinNT40 // win16 use Shiva's RAS if ( !( createPhoneBookEntry( account, location ) ) ) { // Err: Unable to crate RNA phone book entry! char* buf = (char*)malloc( sizeof(char) * 255 ); if ( buf ) { if ( getMsgString( buf, IDS_NO_RNA_REGSERVER ) ) displayErrMsgWnd( buf, MB_OK | MB_ICONEXCLAMATION, gHwndNavigator ); free( buf ); } } // int ret; // if ( gPlatformOS == VER_PLATFORM_WIN32_WINDOWS ) // { // // sets the location stuff // ret = SetLocationInfo( account, location ); // //ret = DisplayDialableNumber(); // } // else // { // ret = SetLocationInfoNT( account, location ); // } return 0; } //******************************************************************************** // IsDialerConnected // checks if the dialer is still connected // // returns: // TRUE if the dialer is connected // FALSE if the dialer is not connected or there is an error trying to // determine if the dialer is connected //******************************************************************************** BOOL IsDialerConnected() { RASCONN* info = NULL; RASCONN* lpTemp = NULL; DWORD code = 0; DWORD count = 0; DWORD dSize = stRASCONN; // try to get a buffer to receive the connection data if ( ! ( info = (RASCONN*)LocalAlloc( LPTR, dSize ) ) ) return FALSE; // see if there are any open connections info->dwSize = stRASCONN; code = (*m_lpfnRasEnumConnections)( info, &dSize, &count ); if ( 0 != code ) // ERROR_BUFFER_TOO_SMALL ? { // free the old buffer LocalFree( info ); // allocate a new bigger one info = (RASCONN*)LocalAlloc( LPTR, dSize ); if ( !info ) return FALSE; // try to enumerate again info->dwSize = dSize; if ( (*m_lpfnRasEnumConnections) (info, &dSize, &count ) != 0 ) { LocalFree( info ); // can't enumerate connections, assume none is active return FALSE; } } // check for no connections if ( 0 == count ) { LocalFree( info ); return FALSE; } LocalFree( info ); return TRUE; } //******************************************************************************** // SetAutoDisconnect // Sets the autodisconnect time if idle // the parameter "disconnectTime" is specified as MINUTES, convert it to SECONDS // as necessary //******************************************************************************** void SetAutoDisconnect(DWORD disconnectTime) { HKEY hKey; DWORD dwDisposition; long result; DWORD dwValue; // if it's win95 if ( gPlatformOS == VER_PLATFORM_WIN32_WINDOWS ) { // // set the autodial flag first // result = RegCreateKeyEx(HKEY_CURRENT_USER, "Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings", NULL, NULL, NULL, KEY_ALL_ACCESS, NULL, &hKey, &dwDisposition); // err, oops if (result != ERROR_SUCCESS) return; // try setting autodisconnect here dwValue = 1; result = RegSetValueEx(hKey, "EnableAutoDisconnect", NULL, REG_BINARY, (LPBYTE)&dwValue, sizeof(DWORD)); // default auto-disconnect after 5 minutes or as specified (with a minimal of 3 minutes) if (disconnectTime < 3) dwValue = 3; else dwValue = disconnectTime; result = RegSetValueEx(hKey, "DisconnectIdleTime", NULL, REG_BINARY, (LPBYTE)&dwValue, sizeof(DWORD)); RegCloseKey(hKey); // // set the autodisconnect flags here too // result = RegCreateKeyEx(HKEY_CURRENT_USER, "Software\\Microsoft\\Windows\\Internet Settings", NULL, NULL, NULL, KEY_ALL_ACCESS, NULL, &hKey, &dwDisposition); // err, oops if (result != ERROR_SUCCESS) return; dwValue = 1; result = RegSetValueEx(hKey, "EnableAutoDisconnect", NULL, REG_BINARY, (LPBYTE)&dwValue, sizeof(DWORD)); // default auto-disconnect after 5 minutes if (disconnectTime < 3) dwValue = 3; else dwValue = disconnectTime; result = RegSetValueEx(hKey, "DisconnectIdleTime", NULL, REG_BINARY, (LPBYTE)&dwValue, sizeof(DWORD)); RegCloseKey(hKey); // // also set the autodial flag here // result = RegCreateKeyEx(HKEY_USERS, ".Default\\Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings", NULL, NULL, NULL, KEY_ALL_ACCESS, NULL, &hKey, &dwDisposition); // err, oops if (result != ERROR_SUCCESS) return; // try setting autodisconnect here dwValue = 1; result = RegSetValueEx(hKey, "EnableAutoDisconnect", NULL, REG_BINARY, (LPBYTE)&dwValue, sizeof(DWORD)); // default auto-disconnect after 5 minutes or as specified (with a minimal of 3 minutes) if (disconnectTime < 3) dwValue = 3; else dwValue = disconnectTime; result = RegSetValueEx(hKey, "DisconnectIdleTime", NULL, REG_BINARY, (LPBYTE)&dwValue, sizeof(DWORD)); RegCloseKey(hKey); // // set the autodisconnect flags here too // result = RegCreateKeyEx(HKEY_USERS, ".Default\\Software\\Microsoft\\Windows\\Internet Settings", NULL, NULL, NULL, KEY_ALL_ACCESS, NULL, &hKey, &dwDisposition); // err, oops if (result != ERROR_SUCCESS) return; dwValue = 1; result = RegSetValueEx(hKey, "EnableAutoDisconnect", NULL, REG_BINARY, (LPBYTE)&dwValue, sizeof(DWORD)); // default auto-disconnect after 5 minutes if (disconnectTime < 3) dwValue = 3; else dwValue = disconnectTime; result = RegSetValueEx(hKey, "DisconnectIdleTime", NULL, REG_BINARY, (LPBYTE)&dwValue, sizeof(DWORD)); RegCloseKey(hKey); } else { // NT40 // we need to convert disconnectTime to # of seconds for NT40 dwValue = (disconnectTime * 60); result = RegOpenKeyEx(HKEY_USERS, ".DEFAULT\\Software\\Microsoft\\RAS Phonebook", NULL, KEY_ALL_ACCESS, &hKey); if (result != ERROR_SUCCESS) return; // now set the auto disconnect seconds result = RegSetValueEx(hKey, "IdleHangupSeconds", NULL, REG_DWORD, (LPBYTE)&dwValue, sizeof(DWORD)); RegCloseKey(hKey); } return; } //******************************************************************************** // CheckDNS // for Win95 // If user has DNS enabled, when setting up an account, we need to warn them // that there might be problems. //******************************************************************************** void CheckDNS() { char buf[ 256 ]; HKEY hKey; DWORD cbData; LONG res; // open the key if registry if( ERROR_SUCCESS != RegOpenKeyEx( HKEY_LOCAL_MACHINE, "System\\CurrentControlSet\\Services\\VxD\\MSTCP", NULL, KEY_ALL_ACCESS , &hKey ) ) return; cbData = sizeof( buf ); res = RegQueryValueEx( hKey, "EnableDNS", NULL, NULL, (LPBYTE)buf, &cbData ); RegCloseKey( hKey ); // if DNS is enabled we need to warn the user if( buf[ 0 ] == '1' ) { BOOL correctWinsockVersion = FALSE; // check for user's winsock version first, see if it's winsock2 WORD wVersionRequested; WSADATA wsaData; int err; wVersionRequested = MAKEWORD( 2, 2 ); err = WSAStartup( wVersionRequested, &wsaData ); if ( err != 0 ) { // user doesn't have winsock2, so check their winsock's date char winDir[ MAX_PATH ]; UINT uSize = MAX_PATH; char winsockFile[ MAX_PATH ]; winDir[ 0 ] = '\0'; winsockFile[ 0 ] = '\0'; GetWindowsDirectory( (char*)&winDir, uSize ); strcpy( winsockFile, winDir ); strcat( winsockFile, "\\winsock.dll" ); HANDLE hfile = CreateFile( (char*)&winsockFile, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL ); if ( hfile != INVALID_HANDLE_VALUE ) { // openned file is valid FILETIME lastWriteTime; BOOL rtnval = GetFileTime( hfile, NULL, NULL, &lastWriteTime ); SYSTEMTIME systemTime; rtnval = FileTimeToSystemTime( &lastWriteTime, &systemTime ); // perfect example of why Windows software is so awful if ( ( systemTime.wYear >= 1996 ) && ( systemTime.wMonth >= 8 ) && ( systemTime.wDay >= 24 ) ) correctWinsockVersion = TRUE; CloseHandle( hfile ); } } else correctWinsockVersion = TRUE; if ( !correctWinsockVersion ) { // Err: Your system is configured for another Domain Name System (DNS) server. // You might need to edit your DNS configuration. Check the User's Guide // for more information. char buf[ 255 ]; if ( getMsgString( buf, IDS_DNS_ALREADY ) ) displayErrMsgWnd( buf, MB_OK | MB_ICONASTERISK, NULL ); } } return; } //******************************************************************************** // CheckDUN // for Win95 // If user doesn't have Dial-Up Networking installed, they will have problem // setting up an account. //******************************************************************************** BOOL CheckDUN() { static const char c_szRNA[] = "rundll.exe setupx.dll,InstallHinfSection RNA 0 rna.inf"; BOOL bInstall = FALSE; HKEY hKey; LONG res; char szBuf[ MAX_PATH ]; // Let's see if its installed if( ERROR_SUCCESS != RegOpenKeyEx( HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Setup\\OptionalComponents\\RNA", NULL, KEY_QUERY_VALUE, &hKey ) ) bInstall = TRUE; // the key is there, was it actually installed though... if( !bInstall ) { DWORD cbData = sizeof( szBuf ); res = RegQueryValueEx( hKey, "Installed", NULL, NULL, (LPBYTE)szBuf, &cbData ); if ( szBuf[ 0 ] != '1' && szBuf[ 0 ] != 'Y' && szBuf[ 0 ] != 'y' ) bInstall = TRUE; } // make sure a random file from the installation exists so that we // know the user actually installed instead of just skipping over // the install step if( !bInstall ) { if( GetSystemDirectory( szBuf, sizeof( szBuf ) ) ) { // create a name of one of the files strcat( szBuf, "\\pppmac.vxd" ); // let's see if that file exists struct _stat stat_struct; if( _stat( szBuf, &stat_struct ) != 0 ) bInstall = TRUE; } } // if no Dial-Up Networking installed install it now if ( bInstall ) { // let the user not install it or exit // // Err: Dial-Up Networking has not been installed on this machine; // this product will not work until Dial-Up Networking is installed. // Would you like to install Dial-Up Networking now? char* buf = (char*)malloc(sizeof( char ) * 255 ); if ( !buf ) // Err: Out of Memory return FALSE; if ( getMsgString( buf, IDS_NO_DUN ) ) { if ( IDOK != displayErrMsgWnd( buf, MB_OKCANCEL | MB_ICONASTERISK, NULL ) ) { free( buf ); return FALSE; } } free( buf ); // install Dial-Up Networking PROCESS_INFORMATION pi; STARTUPINFO sti; UINT err = ERROR_SUCCESS; memset( &sti, 0, sizeof( sti ) ); sti.cb = sizeof( STARTUPINFO ); // Run the setup application if ( CreateProcess( NULL, (LPSTR)c_szRNA, NULL, NULL, FALSE, 0, NULL, NULL, &sti, &pi ) ) { CloseHandle( pi.hThread ); // Wait for the modem wizard process to complete WaitForSingleObject( pi.hProcess, INFINITE ); CloseHandle( pi.hProcess ); } } RegCloseKey( hKey ); return TRUE; } //******************************************************************************** // check if a user is an Administrator on NT40 //******************************************************************************** static BOOL isWinNTAdmin() { HANDLE hAccessToken; UCHAR infoBuffer[ 1024 ]; PTOKEN_GROUPS ptgGroups = (PTOKEN_GROUPS)infoBuffer; DWORD dwInfoBufferSize; PSID psidAdministrators; SID_IDENTIFIER_AUTHORITY siaNtAuthority = SECURITY_NT_AUTHORITY; UINT x; BOOL bSuccess; if ( !OpenProcessToken( GetCurrentProcess(), TOKEN_READ, &hAccessToken ) ) return FALSE; bSuccess = GetTokenInformation( hAccessToken, TokenGroups, infoBuffer, 1024, &dwInfoBufferSize ); CloseHandle( hAccessToken ); if( !bSuccess ) return FALSE; if( !AllocateAndInitializeSid( &siaNtAuthority, 2, SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0, &psidAdministrators ) ) return FALSE; // assume that we don't find the admin SID. bSuccess = FALSE; for ( x = 0; x < ptgGroups->GroupCount; x++ ) { if ( EqualSid( psidAdministrators, ptgGroups->Groups[ x ].Sid ) ) { bSuccess = TRUE; break; } } FreeSid( &psidAdministrators ); return bSuccess; } //******************************************************************************** // CheckDUN_NT // for WinNT40 // If user doesn't have Dial-Up Networking installed, they will have problem // setting up an account. //******************************************************************************** BOOL CheckDUN_NT() { BOOL bInstall = FALSE; BOOL bAdmin = FALSE; HKEY hKey; LONG res; char szBuf[ MAX_PATH ]; char* buf = NULL; // Let's see if its installed // "HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Services\\RemoteAccess" if ( ERROR_SUCCESS != RegOpenKeyEx( HKEY_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Services\\RemoteAccess", NULL, KEY_QUERY_VALUE, &hKey ) ) bInstall = TRUE; // the key is there, was it actually installed though... // look for some RAS keys szBuf[ 0 ] = '\0'; if ( !bInstall ) { DWORD cbData = sizeof( szBuf ); res = RegQueryValueEx( hKey, "DisplayName", NULL, NULL, (LPBYTE)szBuf, &cbData ); if( strlen( szBuf ) == 0 ) bInstall = TRUE; RegCloseKey( hKey ); // how about autodial manager.... // "HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Services\\RasAuto" if ( ERROR_SUCCESS != RegOpenKeyEx( HKEY_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Services\\RasAuto", NULL, KEY_QUERY_VALUE, &hKey ) ) bInstall = TRUE; RegCloseKey( hKey ); } // if no Dial-Up Networking installed, warn the users depending on // their premissions and return FALSE if ( bInstall ) { bAdmin = isWinNTAdmin(); if ( bAdmin ) { // Err: Dial-Up Networking has not been installed on this machine; // this product will not work until Dial-Up Networking is installed. // Pleas install Dial-Up Networking before running Accout Setup. char buf[ 255 ]; if ( getMsgString( buf, IDS_NO_DUN_NT ) ) displayErrMsgWnd( buf, MB_OK | MB_ICONASTERISK, NULL ); #if 0 // install Dial-Up Networking PROCESS_INFORMATION pi; STARTUPINFO sti; UINT err = ERROR_SUCCESS; char RASphone[ MAX_PATH ]; GetSystemDirectory( RASphone, MAX_PATH ); strcat( RASphone, "\\rasphone.exe" ); memset( &sti, 0, sizeof( sti ) ); sti.cb = sizeof( STARTUPINFO ); // Run the setup application if ( CreateProcess( (LPCTSTR)&RASphone, NULL, NULL, NULL, FALSE, 0, NULL, NULL, &sti, &pi ) ) { CloseHandle( pi.hThread ); // Wait for the Dial-Up Networking install process to complete WaitForSingleObject( pi.hProcess, INFINITE ); CloseHandle( pi.hProcess ); } #endif } else { // user need to have administrator premission to install, and ASW won't // work if DUN is not installed // Err: You do not have Administrator premission on this machine to intall // Dial-Up Networking. Please make sure you have Administrator premission // in order to install Dial-Up Networking first before running Account Setup. char buf[ 255 ]; if ( getMsgString( buf, IDS_NO_ADMIN_PREMISSION ) ) displayErrMsgWnd( buf, MB_OK | MB_ICONASTERISK, NULL ); } return FALSE; } return TRUE; } //******************************************************************************** // CreateDialerShortcut // Creates a shell shortcut to the PIDL //******************************************************************************** static short createDialerShortcut( char* szDesktop, // Desktop path LPCSTR accountName, // connectoid/phonebook entry name IMalloc* pMalloc, char* szPath, // path to PE folder char* strDesc, char* iconPath ) // shortcut description { HRESULT hres; LPITEMIDLIST pidl; char desktop[ MAX_PATH ]; DWORD cbData; HKEY hKey; long res; szDesktop[ 0 ] = '\0'; // gets Desktop folder path from registry for both win95 & winNT40 // "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders" if ( ERROR_SUCCESS != RegOpenKeyEx( HKEY_CURRENT_USER, REGSTR_PATH_SPECIAL_FOLDERS, NULL, KEY_QUERY_VALUE, &hKey ) ) return -3; // huh? cbData = MAX_PATH; res = RegQueryValueEx( hKey, "Desktop", NULL, NULL, (LPBYTE)desktop, &cbData ); RegCloseKey( hKey ); strcpy( szDesktop, desktop ); // win95 only if ( gPlatformOS == VER_PLATFORM_WIN32_WINDOWS ) { // Get a PIDL that points to the dial-up connection hres = getDialUpConnectionPIDL( accountName, &pidl ); if ( FAILED( hres ) ) { // Err: Unable to create shortcut to RNA phone book entry char* buf = (char*)malloc(sizeof( char ) * 255 ); if ( !buf ) // Err: Out of Memory return -6; // huh? if ( getMsgString( buf, IDS_NO_RNA ) ) { if ( IDOK != displayErrMsgWnd( buf, MB_OK | MB_ICONEXCLAMATION, NULL ) ) { free( buf ); return FALSE; } } free( buf ); return -1; } // If the dial-up networking folder is open when we create the RNA // entry, then we will have failed to get a PIDL above. The dial-up // networking folder itself won't display the icon until it is closed // and re-opened. There's nothing we can do but return if ( !pidl ) { pMalloc->Release(); return -2; // huh? } // Create a shortcut on the desktop char strPath[ MAX_PATH ]; strcpy( strPath, szDesktop ); strcat( strPath, "\\" ); strcat( strPath, strDesc ); strcat( strPath, ".Lnk" ); createLink( pidl, strPath, strDesc, iconPath ); // And one in our PE folder strcpy( strPath, szPath ); strcat( strPath, "\\" ); strcat( strPath, strDesc ); strcat( strPath, ".Lnk" ); createLink( pidl, strPath, strDesc, iconPath ); } else if ( gPlatformOS == VER_PLATFORM_WIN32_NT ) { // WinNT40 here // make sure the phonebook entry we created still exists char* sysDir = (char*)malloc(sizeof( char ) * MAX_PATH ); if ( !sysDir ) return -5; // huh? char pbPath[ MAX_PATH ]; GetSystemDirectory( sysDir, MAX_PATH ); strcpy( pbPath, sysDir ); strcat( pbPath, "\\ras\\rasphone.pbk" ); strcat( pbPath, "\0" ); free( sysDir ); RASENTRYNAME rasEntryName[ MAX_PATH ]; if ( !rasEntryName ) return -7; // huh? rasEntryName[ 0 ].dwSize = stRASENTRYNAME; DWORD size = stRASENTRYNAME * MAX_PATH; DWORD entries; if ( 0 != RasEnumEntries( NULL, pbPath, rasEntryName, &size, &entries ) ) return -4; BOOL exists = FALSE; DWORD i = 0; while ( ( i < entries) && ( !exists ) ) { if ( strcmp( rasEntryName[ i ].szEntryName, accountName ) == 0 ) exists = TRUE; i++; } // create a shortcut file on desktop if ( exists ) { HANDLE hfile = NULL; // create phonebook entry shortcut file on desktop, overwrites if exists SECURITY_ATTRIBUTES secAttrib; memset( &secAttrib, 0, sizeof( SECURITY_ATTRIBUTES ) ); secAttrib.nLength = sizeof( SECURITY_ATTRIBUTES ); secAttrib.lpSecurityDescriptor = NULL; secAttrib.bInheritHandle = FALSE; // construct phonebook entry shortcut file name char file[ MAX_PATH ]; strcpy( file, szDesktop ); strcat( file, "\\" ); strcat( file, accountName ); strcat( file, ".rnk" ); hfile = CreateFile( file, GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE, &secAttrib, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL ); if ( hfile == INVALID_HANDLE_VALUE ) return -9; // huh? CloseHandle( hfile ); hfile = NULL; // writes shortcut file data in the following format: // [Dial-Up Shortcut] // Entry=stuff // Phonebook=C:\WINNT40\System32\RAS\rasphone.pbk (default system phonebook) WritePrivateProfileString( "Dial-Up Shortcut", "Entry", accountName, file ); WritePrivateProfileString( "Dial-Up Shortcut", "Phonebook", pbPath, file ); // create the same shortcut file in our PE folder strcpy( file, szPath ); strcat( file, "\\" ); strcat( file, accountName ); strcat( file, ".rnk" ); hfile = CreateFile( file, GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE, &secAttrib, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL ); if ( hfile == INVALID_HANDLE_VALUE ) return -10; CloseHandle( hfile ); WritePrivateProfileString( "Dial-Up Shortcut", "Entry", accountName, file ); WritePrivateProfileString( "Dial-Up Shortcut", "Phonebook", pbPath, file ); } else return -8; // huh? } return 0; } //******************************************************************************** // createProgramItems // adds 2 icons: // Dialer - to Dial-Up Networking folder, Desktop & our PE folder // Navigator - to our PE folder //******************************************************************************** static short createProgramItems( LPCSTR accountName, LPCSTR iniPath, char* iconFile ) { char szPath[ MAX_PATH ]; LPITEMIDLIST pidl; char szBuf[ MAX_PATH ]; IMalloc* pMalloc; SHGetMalloc( &pMalloc ); // gets the path to "Programs" folder if ( gPlatformOS == VER_PLATFORM_WIN32_WINDOWS ) { SHGetSpecialFolderLocation( NULL, CSIDL_PROGRAMS, &pidl ); SHGetPathFromIDList( pidl, szBuf ); pMalloc->Free( pidl ); } else if ( gPlatformOS == VER_PLATFORM_WIN32_NT ) { // NT4.0: get the "Programs" folder for "All Users" HKEY hKey; DWORD bufsize = sizeof( szBuf ); if( ERROR_SUCCESS == RegOpenKeyEx( HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion", NULL, KEY_QUERY_VALUE, &hKey ) ) { RegQueryValueEx( hKey, "PathName", NULL, NULL, (LPBYTE)szBuf, &bufsize ); strcat( szBuf, "\\Profiles\\All Users\\Start Menu\\Programs" ); } else return -1; } // gets Netscape PE folder here char buf[ 256 ]; char* csFolderName; csFolderName = (char*)malloc(sizeof( char ) * 256 ); if ( !csFolderName ) return -4; // huh? strcpy( csFolderName, "Netscape Personal Edition" ); // check for custom folder name if( ::GetPrivateProfileString( "General", "InstallFolder", (const char*)csFolderName, buf, sizeof( buf ), iniPath ) ) strcpy( csFolderName, buf ); strcpy( szPath, szBuf ); strcat( szPath, "\\" ); strcat( szPath, csFolderName ); free( csFolderName ); // First do Dialer Icon // Create a dialer icon shortcut description char strDesc[ MAX_PATH ]; #ifdef UPGRADE if ( ???entryInfo.bUpgrading ) { char* csTmp = "Dialer"; strcpy( strDesc, accountName ); strcat( strDesc, " " ); strcat( strDesc, csTmp ); } else { strcpy( strDesc, "Dial" ); strcat( strDesc, " " ); strcat( strDesc, accountName ); } #else strcpy( strDesc, "Dial" ); strDesc[ strlen( strDesc ) + 1 ] = '\0'; strDesc[ strlen( strDesc ) ] = (char)32; strcat( strDesc, accountName ); #endif char szDesktop[ 512 ]; // create dialer shortcut icon on desktop and in PE folder int rtn = createDialerShortcut( szDesktop, accountName, pMalloc, szPath, strDesc, iconFile ); if ( rtn != 0 ) return rtn; #ifdef FOLDER_IN_START_MENU // Cleanup pMalloc->Free( pidl ); pMalloc->Release(); #endif ::Sleep( 250 ); return 0; } //******************************************************************************** // DesktopConfig // Sets up user's desktop (creates icons and short cuts) //******************************************************************************** void DesktopConfig( char* accountName, char* iconFileName, char* acctsetIniPath) { static char lastIconFile[ _MAX_PATH ] = { '\0' }; if ( iconFileName != NULL ) { // JS may pass us different file for icon file if ( ( iconFileName ) && ( strcmp( iconFileName, lastIconFile ) != 0 ) ) { if ( strcmp( lastIconFile, "" ) != 0 ) { if ( fileExists( lastIconFile ) ) // a temp icon file may already existed _unlink( lastIconFile ); } // check if icon file exists if ( fileExists( iconFileName ) ) strcpy( lastIconFile, iconFileName ); else lastIconFile[0] = '\0'; } } // remove the RegiServer RAS char regiRAS[ 50 ]; getMsgString( (char*)regiRAS, IDS_REGGIE_PROGITEM_NAME ); (*m_lpfnRasDeleteEntry)( NULL, (LPSTR)regiRAS ); // creates prgram icons in folders and desktop int ret = createProgramItems( accountName, acctsetIniPath, lastIconFile ); } //******************************************************************************** // QuitNavigator // quits the navigator //******************************************************************************** void QuitNavigator() { // Bug#112622 - don't broadcast this, java catches it and dies. // Instead, find the hidden window and tell _it_ what to do. // The strings in this call are hard-coded because the constants needed // do not exist and multiple places are doing similar things. The // values themselves come from winfe's Netscape.cpp. HWND hWnd = FindWindowEx( NULL, NULL, "aHiddenFrameClass", "Netscape's Hidden Frame" ); PostMessage(/*HWND_BROADCAST*/ hWnd, WM_COMMAND, ID_APP_SUPER_EXIT, 0L ); } //******************************************************************************** // getCurrentProfileDirectory // gets the current Navigator user profile directory //******************************************************************************** extern char* GetCurrentProfileDirectory() { char* profilePath = NULL; int bufSize = 256; char buf[ 256 ]; buf[ 0 ] = '\0'; if ( PREF_OK == PREF_GetCharPref( "profile.directory", buf, &bufSize ) ) { // make sure we append the last '\' in the profile dir path strcat( buf, "\\" ); trace( "profile.cpp : GetCurrentProfileDirectory : Got the Current User profile = %s", buf ); } else trace( "profile.cpp : GetCurrentProfileDirectory : Error in obtaining Current User profile" ); profilePath = strdup( buf ); return profilePath; } //******************************************************************************** // GetCurrentProfileName // gets the current Navigator user profile name //******************************************************************************** extern char* GetCurrentProfileName() { char* profileName = NULL; int bufSize = 256; char buf[ 256 ]; buf[ 0 ] = '\0'; if ( PREF_OK == PREF_GetCharPref( "profile.name", buf, &bufSize ) ) trace( "profile.cpp : GetCurrentProfileDirectory : Got the Current profile name = %s", buf ); else trace( "profile.cpp : GetCurrentProfileName : Error in obtaining Current User profile" ); profileName = strdup( buf ); return profileName; } //******************************************************************************** // SetCurrentProfileName // changes the current Navigator user profile name to a different name //******************************************************************************** void SetCurrentProfileName( char* profileName ) { assert( profileName ); if ( NULL == profileName ) // abort if string allocation fails return; if ( PREF_ERROR == PREF_SetDefaultCharPref( "profile.name", profileName ) ) trace( "profile.cpp : SetCurrentProfileName : Error in setting Current User profile name." ); else { trace( "profile.cpp : SetCurrentProfileName : Current User profile is set to = %s", profileName ); if ( PREF_ERROR == PREF_SetDefaultBoolPref( "profile.temporary", FALSE ) ) trace( "profile.cpp : SetCurrentProfileName : Error in setting Temporary flag to false." ); else trace( "profile.cpp : SetCurrentProfileName : Made the profile to be permanent." ); } } // The format of the entry is // LocationX=Y,"name","outside-line-local","outside-line-long-D","area-code",1,0,0,1,"",tone=0,"call-waiting-string" typedef struct tapiLineStruct { int nIndex; char csLocationName[ 60 ]; char csOutsideLocal[ 20 ]; char csOutsideLongDistance[ 20 ]; char csAreaCode[ 20 ]; int nCountryCode; int nCreditCard; int nDunnoB; int nDunnoC; char csDialAsLongDistance[ 10 ]; int nPulseDialing; char csCallWaiting[ 20 ]; } TAPILINE; //******************************************************************************** // readNextInt // Pull an int off the front of the string and return the new string ptr //******************************************************************************** char* readNextInt( char* pInString, int* pInt ) { char* pStr; char buf[ 32 ]; if ( !pInString ) { *pInt = 0; return NULL; } // copy the string over. This strchr should be smarter pStr = strchr( pInString, ',' ); if ( !pStr ) { *pInt = 0; return NULL; } // convert the string strncpy( buf, pInString, pStr - pInString ); buf[ pStr - pInString ] = '\0'; *pInt = atoi( buf ); // return the part after the int return ( pStr + 1 ); } //******************************************************************************** // readNextString // Pull a string from the front of the incoming string and return // the first character after the string //******************************************************************************** char* readNextString( char* pInString, char* csString ) { csString[ 0 ] = '\0'; int i = 0, x = 0; BOOL copy = FALSE; char newpInString[ MAX_PATH ]; if ( !pInString ) { csString = ""; return NULL; } // skip over first quote if ( pInString[ i ] == '\"' ) i++; // copy over stuff by hand line a moron while ( pInString[ i ] != '\"' ) { //strcat(csString, (char *)pInString[i]); csString[ x ] = pInString[ i ]; i++; x++; copy = TRUE; } if ( copy ) csString[ x ] = '\0'; // skip over the closing quote if( pInString[ i ] == '\"' ) i++; // skip over the comma at the end if( pInString[ i ] == ',' ) i++; newpInString[ 0 ]='\0'; x = 0; for ( unsigned short j = i; j < strlen( pInString ); j++ ) { //strcat(newpInString, (char *)pInString[j]); newpInString[ x ] = pInString[ j ]; x++; } newpInString[ x ]='\0'; strcpy( pInString, newpInString ); return pInString; } //******************************************************************************** // readTapiLine // Read a line out of the telephon.ini file and fill the stuff in //******************************************************************************** void readTapiLine( char* lpszFile, int nLineNumber, TAPILINE* line ) { char buf[ 256 ]; char pLocation[ 128 ]; sprintf( pLocation, "Location%d", nLineNumber ); ::GetPrivateProfileString( "Locations", pLocation, "", buf, sizeof( buf ), lpszFile ); char* pString = buf; pString = readNextInt( pString, &line->nIndex ); pString = readNextString( pString, (char *)&line->csLocationName ); pString = readNextString( pString, (char *)&line->csOutsideLocal ); pString = readNextString( pString, (char *)&line->csOutsideLongDistance ); pString = readNextString( pString, (char *)&line->csAreaCode ); pString = readNextInt( pString, &line->nCountryCode ); pString = readNextInt( pString, &line->nCreditCard ); pString = readNextInt( pString, &line->nDunnoB ); pString = readNextInt( pString, &line->nDunnoC ); pString = readNextString( pString, (char *)&line->csDialAsLongDistance ); pString = readNextInt( pString, &line->nPulseDialing ); pString = readNextString( pString, (char *)&line->csCallWaiting ); } //******************************************************************************** // writeTapiLine // Given a tapiLine structure write it out to telephon.ini //******************************************************************************** void writeTapiLine( char* lpszFile, int nLineNumber, TAPILINE* line ) { char buffer[ 256 ]; sprintf( buffer, "%d,\"%s\",\"%s\",\"%s\",\"%s\",%d,%d,%d,%d,\"%s\",%d,\"%s\"", line->nIndex, (const char*) line->csLocationName, (const char*) line->csOutsideLocal, (const char*) line->csOutsideLongDistance, (const char*) line->csAreaCode, line->nCountryCode, line->nCreditCard, line->nDunnoB, line->nDunnoC, (const char*) line->csDialAsLongDistance, line->nPulseDialing, (const char*) line->csCallWaiting ); char pLocation[ 32 ]; sprintf( pLocation, "Location%d", nLineNumber ); ::WritePrivateProfileString( "Locations", pLocation, buffer, lpszFile ); } //******************************************************************************** // SetLocationInfo // sets the location info for win95 dialers // The format of the entry is // LocationX=Y,"name","outside-line-local","outside-line-long-D","area-code",1,0,0,1,"",tone=0,"call-waiting-string" //******************************************************************************** BOOL SetLocationInfo( ACCOUNTPARAMS account, LOCATIONPARAMS location ) { // first read information from telephon.ini char buf[ 256 ]; // get windows directory char lpszDir[ MAX_PATH ]; if ( GetWindowsDirectory( lpszDir, MAX_PATH ) == 0 ) return FALSE; // huh? strcat( lpszDir, "\\telephon.ini" ); // now we build new line information based on the old one and some info // see if there were any locations to begin with ::GetPrivateProfileString( "Locations", "CurrentLocation", "", buf, sizeof( buf ), lpszDir ); if( buf[ 0 ] == '\0' ) { // build the string TAPILINE line; line.nIndex = 0; strcpy( line.csLocationName, "Default Location" ); strcpy( line.csOutsideLocal, location.OutsideLineAccess ); strcpy( line.csOutsideLongDistance, location.OutsideLineAccess ); strcpy( line.csAreaCode, location.UserAreaCode ); line.nCountryCode = location.UserCountryCode; line.nCreditCard = 0; line.nDunnoB = 0; line.nDunnoC = 1; if ( location.DialAsLongDistance == TRUE ) strcpy( line.csDialAsLongDistance, "528" ); else strcpy( line.csDialAsLongDistance, "" ); line.nPulseDialing = ( location.DialType == 0 ? 1 : 0 ); if( location.DisableCallWaiting ) strcpy( line.csCallWaiting, location.DisableCallWaitingCode ); else strcpy( line.csCallWaiting, "" ); writeTapiLine( lpszDir, 0, &line ); // need to create a whole location section ::WritePrivateProfileString( "Locations", "CurrentLocation", "0,0", lpszDir ); ::WritePrivateProfileString( "Locations", "Locations", "1,1", lpszDir ); ::WritePrivateProfileString( "Locations", "Inited", "1", lpszDir ); } else { int nId, nCount; sscanf( buf, "%d,%d", &nId, &nCount ); // read the line TAPILINE line; readTapiLine( lpszDir, nId, &line ); strcpy( line.csOutsideLocal, location.OutsideLineAccess ); strcpy( line.csOutsideLongDistance, location.OutsideLineAccess ); if ( location.DisableCallWaiting ) strcpy( line.csCallWaiting, location.DisableCallWaitingCode ); else strcpy( line.csCallWaiting, "" ); line.nPulseDialing = ( location.DialType == 0 ? 1 : 0 ); if ( strcmp( location.UserAreaCode, "" ) != 0 ) strcpy( line.csAreaCode, location.UserAreaCode ); if ( location.DialAsLongDistance == TRUE ) strcpy( line.csDialAsLongDistance, "528" ); else strcpy( line.csDialAsLongDistance, "" ); // write the line back out writeTapiLine( lpszDir, nId, &line ); } return TRUE; } //******************************************************************************** // SetLocationInfoNT // sets the location info for winNT dialers //******************************************************************************** BOOL SetLocationInfoNT( ACCOUNTPARAMS account, LOCATIONPARAMS location ) { LINEINITIALIZEEXPARAMS m_LineInitExParams; HLINEAPP m_LineApp; DWORD dwNumDevs; LINETRANSLATECAPS m_LineTranslateCaps; DWORD dwApiVersion = 0x00020000; // Initialize TAPI. in order to get current location ID m_LineInitExParams.dwOptions = LINEINITIALIZEEXOPTION_USEEVENT; m_LineInitExParams.dwTotalSize = sizeof( LINEINITIALIZEEXPARAMS ); m_LineInitExParams.dwNeededSize = sizeof( LINEINITIALIZEEXPARAMS ); if ( lineInitialize( &m_LineApp, gDLL, lineCallbackFuncNT, NULL, &dwNumDevs) != 0 ) { char buf[ 255 ]; if ( getMsgString( buf, IDS_NO_TAPI ) ) displayErrMsgWnd( buf, MB_OK | MB_ICONEXCLAMATION, NULL ); return FALSE; } m_LineTranslateCaps.dwTotalSize = sizeof( LINETRANSLATECAPS ); m_LineTranslateCaps.dwNeededSize = sizeof( LINETRANSLATECAPS ); if ( lineGetTranslateCaps( m_LineApp, dwApiVersion, &m_LineTranslateCaps ) != 0 ) return FALSE; //m_LineTranslateCaps.dwCurrentLocationID // gets the location info from registry HKEY hKey; char* keyPath = (char*)malloc( sizeof( char ) * 512 ); assert( keyPath ); if ( !keyPath ) return FALSE; strcpy( keyPath, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Telephony\\locations" ); // finds the user profile location in registry if( ERROR_SUCCESS != RegOpenKeyEx( HKEY_LOCAL_MACHINE, keyPath, NULL, KEY_ALL_ACCESS, &hKey ) ) return FALSE; DWORD subKeys; DWORD maxSubKeyLen; DWORD maxClassLen; DWORD values; DWORD maxValueNameLen; DWORD maxValueLen; DWORD securityDescriptor; FILETIME lastWriteTime; // get some information about this reg key if ( ERROR_SUCCESS != RegQueryInfoKey( hKey, NULL, NULL, NULL, &subKeys, &maxSubKeyLen, &maxClassLen, &values, &maxValueNameLen, &maxValueLen, &securityDescriptor, &lastWriteTime ) ) return FALSE; // now loop through the location keys to find the one that matches current location ID if ( subKeys > 0 ) { DWORD subkeyNameSize = maxSubKeyLen + 1; char subkeyName[ 20 ]; for ( DWORD index = 0; index < subKeys; index++ ) { // gets a location key name if ( ERROR_SUCCESS != RegEnumKey( hKey, index, subkeyName, subkeyNameSize ) ) return FALSE; // try open location key char newSubkeyPath[ 260 ]; HKEY hkeyNewSubkey; strcpy( (char*)newSubkeyPath, keyPath ); strcat( (char*)newSubkeyPath, "\\" ); strcat( (char*)newSubkeyPath, subkeyName ); if ( ERROR_SUCCESS != RegOpenKeyEx( HKEY_LOCAL_MACHINE, (char*)newSubkeyPath, NULL, KEY_ALL_ACCESS, &hkeyNewSubkey ) ) return FALSE; DWORD valbuf; DWORD type = REG_SZ; DWORD bufsize = 20; // get location key's ID value if ( ERROR_SUCCESS != RegQueryValueEx( hkeyNewSubkey, "ID", NULL, &type, (LPBYTE)&valbuf, &bufsize ) ) return FALSE; // if it matches the default location ID if ( valbuf == m_LineTranslateCaps.dwCurrentLocationID ) { // we got the location we want, now change the pulse/tone flag DWORD flagsVal; if ( location.DialType == 0 ) if ( location.DisableCallWaiting ) flagsVal = 4; else flagsVal = 0; else if ( location.DisableCallWaiting ) flagsVal = 5; else flagsVal = 1; if ( ERROR_SUCCESS != RegSetValueEx( hkeyNewSubkey, "Flags", NULL, type, (LPBYTE)&flagsVal, bufsize ) ) return FALSE; // sets the OutsideAccess if ( ERROR_SUCCESS != RegSetValueEx( hkeyNewSubkey, "OutsideAccess", NULL, REG_SZ, (LPBYTE)&location.OutsideLineAccess, strlen(location.OutsideLineAccess ) + 1 ) ) return FALSE; if ( ERROR_SUCCESS != RegSetValueEx( hkeyNewSubkey, "LongDistanceAccess", NULL, REG_SZ, (LPBYTE)&location.OutsideLineAccess, strlen(location.OutsideLineAccess ) + 1 ) ) return FALSE; // sets call waiting char* callwaiting; if( location.DisableCallWaiting ) callwaiting = location.DisableCallWaitingCode; else callwaiting =""; if ( ERROR_SUCCESS != RegSetValueEx( hkeyNewSubkey, "DisableCallWaiting", NULL, REG_SZ, (LPBYTE)callwaiting, strlen( callwaiting ) + 1 ) ) return FALSE; // sets user's area code if( strcmp( location.UserAreaCode, "" ) != 0 ) { if ( ERROR_SUCCESS != RegSetValueEx( hkeyNewSubkey, "AreaCode", NULL, REG_SZ, (LPBYTE)location.UserAreaCode, strlen( location.UserAreaCode ) + 1 ) ) return FALSE; } else { // check if we're international, and force a default area code, so that we don't get an error creating a dialer if ( account.IntlMode ) { char* code = "415"; if ( ERROR_SUCCESS != RegSetValueEx( hkeyNewSubkey, "AreaCode", NULL, REG_SZ, (LPBYTE)code, strlen( code ) + 1 ) ) return FALSE; } } RegCloseKey( hkeyNewSubkey ); break; } RegCloseKey( hkeyNewSubkey ); } } RegCloseKey( hKey ); return TRUE; } //******************************************************************************** // native method: // CheckEnvironment // checks for DUN, RAS function loading correctly //******************************************************************************** BOOL CheckEnvironment() { // try loading RAS routines in RAS dlls // if fails return FALSE switch ( gPlatformOS ) { case VER_PLATFORM_WIN32_NT: // NT //check if it's WinNT40 first if ( !LoadRasFunctionsNT( "RASAPI32.DLL" ) ) { // Err: Unable to dynamically load extended RAS functions! char* buf = (char*)malloc( sizeof( char ) * 255 ); if ( buf ) { if ( getMsgString( buf, IDS_NO_RAS_FUNCTIONS ) ) displayErrMsgWnd( buf, MB_OK | MB_ICONEXCLAMATION, NULL ); free( buf ); } return FALSE; } break; case VER_PLATFORM_WIN32_WINDOWS: // defaults to win95 if ( !LoadRasFunctions( "RASAPI32.DLL" ) && !LoadRasFunctions( "RNAPH.DLL" ) ) { // Err: Unable to dynamically load extended RAS functions! char* buf = (char*)malloc( sizeof( char ) * 255 ); if ( buf ) { if ( getMsgString( buf, IDS_NO_RAS_FUNCTIONS ) ) displayErrMsgWnd( buf, MB_OK | MB_ICONEXCLAMATION, NULL); free( buf ); } return FALSE; } break; } // Check to make sure Dial-Up Networking is installed. // It may be uninstalled by user. // return FALSE if Dialup Networking is not installed switch ( gPlatformOS ) { case VER_PLATFORM_WIN32_NT: if ( FALSE == CheckDUN_NT() ) { char buf[ 255 ]; if ( getMsgString( (char*)buf, IDS_NO_DUN_INSTALLED ) ) displayErrMsgWnd( (char*)buf, MB_OK | MB_ICONEXCLAMATION, NULL ); return FALSE; } break; default: if ( FALSE == CheckDUN() ) { char buf[ 255 ]; if ( getMsgString( (char*)buf, IDS_NO_DUN_INSTALLED ) ) displayErrMsgWnd( (char*)buf, MB_OK | MB_ICONEXCLAMATION, NULL ); return FALSE; } break; } // for win95 only: // Check to see if DNS is already configured for a LAN connection. // If so warn the user that this may cause conflicts, and continue. if ( gPlatformOS == VER_PLATFORM_WIN32_WINDOWS ) CheckDNS(); return TRUE; }