mirror of https://github.com/lianthony/NT4.0
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
8926 lines
243 KiB
8926 lines
243 KiB
/*++ BUILD Version: 0000 // Increment this if a change has global effects
|
|
|
|
Copyright (c) 1995 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
dial.c
|
|
|
|
Abstract:
|
|
|
|
Dialhelper
|
|
|
|
Author:
|
|
|
|
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
|
|
#if DBG
|
|
#define InternalDebugOut(_x_) DbgPrt _x_
|
|
#else
|
|
#define InternalDebugOut(_x_)
|
|
#endif
|
|
|
|
|
|
#include <windows.h>
|
|
#include <windowsx.h>
|
|
|
|
#if WINNT
|
|
#else
|
|
#include <help.h>
|
|
#endif
|
|
|
|
#include "tchar.h"
|
|
#include "prsht.h"
|
|
#include "stdlib.h"
|
|
#include "tapi.h"
|
|
#include "tspi.h"
|
|
#include "clientr.h"
|
|
#include "client.h"
|
|
#include "private.h"
|
|
#include "card.h"
|
|
#include "location.h"
|
|
#include "general.h"
|
|
|
|
|
|
|
|
#undef lineBlindTransfer
|
|
#undef lineConfigDialog
|
|
#undef lineConfigDialogEdit
|
|
#undef lineDial
|
|
#undef lineForward
|
|
#undef lineGatherDigits
|
|
#undef lineGenerateDigits
|
|
#undef lineGetAddressCaps
|
|
#undef lineGetAddressID
|
|
#undef lineGetAddressStatus
|
|
#undef lineGetCallInfo
|
|
#undef lineGetDevCaps
|
|
#undef lineGetDevConfig
|
|
#undef lineGetIcon
|
|
#undef lineGetID
|
|
#undef lineGetLineDevStatus
|
|
#undef lineGetRequest
|
|
#undef lineGetTranslateCaps
|
|
#undef lineHandoff
|
|
#undef lineMakeCall
|
|
#undef lineOpen
|
|
#undef linePark
|
|
#undef linePickup
|
|
#undef linePrepareAddToConference
|
|
#undef lineRedirect
|
|
#undef lineSetDevConfig
|
|
#undef lineSetTollList
|
|
#undef lineSetupConference
|
|
#undef lineSetupTransfer
|
|
#undef lineTranslateAddress
|
|
#undef lineUnpark
|
|
#undef phoneConfigDialog
|
|
#undef phoneGetButtonInfo
|
|
#undef phoneGetDevCaps
|
|
#undef phoneGetIcon
|
|
#undef phoneGetID
|
|
#undef phoneGetStatus
|
|
#undef phoneSetButtonInfo
|
|
#undef tapiGetLocationInfo
|
|
#undef tapiRequestMakeCall
|
|
#undef tapiRequestMediaCall
|
|
#undef lineAddProvider
|
|
#undef lineGetAppPriority
|
|
#undef lineGetCountry
|
|
#undef lineGetProviderList
|
|
#undef lineSetAppPriority
|
|
#undef lineTranslateDialog
|
|
|
|
|
|
//***************************************************************************
|
|
//***************************************************************************
|
|
extern BOOL CALLBACK CallingCardProc( HWND, UINT, WPARAM, LPARAM );
|
|
|
|
|
|
//***************************************************************************
|
|
//***************************************************************************
|
|
#define IsWDigit(c) (((WCHAR)(c)) >= (WCHAR)'0' && ((WCHAR)(c)) <= (WCHAR)'9')
|
|
#define IsDigit(c) (((CHAR)(c)) >= (CHAR)'0' && ((CHAR)(c)) <= (CHAR)'9')
|
|
|
|
|
|
|
|
//***************************************************************************
|
|
extern HINSTANCE ghInst;
|
|
extern CRITICAL_SECTION gUICriticalSection;
|
|
|
|
|
|
//***************************************************************************
|
|
|
|
BOOL gbInternalTranslate = FALSE;
|
|
BOOL gbTranslateSimple = FALSE;
|
|
BOOL gbTranslateSilent = FALSE;
|
|
|
|
PWSTR gpszAddress = NULL;
|
|
|
|
PLOCATION gLocationList = NULL;
|
|
UINT gnNumLocations = 0;
|
|
UINT gnCurrentLocationID = 0;
|
|
|
|
|
|
|
|
PLOCATION gpCurrentLocation = NULL;
|
|
|
|
|
|
|
|
const WCHAR gszLocationW[] = L"Location";
|
|
const WCHAR gszLocationsW[] = L"Locations";
|
|
const CHAR gszNullString[] = "";
|
|
WCHAR gszNullStringW[] = L"";
|
|
|
|
WCHAR gszNameW[] = L"Name";
|
|
WCHAR gszIDW[] = L"ID";
|
|
WCHAR gszAreaCodeW[] = L"AreaCode";
|
|
WCHAR gszCountryW[] = L"Country";
|
|
WCHAR gszOutsideAccessW[] = L"OutsideAccess";
|
|
WCHAR gszLongDistanceAccessW[] = L"LongDistanceAccess";
|
|
WCHAR gszFlagsW[] = L"Flags";
|
|
WCHAR gszCallingCardW[] = L"CallingCard";
|
|
WCHAR gszDisableCallWaitingW[] = L"DisableCallWaiting";
|
|
WCHAR gszTollListW[] = L"TollList";
|
|
|
|
WCHAR gszCardW[] = L"Card";
|
|
WCHAR gszPinW[] = L"Pin";
|
|
const WCHAR gszCardsW[] = L"Cards";
|
|
WCHAR gszLocalRuleW[] = L"LocalRule";
|
|
WCHAR gszLDRuleW[] = L"LDRule";
|
|
WCHAR gszInternationalRuleW[] = L"InternationalRule";
|
|
|
|
WCHAR gszNumEntriesW[] = L"NumEntries";
|
|
WCHAR gszCurrentIDW[] = L"CurrentID";
|
|
WCHAR gszNextIDW[] = L"NextID";
|
|
|
|
|
|
const WCHAR gszTelephonyKey[] = L"Software\\Microsoft\\Windows\\CurrentVersion\\Telephony";
|
|
//const WCHAR gszCardKeyW[] = L"Software\\Microsoft\\Windows\\CurrentVersion\\Telephony\\Cards";
|
|
//const WCHAR gszLocationKeyW[] = L"Software\\Microsoft\\Windows\\CurrentVersion\\Telephony\\Locations";
|
|
|
|
|
|
//char __based(__segname("DIALAGE")) csSCANTO[] = "|^\r";
|
|
const WCHAR csSCANTO[] = L"|^\r";
|
|
const WCHAR csSPECIAL[] = L"$@W?";
|
|
const WCHAR csBADCO[] = L"AaBbCcDdPpTtWw*#!,@$?;()";
|
|
const WCHAR csDISPSUPRESS[] = L"TtPp,Ww@?!$";
|
|
|
|
#define CITY_MANDATORY (1)
|
|
#define CITY_OPTIONAL (-1)
|
|
#define CITY_NONE (0)
|
|
|
|
|
|
//***************************************************************************
|
|
//***************************************************************************
|
|
//***************************************************************************
|
|
LONG PASCAL IsThisAPIVersionInvalid( DWORD dwAPIVersion )
|
|
{
|
|
if (
|
|
( 0x00010003 != dwAPIVersion )
|
|
&&
|
|
( 0x00010004 != dwAPIVersion )
|
|
&&
|
|
( 0x00020000 != dwAPIVersion )
|
|
)
|
|
{
|
|
return LINEERR_INCOMPATIBLEAPIVERSION;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
|
|
//***************************************************************************
|
|
//***************************************************************************
|
|
//***************************************************************************
|
|
//
|
|
// Copies a string (up to endC). Returns NULL on error. If source
|
|
// is null, returns lpDest.
|
|
//
|
|
LPWSTR CopyStringToChar( LPWSTR lpSrc,
|
|
WCHAR endC,
|
|
LPWSTR lpDest,
|
|
LPWSTR lpEnd
|
|
)
|
|
{
|
|
if (lpSrc != NULL && lpDest != NULL)
|
|
{
|
|
while (*lpSrc != endC)
|
|
{
|
|
if ( lpDest < lpEnd )
|
|
*lpDest = *lpSrc;
|
|
|
|
// if ( IsDBCSLeadByte((BYTE)*lpSrc) )
|
|
// {
|
|
// if ( lpDest < lpEnd )
|
|
// *(++lpDest) = *(++lpSrc);
|
|
// }
|
|
|
|
lpSrc++;
|
|
lpDest++;
|
|
}
|
|
}
|
|
return lpDest;
|
|
}
|
|
|
|
|
|
|
|
//***************************************************************************
|
|
//***************************************************************************
|
|
//***************************************************************************
|
|
/*--------------------------------------------------------------------------*\
|
|
|
|
Function: Unscrambler
|
|
|
|
Purpose:
|
|
This is the UN version of Scrambler
|
|
|
|
\*--------------------------------------------------------------------------*/
|
|
UINT WINAPI Unscrambler( DWORD dwKey,
|
|
LPWSTR lpszSrc,
|
|
LPWSTR lpszDst )
|
|
|
|
{
|
|
UINT uIndex;
|
|
UINT uSubKey;
|
|
UINT uNewKey;
|
|
UINT uResult = 0;
|
|
|
|
InternalDebugOut((50, "Entering Unscrambler"));
|
|
if ( !lpszSrc || !lpszDst )
|
|
{
|
|
// uResult = INI_ERR_INVALID_ARG;
|
|
goto done;
|
|
}
|
|
|
|
uNewKey = (UINT)dwKey & 0x7FFF;
|
|
uSubKey = (UINT)dwKey % 10;
|
|
|
|
for ( uIndex = 1; *lpszSrc ; lpszSrc++, lpszDst++, uIndex++ )
|
|
{
|
|
if ( IsWDigit( *lpszSrc ))
|
|
{
|
|
// do the unscramble thang
|
|
//------------------------
|
|
uSubKey = ((*lpszSrc - (WCHAR)'0') - ((uSubKey + uIndex + uNewKey) % 10) + 10) % 10;
|
|
*lpszDst = (WCHAR)(uSubKey + (WCHAR)'0');
|
|
}
|
|
else
|
|
*lpszDst = *lpszSrc; // just save the byte
|
|
}
|
|
|
|
// uResult = INI_SUCCESS;
|
|
|
|
done:
|
|
*lpszDst = (WCHAR)'\0';
|
|
InternalDebugOut((60, "Leaving Unscrambler"));
|
|
return( uResult );
|
|
}
|
|
|
|
|
|
|
|
//***************************************************************************
|
|
//***************************************************************************
|
|
// Copies an unscrambled version of string to lpDest.
|
|
// NOTE: we have modified Toby's algorithm to avoid 32 bit MOD, by taking
|
|
// dwKey MOD 32768 as our key.
|
|
|
|
//LPTSTR PASCAL CopyScrambled( LPTSTR lpszSrc,
|
|
void PASCAL CopyScrambled( LPWSTR lpszSrc,
|
|
LPWSTR lpszDst,
|
|
DWORD dwKey
|
|
)
|
|
{
|
|
UINT uIndex;
|
|
UINT uSubKey;
|
|
UINT uNewKey;
|
|
UINT uResult = 0;
|
|
|
|
InternalDebugOut((50, "Entering IniScrambler"));
|
|
if ( !lpszSrc || !lpszDst )
|
|
{
|
|
// uResult = INI_ERR_INVALID_ARG;
|
|
goto done;
|
|
} // end if
|
|
|
|
uNewKey = (UINT)dwKey & 0x7FFF;
|
|
uSubKey = (UINT)dwKey % 10;
|
|
|
|
for ( uIndex = 1; *lpszSrc ; lpszSrc++, lpszDst++, uIndex++ )
|
|
{
|
|
if ( IsWDigit( *lpszSrc ))
|
|
{
|
|
// do the scramble thang
|
|
//----------------------
|
|
*lpszDst = (WCHAR)(((uSubKey + (*lpszSrc - (WCHAR)'0') + uIndex + uNewKey) % 10) + (WCHAR)'0');
|
|
uSubKey = (UINT)(*lpszSrc - (WCHAR)'0');
|
|
}
|
|
else
|
|
*lpszDst = *lpszSrc; // just save the byte
|
|
} // end for
|
|
|
|
// uResult = INI_SUCCESS;
|
|
|
|
|
|
done:
|
|
|
|
*lpszDst = (WCHAR)'\0';
|
|
InternalDebugOut((60, "Leaving IniScrambler"));
|
|
|
|
return; //( uResult );
|
|
}
|
|
|
|
|
|
|
|
//***************************************************************************
|
|
//***************************************************************************
|
|
//***************************************************************************
|
|
|
|
DWORD GetNumberOfCards()
|
|
{
|
|
DWORD dwNumCards;
|
|
|
|
HKEY hKey;
|
|
HKEY hKey2;
|
|
DWORD dwDataType;
|
|
DWORD dwDataSize;
|
|
|
|
//*** *** ***BUGBUG
|
|
//should do a read of an entire key and get the # of cards from there -
|
|
//no need to keep a separate # cards field (name of subkeys is name of card?)
|
|
|
|
RegOpenKeyExW(
|
|
HKEY_CURRENT_USER,
|
|
gszTelephonyKey,
|
|
0,
|
|
KEY_READ,
|
|
&hKey2
|
|
);
|
|
|
|
RegOpenKeyExW(
|
|
hKey2,
|
|
gszCardsW,
|
|
0,
|
|
KEY_READ,
|
|
&hKey
|
|
);
|
|
|
|
dwDataSize = sizeof(dwNumCards);
|
|
dwNumCards = 0;
|
|
RegQueryValueExW(
|
|
hKey,
|
|
gszNumEntriesW,
|
|
0,
|
|
&dwDataType,
|
|
(LPBYTE)&dwNumCards,
|
|
&dwDataSize
|
|
);
|
|
|
|
|
|
//*** *** ***BUGBUG It's _REALLY_ bad if dwNumCards is zero for any
|
|
// reason. Should probably fail the function on the spot...
|
|
//
|
|
|
|
RegCloseKey( hKey );
|
|
RegCloseKey( hKey2);
|
|
|
|
|
|
return dwNumCards;
|
|
}
|
|
|
|
|
|
|
|
//***************************************************************************
|
|
//***************************************************************************
|
|
//***************************************************************************
|
|
|
|
void CheckCards()
|
|
{
|
|
DWORD dwNumCards;
|
|
DWORD n;
|
|
HKEY hKey;
|
|
HKEY hKey2;
|
|
HKEY hKey3;
|
|
WCHAR szCurrentCardKey[256];
|
|
WCHAR pBuf[512];
|
|
PWSTR pBufTempPtr;
|
|
|
|
|
|
if ( 0 == GetNumberOfCards() )
|
|
{
|
|
|
|
DWORD dwDisposition;
|
|
|
|
LoadString( ghInst, RC_CARD_ID_BASE, (LPSTR)szCurrentCardKey, sizeof(szCurrentCardKey)/sizeof(WCHAR) );
|
|
|
|
dwNumCards = atoi( (LPSTR)szCurrentCardKey );
|
|
|
|
|
|
RegCreateKeyExW(
|
|
HKEY_CURRENT_USER,
|
|
gszTelephonyKey,
|
|
0,
|
|
gszNullStringW, //Class - what class?
|
|
REG_OPTION_NON_VOLATILE,
|
|
KEY_ALL_ACCESS,
|
|
0,
|
|
&hKey3,
|
|
&dwDisposition
|
|
);
|
|
|
|
|
|
RegCreateKeyExW(
|
|
hKey3,
|
|
gszCardsW,
|
|
0,
|
|
gszNullStringW, //Class - what class?
|
|
REG_OPTION_NON_VOLATILE,
|
|
KEY_ALL_ACCESS,
|
|
0,
|
|
&hKey2,
|
|
&dwDisposition
|
|
);
|
|
|
|
|
|
RegSetValueExW(
|
|
hKey2,
|
|
gszNumEntriesW,
|
|
0,
|
|
REG_DWORD,
|
|
(LPBYTE)&dwNumCards,
|
|
sizeof(DWORD)
|
|
);
|
|
|
|
RegSetValueExW(
|
|
hKey2,
|
|
gszNextIDW,
|
|
0,
|
|
REG_DWORD,
|
|
(LPBYTE)&dwNumCards,
|
|
sizeof(DWORD)
|
|
);
|
|
|
|
|
|
for (n = 0; n < dwNumCards; n++)
|
|
{
|
|
DWORD dwDisposition;
|
|
|
|
PWSTR pName;
|
|
PWSTR pPin;
|
|
PWSTR pLocalRule;
|
|
PWSTR pLDRule;
|
|
PWSTR pInternationalRule;
|
|
DWORD dwFlags;
|
|
|
|
|
|
|
|
|
|
wsprintfW(szCurrentCardKey, L"%ls%d",
|
|
gszCardW,
|
|
n
|
|
);
|
|
|
|
|
|
|
|
LoadStringW( ghInst,
|
|
RC_CARD_ID_BASE + n + 1,
|
|
pBuf,
|
|
sizeof(pBuf) / sizeof(WCHAR)
|
|
);
|
|
|
|
|
|
pName = (wcschr( pBuf, L'"' )) + 1;
|
|
|
|
pBufTempPtr = wcschr( pName, L'"' );
|
|
|
|
*pBufTempPtr = L'\0';
|
|
|
|
|
|
pPin = (wcschr( pBufTempPtr+1, L'"' )) + 1;
|
|
|
|
pBufTempPtr = wcschr( pPin, L'"' );
|
|
|
|
*pBufTempPtr = L'\0';
|
|
|
|
|
|
pLocalRule = wcschr( pBufTempPtr+1, L'"') + 1;
|
|
|
|
pBufTempPtr = wcschr( pLocalRule, L'"' );
|
|
|
|
*pBufTempPtr = L'\0';
|
|
|
|
|
|
pLDRule = wcschr( pBufTempPtr+1, L'"') + 1;
|
|
|
|
pBufTempPtr = wcschr( pLDRule, L'"' );
|
|
|
|
*pBufTempPtr = L'\0';
|
|
|
|
|
|
pInternationalRule = wcschr( pBufTempPtr+1, L'"') + 1;
|
|
|
|
pBufTempPtr = wcschr( pInternationalRule, L'"' );
|
|
|
|
*pBufTempPtr = L'\0';
|
|
|
|
|
|
{
|
|
DWORD dwSize;
|
|
PSTR pszTemp;
|
|
|
|
dwSize = WideCharToMultiByte(
|
|
GetACP(),
|
|
0,
|
|
(pBufTempPtr + 2),
|
|
-1,
|
|
NULL,
|
|
0,
|
|
NULL,
|
|
NULL
|
|
);
|
|
|
|
pszTemp = ClientAlloc( dwSize );
|
|
|
|
WideCharToMultiByte(
|
|
GetACP(),
|
|
0,
|
|
(pBufTempPtr + 2),
|
|
-1,
|
|
pszTemp,
|
|
dwSize,
|
|
NULL,
|
|
NULL
|
|
);
|
|
|
|
dwFlags = atoi( pszTemp );
|
|
|
|
ClientFree( pszTemp );
|
|
}
|
|
|
|
|
|
RegCreateKeyExW(
|
|
hKey2,
|
|
szCurrentCardKey,
|
|
0,
|
|
gszNullStringW, //Class - what class?
|
|
REG_OPTION_NON_VOLATILE,
|
|
KEY_ALL_ACCESS,
|
|
0,
|
|
&hKey,
|
|
&dwDisposition
|
|
);
|
|
|
|
|
|
RegSetValueExW(
|
|
hKey,
|
|
gszIDW,
|
|
0,
|
|
REG_DWORD,
|
|
(LPBYTE)&n,
|
|
sizeof(DWORD)
|
|
);
|
|
|
|
RegSetValueExW(
|
|
hKey,
|
|
gszNameW,
|
|
0,
|
|
REG_SZ,
|
|
(LPBYTE)pName,
|
|
(lstrlenW(pName)+1)*sizeof(WCHAR)
|
|
);
|
|
|
|
RegSetValueExW(
|
|
hKey,
|
|
gszPinW,
|
|
0,
|
|
REG_SZ,
|
|
(LPBYTE)pPin,
|
|
(lstrlenW(pPin)+1)*sizeof(WCHAR)
|
|
);
|
|
|
|
RegSetValueExW(
|
|
hKey,
|
|
gszLocalRuleW,
|
|
0,
|
|
REG_SZ,
|
|
(LPBYTE)pLocalRule,
|
|
(lstrlenW(pLocalRule)+1)*sizeof(WCHAR)
|
|
);
|
|
|
|
RegSetValueExW(
|
|
hKey,
|
|
gszLDRuleW,
|
|
0,
|
|
REG_SZ,
|
|
(LPBYTE)pLDRule,
|
|
(lstrlenW(pLDRule)+1)*sizeof(WCHAR)
|
|
);
|
|
|
|
RegSetValueExW(
|
|
hKey,
|
|
gszInternationalRuleW,
|
|
0,
|
|
REG_SZ,
|
|
(LPBYTE)pInternationalRule,
|
|
(lstrlenW(pInternationalRule)+1)*sizeof(WCHAR)
|
|
);
|
|
|
|
RegSetValueExW(
|
|
hKey,
|
|
gszFlagsW,
|
|
0,
|
|
REG_DWORD,
|
|
(LPBYTE)&dwFlags,
|
|
sizeof(DWORD)
|
|
);
|
|
|
|
|
|
RegCloseKey(
|
|
hKey
|
|
);
|
|
|
|
}
|
|
|
|
|
|
RegCloseKey( hKey2);
|
|
RegCloseKey( hKey3);
|
|
|
|
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
|
|
|
|
//***************************************************************************
|
|
//***************************************************************************
|
|
//***************************************************************************
|
|
LONG PASCAL ReadCards( PCARD pCardSpace, PUINT pnStuff )
|
|
{
|
|
UINT n;
|
|
WCHAR szCurrentCardKey[256]; // Holds "CARDxx" during reads
|
|
PCARD pCardList;
|
|
UINT nNumCards;
|
|
LONG lResult = 0;
|
|
|
|
HKEY hKey;
|
|
HKEY hKey2;
|
|
DWORD dwDataType;
|
|
DWORD dwDataSize;
|
|
|
|
|
|
CheckCards();
|
|
|
|
nNumCards = GetNumberOfCards();
|
|
|
|
InternalDebugOut((40, "NumCards=%d",
|
|
nNumCards ));
|
|
|
|
//
|
|
// Did the caller pass in a buffer he wants loaded?
|
|
//
|
|
if ( pCardSpace )
|
|
{
|
|
//
|
|
// Does the caller know what he's doing?
|
|
//
|
|
if ( *(LPDWORD)pCardSpace < nNumCards )
|
|
{
|
|
InternalDebugOut((1, "ReadCards: Buffer too small!"));
|
|
|
|
*(LPDWORD)pCardSpace = nNumCards;
|
|
|
|
lResult = LINEERR_STRUCTURETOOSMALL;
|
|
|
|
goto CLEANUP_ERROR;
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Ok, it _looks_ like he's allocated enough space...
|
|
//
|
|
pCardList = pCardSpace;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
pCardList = ClientAlloc(sizeof(CARD) * nNumCards);
|
|
|
|
if (!pCardList)
|
|
{
|
|
goto CLEANUP_ERROR;
|
|
}
|
|
}
|
|
|
|
RegOpenKeyExW(
|
|
HKEY_CURRENT_USER,
|
|
gszTelephonyKey,
|
|
0,
|
|
KEY_READ,
|
|
&hKey2
|
|
);
|
|
|
|
for (n = 0; n < nNumCards; n++)
|
|
{
|
|
PCARD ThisCard = &pCardList[n];
|
|
|
|
wsprintfW(szCurrentCardKey, L"%ls\\%ls%d", gszCardsW, gszCardW, n);
|
|
|
|
|
|
RegOpenKeyExW(
|
|
hKey2,
|
|
szCurrentCardKey,
|
|
0,
|
|
KEY_READ,
|
|
&hKey
|
|
);
|
|
|
|
dwDataSize = sizeof(ThisCard->dwID);
|
|
ThisCard->dwID = 0;
|
|
RegQueryValueExW(
|
|
hKey,
|
|
gszIDW,
|
|
0,
|
|
&dwDataType,
|
|
(LPBYTE)&ThisCard->dwID,
|
|
&dwDataSize
|
|
);
|
|
|
|
|
|
dwDataSize = sizeof(ThisCard->NameW);
|
|
ThisCard->NameW[0] = '\0';
|
|
RegQueryValueExW(
|
|
hKey,
|
|
gszNameW,
|
|
0,
|
|
&dwDataType,
|
|
(LPBYTE)ThisCard->NameW,
|
|
&dwDataSize
|
|
);
|
|
//BUGBUG THIS SHOULD NOT BE NECESSARY!!!
|
|
ThisCard->NameW[dwDataSize/sizeof(WCHAR)] = '\0';
|
|
|
|
// {
|
|
// TCHAR cTemp[MAXLEN_PIN];
|
|
//
|
|
// dwDataSize = sizeof(ThisCard->PinW);
|
|
// cTemp[0] = '\0';
|
|
dwDataSize = sizeof(ThisCard->PinW);
|
|
ThisCard->PinW[0] = '\0';
|
|
RegQueryValueExW(
|
|
hKey,
|
|
gszPinW,
|
|
0,
|
|
&dwDataType,
|
|
(LPBYTE)ThisCard->PinW,
|
|
&dwDataSize
|
|
);
|
|
ThisCard->PinW[dwDataSize/sizeof(WCHAR)] = '\0';
|
|
|
|
// Unscrambler( ThisCard->dwID,
|
|
// cTemp,
|
|
// ThisCard->Pin
|
|
// );
|
|
//Unscramble in place
|
|
|
|
Unscrambler( ThisCard->dwID,
|
|
ThisCard->PinW,
|
|
ThisCard->PinW
|
|
);
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
//{
|
|
// TCHAR cTemp[] = "123";
|
|
// TCHAR cTemp2[sizeof(cTemp)] = "";
|
|
//
|
|
// InternalDebugOut((0, "Starting with: %s %s", cTemp, cTemp2));
|
|
// CopyScrambled( cTemp,
|
|
// cTemp2,
|
|
// 9
|
|
// );
|
|
// InternalDebugOut((0, " Called scram: %s %s", cTemp, cTemp2));
|
|
// Unscrambler( 9,
|
|
// cTemp2,
|
|
// cTemp
|
|
// );
|
|
// InternalDebugOut((0, "Called uscram: %s %s", cTemp, cTemp2));
|
|
//}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
dwDataSize = sizeof(ThisCard->LocalRuleW);
|
|
ThisCard->LocalRuleW[0] = '\0';
|
|
RegQueryValueExW(
|
|
hKey,
|
|
gszLocalRuleW,
|
|
0,
|
|
&dwDataType,
|
|
(LPBYTE)ThisCard->LocalRuleW,
|
|
&dwDataSize
|
|
);
|
|
ThisCard->LocalRuleW[dwDataSize/sizeof(WCHAR)] = '\0';
|
|
|
|
dwDataSize = sizeof(ThisCard->LDRuleW);
|
|
ThisCard->LDRuleW[0] = '\0';
|
|
RegQueryValueExW(
|
|
hKey,
|
|
gszLDRuleW,
|
|
0,
|
|
&dwDataType,
|
|
(LPBYTE)ThisCard->LDRuleW,
|
|
&dwDataSize
|
|
);
|
|
ThisCard->LDRuleW[dwDataSize/sizeof(WCHAR)] = '\0';
|
|
|
|
dwDataSize = sizeof(ThisCard->InternationalRuleW);
|
|
ThisCard->InternationalRuleW[0] = '\0';
|
|
RegQueryValueExW(
|
|
hKey,
|
|
gszInternationalRuleW,
|
|
0,
|
|
&dwDataType,
|
|
(LPBYTE)ThisCard->InternationalRuleW,
|
|
&dwDataSize
|
|
);
|
|
ThisCard->InternationalRuleW[dwDataSize/sizeof(WCHAR)] = '\0';
|
|
|
|
dwDataSize = sizeof(ThisCard->dwFlags);
|
|
ThisCard->dwFlags = 0;
|
|
RegQueryValueExW(
|
|
hKey,
|
|
gszFlagsW,
|
|
0,
|
|
&dwDataType,
|
|
(LPBYTE)&ThisCard->dwFlags,
|
|
&dwDataSize
|
|
);
|
|
|
|
RegCloseKey( hKey );
|
|
|
|
InternalDebugOut((10, "getting card entry %d is %d [%ls]",
|
|
n,
|
|
ThisCard->dwID,
|
|
ThisCard->NameW));
|
|
|
|
}
|
|
|
|
|
|
RegCloseKey( hKey2);
|
|
|
|
//
|
|
// Did the caller give us a place to put this stuff?
|
|
//
|
|
if ( pnStuff )
|
|
{
|
|
pnStuff[0] = 0;
|
|
pnStuff[1] = (UINT)pCardList;
|
|
pnStuff[2] = nNumCards;
|
|
}
|
|
// else
|
|
// {
|
|
// gnCurrentCardID = 0;
|
|
// gCardList = pCardList;
|
|
// gnNumCards = nNumCards;
|
|
// }
|
|
|
|
|
|
return lResult;
|
|
|
|
|
|
CLEANUP_ERROR:
|
|
|
|
|
|
// Free_gCardList();
|
|
|
|
return lResult;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//***************************************************************************
|
|
//***************************************************************************
|
|
//***************************************************************************
|
|
LONG PASCAL ReadCardsEasy(
|
|
PCARD *pCardSpace,
|
|
LPUINT *pnStuff )
|
|
{
|
|
UINT n;
|
|
|
|
n = 0;
|
|
ReadCards((PCARD)&n, NULL);
|
|
|
|
|
|
//
|
|
// Alloc space needed. Add size of DWORD in case there are 0 cards.
|
|
//
|
|
*pCardSpace = ClientAlloc( (n * sizeof(CARD)) + sizeof(DWORD));
|
|
|
|
if ( NULL == *pCardSpace )
|
|
{
|
|
//*** *** ***BUGBUG Handle the error (msg anyway...)
|
|
|
|
return LINEERR_NOMEM;
|
|
}
|
|
|
|
|
|
*(PUINT)*pCardSpace = n;
|
|
|
|
*pnStuff = ClientAlloc( 3 * sizeof(DWORD) );
|
|
|
|
if ( NULL == *pnStuff )
|
|
{
|
|
ClientFree( *pCardSpace );
|
|
|
|
//*** *** ***BUGBUG Handle the error (msg anyway...)
|
|
|
|
return LINEERR_NOMEM;
|
|
}
|
|
|
|
return ReadCards( *pCardSpace, *pnStuff );
|
|
|
|
}
|
|
|
|
|
|
|
|
//***************************************************************************
|
|
//***************************************************************************
|
|
//***************************************************************************
|
|
void PASCAL WriteCards( PCARD pCardList, UINT nNumCards,
|
|
DWORD dwChangedFlags)
|
|
{
|
|
UINT n;
|
|
UINT nCurrentCard;
|
|
WCHAR szCurrentCardKey[256]; // Holds "CARDx" string
|
|
HKEY hKey;
|
|
HKEY hKey2;
|
|
DWORD dwDisposition;
|
|
|
|
|
|
//*** *** ***BUGBUG
|
|
// should we wipe out all of the old ones first?
|
|
|
|
|
|
InternalDebugOut((40, "In writecards"));
|
|
|
|
//
|
|
// Has _anything_ changed?
|
|
//
|
|
if ( dwChangedFlags )
|
|
{
|
|
|
|
//
|
|
// Has anything changed that should cause us to write out all
|
|
// of the card info?
|
|
//
|
|
|
|
if ( dwChangedFlags & CHANGEDFLAGS_REALCHANGE )
|
|
{
|
|
|
|
InternalDebugOut((40, "About to write %d cards", nNumCards));
|
|
|
|
//
|
|
// This var will be the # of the current card as opposed to the
|
|
// # in mem - if a user deleted one, we can't write CARDx ...
|
|
//
|
|
nCurrentCard = 0;
|
|
|
|
RegCreateKeyExW(
|
|
HKEY_CURRENT_USER,
|
|
gszTelephonyKey,
|
|
0,
|
|
gszNullStringW, //Class - what class?
|
|
REG_OPTION_NON_VOLATILE,
|
|
KEY_ALL_ACCESS,
|
|
0,
|
|
&hKey2,
|
|
&dwDisposition
|
|
);
|
|
|
|
for (n = 0; n < nNumCards; n++)
|
|
{
|
|
PCARD ThisCard = &(pCardList[n]);
|
|
|
|
|
|
//
|
|
// If the user Removed this card, don't write it.
|
|
//
|
|
if ( (WCHAR)'\0' == ThisCard->NameW[0] )
|
|
{
|
|
continue; // skipit
|
|
}
|
|
|
|
InternalDebugOut((50, "About to write Card#%d - %ls",
|
|
nCurrentCard,
|
|
ThisCard->NameW));
|
|
|
|
|
|
wsprintfW(szCurrentCardKey, L"%ls\\%ls%d",
|
|
gszCardsW,
|
|
gszCardW,
|
|
nCurrentCard);
|
|
|
|
{
|
|
|
|
RegCreateKeyExW(
|
|
hKey2,
|
|
szCurrentCardKey,
|
|
0,
|
|
gszNullStringW, //Class - what class?
|
|
REG_OPTION_NON_VOLATILE,
|
|
KEY_ALL_ACCESS,
|
|
0,
|
|
&hKey,
|
|
&dwDisposition
|
|
);
|
|
|
|
RegSetValueExW(
|
|
hKey,
|
|
gszIDW,
|
|
0,
|
|
REG_DWORD,
|
|
(LPBYTE)&ThisCard->dwID,
|
|
sizeof(DWORD)
|
|
);
|
|
|
|
RegSetValueExW(
|
|
hKey,
|
|
gszNameW,
|
|
0,
|
|
REG_SZ,
|
|
(LPBYTE)ThisCard->NameW,
|
|
(lstrlenW(ThisCard->NameW)+1)*sizeof(WCHAR)
|
|
);
|
|
|
|
|
|
{
|
|
WCHAR wTemp[MAXLEN_PIN];
|
|
|
|
CopyScrambled( ThisCard->PinW,
|
|
wTemp,
|
|
ThisCard->dwID
|
|
);
|
|
|
|
RegSetValueExW(
|
|
hKey,
|
|
gszPinW,
|
|
0,
|
|
REG_SZ,
|
|
(LPBYTE)wTemp,
|
|
(lstrlenW(ThisCard->PinW)+1)*sizeof(WCHAR)
|
|
);
|
|
}
|
|
|
|
RegSetValueExW(
|
|
hKey,
|
|
gszLocalRuleW,
|
|
0,
|
|
REG_SZ,
|
|
(LPBYTE)ThisCard->LocalRuleW,
|
|
(lstrlenW(ThisCard->LocalRuleW)+1)*sizeof(WCHAR)
|
|
);
|
|
|
|
|
|
RegSetValueExW(
|
|
hKey,
|
|
gszLDRuleW,
|
|
0,
|
|
REG_SZ,
|
|
(LPBYTE)ThisCard->LDRuleW,
|
|
(lstrlenW(ThisCard->LDRuleW)+1)*sizeof(WCHAR)
|
|
);
|
|
|
|
RegSetValueExW(
|
|
hKey,
|
|
gszInternationalRuleW,
|
|
0,
|
|
REG_SZ,
|
|
(LPBYTE)ThisCard->InternationalRuleW,
|
|
(lstrlenW(ThisCard->InternationalRuleW)+1)*sizeof(WCHAR)
|
|
);
|
|
|
|
RegSetValueExW(
|
|
hKey,
|
|
gszFlagsW,
|
|
0,
|
|
REG_DWORD,
|
|
(LPBYTE)&ThisCard->dwFlags,
|
|
sizeof(DWORD)
|
|
);
|
|
|
|
RegCloseKey( hKey );
|
|
|
|
}
|
|
|
|
|
|
nCurrentCard++;
|
|
|
|
}
|
|
|
|
|
|
//
|
|
// If we "deleted" one or more calling cards, they're still hanging
|
|
// around. Delete them now.
|
|
//
|
|
for (n = nCurrentCard; n < nNumCards; n++)
|
|
{
|
|
wsprintfW(szCurrentCardKey, L"%ls\\%ls%d",
|
|
gszCardsW,
|
|
gszCardW,
|
|
n);
|
|
|
|
RegDeleteKeyW( hKey2,
|
|
szCurrentCardKey
|
|
);
|
|
}
|
|
|
|
|
|
|
|
RegOpenKeyExW(
|
|
hKey2,
|
|
gszCardsW,
|
|
0,
|
|
KEY_ALL_ACCESS,
|
|
&hKey
|
|
);
|
|
|
|
|
|
RegSetValueExW(
|
|
hKey,
|
|
gszNumEntriesW,
|
|
0,
|
|
REG_DWORD,
|
|
(LPBYTE)&nCurrentCard,
|
|
sizeof(DWORD)
|
|
);
|
|
|
|
RegCloseKey( hKey );
|
|
|
|
RegCloseKey( hKey2);
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
//***************************************************************************
|
|
//***************************************************************************
|
|
//***************************************************************************
|
|
LONG PASCAL GetLocationIndexFromID( UINT nID, PLOCATION pCallersList, UINT nCallersNumLocations )
|
|
{
|
|
UINT n;
|
|
PLOCATION pLocationList;
|
|
UINT nNumLocations;
|
|
|
|
|
|
//
|
|
// If the caller passed in his own list, use his info
|
|
//
|
|
if ( pCallersList )
|
|
{
|
|
pLocationList = pCallersList;
|
|
nNumLocations = nCallersNumLocations;
|
|
}
|
|
else
|
|
{
|
|
pLocationList = gLocationList;
|
|
nNumLocations = gnNumLocations;
|
|
}
|
|
|
|
|
|
for (n=0; n < nNumLocations; n++)
|
|
{
|
|
|
|
InternalDebugOut((10, "comparing <in %ld> with <list entry %ld is %ld>",
|
|
(DWORD)nID, (DWORD)n, (DWORD)pLocationList[n].dwID));
|
|
|
|
if ( nID == pLocationList[n].dwID )
|
|
{
|
|
return (n);
|
|
}
|
|
}
|
|
|
|
InternalDebugOut((1, "GetLocationIndexFromID failed! Looking for 0x%08lx", nID));
|
|
return (-1);
|
|
}
|
|
|
|
|
|
//***************************************************************************
|
|
//***************************************************************************
|
|
//***************************************************************************
|
|
void GetThisLocation( PLOCATION pLocation, UINT nLocationID, PLOCATION pLocationList, UINT nNumLocations )
|
|
{
|
|
UINT n;
|
|
|
|
n = GetLocationIndexFromID( nLocationID,
|
|
pLocationList,
|
|
nNumLocations);
|
|
|
|
//bjm10/31 pLocation->Name = pLocationList[n].Name;
|
|
//bjm10/31 pLocation->AreaCode = pLocationList[n].AreaCode;
|
|
//bjm10/31 pLocation->dwCountry = pLocationList[n].dwCountry;
|
|
//bjm10/31 pLocation->OutsideAccess = pLocationList[n].OutsideAccess;
|
|
//bjm10/31 pLocation->LongDistanceAccess = pLocationList[n].LongDistanceAccess;
|
|
//bjm10/31 pLocation->dwFlags = pLocationList[n].dwFlags;
|
|
//bjm10/31 pLocation->dwCallingCard = pLocationList[n].dwCallingCard;
|
|
//bjm10/31 pLocation->dwID = pLocationList[n].dwID;
|
|
//bjm10/31 pLocation->DisableCallWaiting = pLocationList[n].DisableCallWaiting;
|
|
//bjm10/31 pLocation->TollList = pLocationList[n].TollList;
|
|
|
|
CopyMemory( pLocation,
|
|
&pLocationList[n],
|
|
sizeof(LOCATION)
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
//***************************************************************************
|
|
//***************************************************************************
|
|
//***************************************************************************
|
|
LONG PASCAL ReadCountries( LPLINECOUNTRYLIST *ppLCL,
|
|
UINT nCountryID,
|
|
DWORD dwDestCountryID
|
|
)
|
|
{
|
|
LONG lTapiResult;
|
|
UINT nBufSize = 0x8000; //Start with a buffer of 16K
|
|
UINT n;
|
|
LPLINECOUNTRYLIST pNewLCL;
|
|
|
|
FUNC_ARGS funcArgs =
|
|
{
|
|
MAKELONG (LINE_FUNC | SYNC | 4, lGetCountry),
|
|
|
|
{
|
|
0,
|
|
TAPI_VERSION_CURRENT,
|
|
dwDestCountryID,
|
|
0
|
|
},
|
|
|
|
{
|
|
Dword,
|
|
Dword,
|
|
Dword,
|
|
lpGet_Struct
|
|
}
|
|
};
|
|
|
|
|
|
//
|
|
// Try until success or the buffer is huge
|
|
//
|
|
for ( lTapiResult = 1, n = 0;
|
|
lTapiResult && (n < 5);
|
|
n++ )
|
|
{
|
|
|
|
pNewLCL = (LPLINECOUNTRYLIST)ClientAlloc( nBufSize );
|
|
|
|
|
|
pNewLCL->dwTotalSize = nBufSize;
|
|
|
|
|
|
//
|
|
// Put new values in structure for TAPISRV
|
|
//
|
|
funcArgs.Args[0] = nCountryID;
|
|
funcArgs.Args[3] = (DWORD)pNewLCL;
|
|
|
|
|
|
//
|
|
// Call TAPISRV to get the country list
|
|
//
|
|
lTapiResult = DOFUNC (&funcArgs, "lineGetCountry");
|
|
|
|
|
|
//
|
|
// If the call succeeded, but the buffer was too small, or if the
|
|
// call failed, do it again...
|
|
//
|
|
if (
|
|
(lTapiResult == LINEERR_STRUCTURETOOSMALL)
|
|
||
|
|
(pNewLCL->dwNeededSize > nBufSize)
|
|
)
|
|
{
|
|
//
|
|
// Complain to anyone who'll listen that this should be tuned
|
|
// to start with a larger buffer so we don't have to do this multiple
|
|
// times....
|
|
//
|
|
InternalDebugOut((10, " TUNING PROBLEM: We're about to call lineGetCountry()"));
|
|
InternalDebugOut((10, " _again_ because the buffer wasn't big enough"));
|
|
InternalDebugOut((10, " the last time. FIX THIS!!!"));
|
|
|
|
|
|
lTapiResult = 1; // Force error condition if size was bad...
|
|
nBufSize += 0x4000; // Try a bit bigger
|
|
ClientFree( pNewLCL );
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// We didn't work for some other reason
|
|
//
|
|
break;
|
|
}
|
|
}
|
|
|
|
*ppLCL = pNewLCL;
|
|
|
|
return lTapiResult;
|
|
}
|
|
|
|
|
|
|
|
//***************************************************************************
|
|
//***************************************************************************
|
|
//***************************************************************************
|
|
void PASCAL FillCountriesListbox( HWND hWnd )
|
|
{
|
|
UINT n;
|
|
UINT nNumCountries;
|
|
LPLINECOUNTRYENTRY pCountryEntry;
|
|
/*static*/ LPLINECOUNTRYLIST pCountryList;
|
|
LONG lItemIndex;
|
|
|
|
|
|
if ( ReadCountries( &pCountryList, 0, 0 ) )
|
|
{
|
|
//*** *** ***BUGBUG Handle error condition!")
|
|
InternalDebugOut((1, " GetCountryList failed!"));
|
|
}
|
|
|
|
pCountryEntry = (LPLINECOUNTRYENTRY)
|
|
(((LPBYTE) pCountryList) + pCountryList->dwCountryListOffset);
|
|
|
|
nNumCountries = pCountryList->dwNumCountries;
|
|
|
|
//
|
|
// Run through all countries and toss 'em in the listbox
|
|
//
|
|
for (n = 0; n < nNumCountries; n++)
|
|
{
|
|
#ifdef PARTIAL_UNICODE
|
|
CHAR szTempString[256];
|
|
|
|
WideCharToMultiByte(
|
|
GetACP(),
|
|
0,
|
|
(PWSTR)(((LPBYTE) pCountryList) +
|
|
pCountryEntry->dwCountryNameOffset),
|
|
-1,
|
|
szTempString,
|
|
sizeof(szTempString),
|
|
NULL,
|
|
NULL
|
|
);
|
|
#endif
|
|
|
|
|
|
lItemIndex =
|
|
#ifdef PARTIAL_UNICODE
|
|
SendDlgItemMessage(
|
|
#else
|
|
SendDlgItemMessageW(
|
|
#endif
|
|
hWnd,
|
|
IDCC_DL_COUNTRY,
|
|
CB_ADDSTRING,
|
|
0,
|
|
#ifdef PARTIAL_UNICODE
|
|
(LPARAM)szTempString
|
|
#else
|
|
(LPARAM)(PWSTR)(((LPBYTE)pCountryList) +
|
|
pCountryEntry->dwCountryNameOffset)
|
|
#endif
|
|
);
|
|
|
|
SendDlgItemMessage(
|
|
hWnd,
|
|
IDCC_DL_COUNTRY,
|
|
CB_SETITEMDATA,
|
|
(WPARAM) lItemIndex,
|
|
(LPARAM) pCountryEntry->dwCountryID
|
|
);
|
|
|
|
pCountryEntry++;
|
|
}
|
|
|
|
ClientFree( pCountryList );
|
|
}
|
|
|
|
|
|
|
|
//***************************************************************************
|
|
//***************************************************************************
|
|
//***************************************************************************
|
|
void Free_gLocationList( void )
|
|
{
|
|
// PLOCATION ThisLocation;
|
|
// UINT n;
|
|
|
|
InternalDebugOut((80, "Freeing gLocationList"));
|
|
|
|
//
|
|
// Free all mem that was allocated
|
|
//
|
|
if (gLocationList)
|
|
{
|
|
ClientFree(gLocationList);
|
|
|
|
gLocationList = NULL;
|
|
}
|
|
|
|
}
|
|
|
|
|
|
//***************************************************************************
|
|
//***************************************************************************
|
|
//***************************************************************************
|
|
void WriteCurrentLocationValue( HWND hWnd, UINT nLocationID )
|
|
{
|
|
DWORD dwNewLocation;
|
|
|
|
FUNC_ARGS funcArgs =
|
|
{
|
|
MAKELONG (LINE_FUNC | SYNC | 4, tWriteLocations),
|
|
{
|
|
0,
|
|
CHANGEDFLAGS_CURLOCATIONCHANGED,
|
|
0, // dwNewLocation
|
|
0
|
|
},
|
|
|
|
{
|
|
Dword,
|
|
Dword,
|
|
Dword,
|
|
Dword
|
|
}
|
|
};
|
|
|
|
|
|
|
|
//
|
|
// If the user passed in an hWnd, get the new current loc from
|
|
// the selection box. Otherwise, use gnCurrentLocation which
|
|
// should have been updated before calling here.
|
|
//
|
|
if ( hWnd )
|
|
{
|
|
PLOCATION pThisLocation;
|
|
UINT nThisItemIndex;
|
|
|
|
nThisItemIndex = SendDlgItemMessage( hWnd,
|
|
IDCC_DL_NAME,
|
|
CB_GETCURSEL,
|
|
0,
|
|
0);
|
|
if (nThisItemIndex == -1 )
|
|
{
|
|
DBGOUT((10, "Found one(0)!!!!"));
|
|
}
|
|
pThisLocation = (PLOCATION)SendDlgItemMessage( hWnd,
|
|
IDCC_DL_NAME,
|
|
CB_GETITEMDATA,
|
|
nThisItemIndex,
|
|
0);
|
|
|
|
dwNewLocation = pThisLocation->dwID;
|
|
}
|
|
else
|
|
{
|
|
dwNewLocation = nLocationID;
|
|
}
|
|
|
|
|
|
InternalDebugOut((10, "Updating curlocation value (%ld)", dwNewLocation));
|
|
|
|
|
|
funcArgs.Args[2] = dwNewLocation;
|
|
|
|
DOFUNC (&funcArgs, "TWriteLocations");
|
|
|
|
}
|
|
|
|
|
|
//***************************************************************************
|
|
//***************************************************************************
|
|
//***************************************************************************
|
|
LONG PASCAL WriteLocations( PLOCATION pLocationList,
|
|
UINT nNumLocations,
|
|
DWORD dwChangedFlags,
|
|
PLOCATION pCurrentLocation
|
|
)
|
|
{
|
|
PWSTR pString;
|
|
UINT n;
|
|
PBYTE pNewLocationList;
|
|
LONG lResult;
|
|
|
|
FUNC_ARGS funcArgs =
|
|
{
|
|
MAKELONG (LINE_FUNC | SYNC | 4, tWriteLocations),
|
|
{
|
|
nNumLocations,
|
|
dwChangedFlags,
|
|
pCurrentLocation->dwID,
|
|
0 //pNewLocationList
|
|
},
|
|
|
|
{
|
|
Dword,
|
|
Dword,
|
|
Dword,
|
|
lpSet_Struct
|
|
}
|
|
};
|
|
|
|
|
|
if ( NULL == (pNewLocationList = ClientAlloc( sizeof(DWORD) * 3 +
|
|
sizeof(LOCATION) * nNumLocations)) )
|
|
{
|
|
DBGOUT((1, "MEM ALLOC (0x%08lx) FAILED!! WriteLoc",
|
|
(nNumLocations * sizeof(LOCATION)) + (sizeof(DWORD) * 3) ));
|
|
|
|
return LINEERR_NOMEM;
|
|
}
|
|
|
|
funcArgs.Args[3] = (DWORD)pNewLocationList;
|
|
|
|
|
|
CopyMemory( (PBYTE)pNewLocationList + ( 3 * sizeof(DWORD) ),
|
|
pLocationList,
|
|
nNumLocations * sizeof(LOCATION)
|
|
);
|
|
|
|
//
|
|
// Set "dwTotalSize"
|
|
//
|
|
((LPDWORD)pNewLocationList)[0] = (3 * sizeof(DWORD)) +
|
|
(nNumLocations * sizeof(LOCATION));
|
|
|
|
|
|
lResult = (DOFUNC (&funcArgs, "TWriteLocations"));
|
|
|
|
if ( 0 != lResult )
|
|
{
|
|
ClientFree( pNewLocationList );
|
|
goto WL_ERROR;
|
|
}
|
|
|
|
|
|
pString = ClientAlloc( 256 * sizeof(WCHAR) );
|
|
|
|
for ( n = 0; n < nNumLocations; n++)
|
|
{
|
|
PLOCATION ThisLocation;
|
|
DWORD dwDisposition;
|
|
DWORD dwDataType;
|
|
DWORD dwDataSize;
|
|
HKEY hKey;
|
|
HKEY hKey2;
|
|
|
|
|
|
ThisLocation = &(pLocationList[n]);
|
|
|
|
|
|
wsprintfW( pString, L"%ls\\%ls%ld",
|
|
gszLocationsW,
|
|
gszLocationW,
|
|
n );
|
|
|
|
//
|
|
// Now write the card ID to the CURRENT USER section
|
|
//
|
|
RegCreateKeyExW(
|
|
HKEY_CURRENT_USER,
|
|
gszTelephonyKey,
|
|
0,
|
|
gszNullStringW, //Class - what class?
|
|
REG_OPTION_NON_VOLATILE,
|
|
KEY_ALL_ACCESS,
|
|
0,
|
|
&hKey2,
|
|
&dwDisposition
|
|
);
|
|
|
|
RegCreateKeyExW(
|
|
hKey2,
|
|
pString,
|
|
0,
|
|
gszNullStringW, //Class - what class?
|
|
REG_OPTION_NON_VOLATILE,
|
|
KEY_ALL_ACCESS,
|
|
0,
|
|
&hKey,
|
|
&dwDisposition
|
|
);
|
|
|
|
RegSetValueExW(
|
|
hKey,
|
|
gszCallingCardW,
|
|
0,
|
|
REG_DWORD,
|
|
(LPBYTE)&ThisLocation->dwCallingCard,
|
|
sizeof(DWORD)
|
|
);
|
|
|
|
RegCloseKey( hKey );
|
|
RegCloseKey( hKey2);
|
|
|
|
}
|
|
|
|
ClientFree( pString );
|
|
ClientFree( pNewLocationList );
|
|
|
|
WL_ERROR:
|
|
|
|
return lResult;
|
|
}
|
|
|
|
|
|
//***************************************************************************
|
|
//***************************************************************************
|
|
//***************************************************************************
|
|
LONG PASCAL ReadLocations( PLOCATION *pLocationSpace,
|
|
PUINT *pnStuff,
|
|
HLINEAPP hLineApp,
|
|
DWORD dwDeviceID,
|
|
DWORD dwAPIVersion,
|
|
DWORD dwParmsToCheckFlags
|
|
)
|
|
{
|
|
FUNC_ARGS funcArgs =
|
|
{
|
|
MAKELONG (LINE_FUNC | SYNC | 5, tReadLocations),
|
|
|
|
{
|
|
(DWORD)hLineApp,
|
|
|
|
dwDeviceID,
|
|
|
|
dwAPIVersion,
|
|
|
|
dwParmsToCheckFlags,
|
|
|
|
0 // (DWORD) pLocationSpace
|
|
},
|
|
|
|
{
|
|
hXxxApp_NULLOK,
|
|
Dword,
|
|
Dword,
|
|
Dword,
|
|
lpGet_Struct
|
|
}
|
|
};
|
|
|
|
PBYTE pTemp;
|
|
PBYTE pNewBuf;
|
|
LONG lResult;
|
|
PBYTE pNewLocationSpace;
|
|
UINT n;
|
|
PWSTR pString;
|
|
|
|
|
|
//
|
|
// A quick check to see if this is pointless
|
|
//
|
|
if (
|
|
(NULL == pLocationSpace)
|
|
&&
|
|
(gLocationList)
|
|
)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
|
|
//
|
|
// Do it once to get the dwNeededSize (if there are less than 5 locations
|
|
// this will be the only call we'll need to make)
|
|
//
|
|
// ( sizeof(DWORD) * 6 is for dwTotalsize, usedsize&needed size & pnstuff )
|
|
//
|
|
pTemp = ClientAlloc( (sizeof(DWORD) * 6) +
|
|
(sizeof(LOCATION) * 4)
|
|
);
|
|
|
|
|
|
if ( NULL == pTemp )
|
|
{
|
|
DBGOUT((1, "Mem alloc (0x%08lx) Failed! ReadLoc",
|
|
(sizeof(DWORD) * 6 ) + (sizeof(LOCATION) * 4) ));
|
|
|
|
lResult = LINEERR_NOMEM;
|
|
goto RL_ERROR;
|
|
}
|
|
|
|
((LPDWORD)pTemp)[DWTOTALSIZE] = (sizeof(DWORD) * 6) +
|
|
(sizeof(LOCATION) * 4);
|
|
|
|
funcArgs.Args[4] = (DWORD)pTemp;
|
|
|
|
lResult = (DOFUNC (&funcArgs, "TReadLocations"));
|
|
|
|
if ( 0 != lResult )
|
|
{
|
|
ClientFree( pTemp );
|
|
goto RL_ERROR;
|
|
}
|
|
|
|
|
|
//
|
|
// Did we have enough room?
|
|
//
|
|
if ( ((LPDWORD)pTemp)[DWTOTALSIZE] < ((LPDWORD)pTemp)[DWNEEDEDSIZE] )
|
|
{
|
|
//
|
|
// No, do it to really get the struct
|
|
//
|
|
pNewBuf = ClientAlloc( ((LPDWORD)pTemp)[DWNEEDEDSIZE] );
|
|
|
|
if ( NULL == pTemp )
|
|
{
|
|
DBGOUT((1, "Mem alloc (0x%08lx) Failed! ReadLoc2",
|
|
((LPDWORD)pTemp)[1] ));
|
|
|
|
lResult = LINEERR_NOMEM;
|
|
goto RL_ERROR;
|
|
}
|
|
|
|
((LPDWORD)pNewBuf)[DWTOTALSIZE] = ((LPDWORD)pTemp)[DWNEEDEDSIZE];
|
|
|
|
ClientFree( pTemp );
|
|
|
|
funcArgs.Args[4] = (DWORD)pNewBuf;
|
|
|
|
lResult = (DOFUNC (&funcArgs, "TReadLocations"));
|
|
|
|
if ( 0 != lResult )
|
|
{
|
|
ClientFree( pNewBuf );
|
|
goto RL_ERROR;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Do as if we didn't make it...
|
|
//
|
|
pNewBuf = pTemp;
|
|
}
|
|
|
|
|
|
pNewLocationSpace = ClientAlloc( ((LPDWORD)pNewBuf)[DWNEEDEDSIZE] - (sizeof(DWORD) * 6) );
|
|
|
|
CopyMemory( pNewLocationSpace,
|
|
pNewBuf + (sizeof(DWORD) * 6),
|
|
((LPDWORD)pNewBuf)[DWNEEDEDSIZE] - (sizeof(DWORD) * 6)
|
|
);
|
|
|
|
if ( pLocationSpace )
|
|
{
|
|
*pLocationSpace = (PLOCATION)pNewLocationSpace;
|
|
}
|
|
|
|
|
|
|
|
#pragma message("where should this be?")
|
|
// Can't be in TAPISRV because it doesn't know HKEY_CURRENT_USER (well, it could impersonate...)
|
|
|
|
pString = ClientAlloc( 256 * sizeof(WCHAR) );
|
|
|
|
//
|
|
// For each location, get the current loc from HKEY_CURRENT_USER
|
|
//
|
|
for ( n = 0; n < ((LPUINT)pNewBuf)[5]; n++)
|
|
{
|
|
PLOCATION ThisLocation;
|
|
DWORD dwDataType;
|
|
DWORD dwDataSize;
|
|
HKEY hKey;
|
|
HKEY hKey2;
|
|
|
|
ThisLocation = &(((PLOCATION)pNewLocationSpace)[n]);
|
|
|
|
wsprintfW( pString, L"%ls\\%ls%ld",
|
|
gszLocationsW,
|
|
gszLocationW,
|
|
n );
|
|
|
|
|
|
//
|
|
// Now get the card ID from the CURRENT USER section
|
|
//
|
|
RegOpenKeyExW(
|
|
HKEY_CURRENT_USER,
|
|
gszTelephonyKey,
|
|
0,
|
|
KEY_READ,
|
|
&hKey2
|
|
);
|
|
|
|
RegOpenKeyExW(
|
|
hKey2,
|
|
pString,
|
|
0,
|
|
KEY_READ,
|
|
&hKey
|
|
);
|
|
|
|
dwDataSize = sizeof(DWORD);
|
|
ThisLocation->dwCallingCard = 0;
|
|
RegQueryValueExW(
|
|
hKey,
|
|
gszCallingCardW,
|
|
0,
|
|
&dwDataType,
|
|
(LPBYTE)&ThisLocation->dwCallingCard,
|
|
&dwDataSize
|
|
);
|
|
|
|
RegCloseKey( hKey );
|
|
RegCloseKey( hKey2);
|
|
|
|
}
|
|
|
|
ClientFree( pString );
|
|
|
|
|
|
//
|
|
// Did the caller give us a place to put this stuff?
|
|
//
|
|
if ( pnStuff )
|
|
{
|
|
*pnStuff = ClientAlloc( 3 * sizeof(UINT) );
|
|
|
|
(*pnStuff)[0] = ((LPUINT)pNewBuf)[3];
|
|
(*pnStuff)[1] = (UINT)pNewLocationSpace;
|
|
(*pnStuff)[2] = ((LPUINT)pNewBuf)[5];
|
|
}
|
|
else
|
|
{
|
|
gnCurrentLocationID = ((LPUINT)pNewBuf)[3];
|
|
gLocationList = (PLOCATION)pNewLocationSpace;
|
|
gnNumLocations = ((LPUINT)pNewBuf)[5];
|
|
}
|
|
|
|
|
|
ClientFree( pNewBuf );
|
|
|
|
|
|
RL_ERROR:
|
|
|
|
return lResult;
|
|
}
|
|
|
|
|
|
|
|
// //***************************************************************************
|
|
// //***************************************************************************
|
|
// //***************************************************************************
|
|
// LONG PASCAL ReadLocationsEasy(
|
|
// PLOCATION *pLocationSpace,
|
|
// LPUINT *pnStuff )
|
|
// {
|
|
// UINT n;
|
|
//
|
|
//
|
|
// //BUGBUG:PERFORMANCE: Start with space for 3 locations
|
|
//
|
|
// n = 0;
|
|
// ReadLocations( (PLOCATION)&n, NULL);
|
|
//
|
|
//
|
|
// *pLocationSpace = ClientAlloc( (n * sizeof(LOCATION)) + sizeof(DWORD) );
|
|
//
|
|
// if ( NULL == *pLocationSpace )
|
|
// {
|
|
// //*** *** ***BUGBUG Handle the error
|
|
// }
|
|
//
|
|
//
|
|
// *(PUINT)*pLocationSpace = n;
|
|
//
|
|
// *pnStuff = ClientAlloc( 3 * sizeof(DWORD) );
|
|
//
|
|
// if ( NULL == *pnStuff )
|
|
// {
|
|
// ClientFree( *pLocationSpace );
|
|
//
|
|
// return LINEERR_NOMEM;
|
|
// }
|
|
//
|
|
// return ReadLocations( *pLocationSpace, *pnStuff );
|
|
// }
|
|
|
|
|
|
|
|
//***************************************************************************
|
|
//***************************************************************************
|
|
//***************************************************************************
|
|
void PASCAL AddLocationToListbox( HWND hWnd, UINT nIndex)
|
|
{
|
|
LONG lItemIndex;
|
|
|
|
#ifdef PARTIAL_UNICODE
|
|
CHAR szTempString[MAXLEN_NAME];
|
|
|
|
|
|
WideCharToMultiByte(
|
|
GetACP(),
|
|
0,
|
|
gLocationList[nIndex].NameW,
|
|
-1,
|
|
szTempString,
|
|
sizeof(szTempString),
|
|
NULL,
|
|
NULL
|
|
);
|
|
#endif
|
|
|
|
lItemIndex =
|
|
#ifdef PARTIAL_UNICODE
|
|
SendDlgItemMessage(
|
|
#else
|
|
SendDlgItemMessageW(
|
|
#endif
|
|
hWnd,
|
|
IDCC_DL_NAME,
|
|
CB_ADDSTRING,
|
|
0,
|
|
#ifdef PARTIAL_UNICODE
|
|
(LPARAM)szTempString
|
|
#else
|
|
(LPARAM)gLocationList[nIndex].NameW
|
|
#endif
|
|
);
|
|
|
|
SendDlgItemMessage(
|
|
hWnd,
|
|
IDCC_DL_NAME,
|
|
CB_SETITEMDATA,
|
|
(WPARAM) lItemIndex,
|
|
(LPARAM)(DWORD) &(gLocationList[nIndex])
|
|
);
|
|
}
|
|
|
|
|
|
|
|
//***************************************************************************
|
|
//***************************************************************************
|
|
//***************************************************************************
|
|
void RedoLocationListbox( HWND hWnd,
|
|
PLOCATION pLocationList,
|
|
UINT nNumLocations,
|
|
PLOCATION pCurrentLocation)
|
|
{
|
|
//
|
|
// sledgehammer - refill the listbox
|
|
//
|
|
UINT n;
|
|
#ifdef PARTIAL_UNICODE
|
|
CHAR szTempString[MAXLEN_NAME];
|
|
#endif
|
|
|
|
SendDlgItemMessage(
|
|
hWnd,
|
|
IDCC_DL_NAME,
|
|
CB_RESETCONTENT,
|
|
0,
|
|
0
|
|
);
|
|
|
|
for ( n=0; n<nNumLocations; n++ )
|
|
{
|
|
if ( pLocationList[n].NameW[0] != '\0' )
|
|
AddLocationToListbox( hWnd, n);
|
|
}
|
|
|
|
|
|
#ifdef PARTIAL_UNICODE
|
|
WideCharToMultiByte(
|
|
GetACP(),
|
|
0,
|
|
pCurrentLocation->NameW,
|
|
-1,
|
|
szTempString,
|
|
sizeof(szTempString),
|
|
NULL,
|
|
NULL
|
|
);
|
|
#endif
|
|
|
|
//
|
|
// Select the proper location
|
|
//
|
|
#ifdef PARTIAL_UNICODE
|
|
SendDlgItemMessage(
|
|
#else
|
|
SendDlgItemMessageW(
|
|
#endif
|
|
hWnd,
|
|
IDCC_DL_NAME,
|
|
CB_SELECTSTRING,
|
|
(WPARAM)-1,
|
|
#ifdef PARTIAL_UNICODE
|
|
(LPARAM)szTempString
|
|
#else
|
|
(LPARAM)pCurrentLocation->NameW
|
|
#endif
|
|
);
|
|
|
|
|
|
SendDlgItemMessage(
|
|
hWnd,
|
|
IDCC_DL_NAME,
|
|
CB_SETEDITSEL,
|
|
0,
|
|
MAKELPARAM(-2,-2)
|
|
);
|
|
|
|
}
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////
|
|
// CheckForDupLocation - check dialing locations list box
|
|
// to see if there is a duplicate
|
|
// return FALSE is there is a bad entry and TRUE if there
|
|
// is not
|
|
//////////////////////////////////////////////////////////////////
|
|
BOOL CheckForDupLocation(HWND hWnd,
|
|
int iLastEdit)
|
|
{
|
|
WCHAR szTempString1[MAXLEN_NAME];
|
|
WCHAR szTempString2[MAXLEN_NAME];
|
|
int count, n;
|
|
|
|
if (iLastEdit != -1)
|
|
{
|
|
// get text that was last edited
|
|
SendDlgItemMessageW(hWnd,
|
|
IDCC_DL_NAME,
|
|
CB_GETLBTEXT,
|
|
(WPARAM)iLastEdit,
|
|
(LPARAM)(LPTSTR)szTempString1);
|
|
|
|
// get total locations in list box
|
|
count = SendDlgItemMessage(hWnd,
|
|
IDCC_DL_NAME,
|
|
CB_GETCOUNT,
|
|
0,
|
|
0);
|
|
|
|
// cycle through and if 2 match, then it's a dup
|
|
for (n = 0; n < count; n++)
|
|
{
|
|
if (n == iLastEdit)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
SendDlgItemMessageW(hWnd,
|
|
IDCC_DL_NAME,
|
|
CB_GETLBTEXT,
|
|
(WPARAM)n,
|
|
(LPARAM)(LPTSTR)szTempString2);
|
|
|
|
if (!lstrcmpiW(szTempString1, szTempString2))
|
|
{
|
|
PWSTR buf1;
|
|
PWSTR buf2;
|
|
|
|
// put up messagebox
|
|
buf1 = ClientAlloc( 512 * sizeof(WCHAR));
|
|
buf2 = ClientAlloc( 512 * sizeof(WCHAR));
|
|
|
|
LoadStringW(ghInst, IDS_DL_DUP_NAME, buf1, 512 );
|
|
LoadStringW(ghInst, IDS_DL_DUP_NAME_CAPTION, buf2, 512 );
|
|
|
|
MessageBoxW( hWnd,
|
|
buf1,
|
|
buf2,
|
|
MB_OK
|
|
);
|
|
|
|
ClientFree( buf1 );
|
|
ClientFree( buf2 );
|
|
|
|
// set selection back
|
|
SendDlgItemMessageW(hWnd,
|
|
IDCC_DL_NAME,
|
|
CB_SETCURSEL,
|
|
(WPARAM)iLastEdit,
|
|
0);
|
|
|
|
// set edit control back to display correct text
|
|
SetDlgItemTextW(hWnd,
|
|
IDCC_DL_NAME,
|
|
szTempString1);
|
|
|
|
// set focus
|
|
SetFocus(GetDlgItem(hWnd,
|
|
IDCC_DL_NAME));
|
|
|
|
return FALSE;
|
|
}
|
|
}
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
//***************************************************************************
|
|
//***************************************************************************
|
|
//***************************************************************************
|
|
LONG PASCAL FillLocationsListbox( HWND hWnd )
|
|
{
|
|
UINT n;
|
|
LONG lResult;
|
|
|
|
|
|
if ( 0 != ( lResult = ReadLocations( NULL, NULL, 0, 0, 0, 0)) )
|
|
{
|
|
return lResult;
|
|
}
|
|
|
|
|
|
//
|
|
// Put the location names in the location listbox
|
|
//
|
|
for (n = 0; n < gnNumLocations; n++)
|
|
{
|
|
AddLocationToListbox( hWnd, n);
|
|
}
|
|
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
//***************************************************************************
|
|
//***************************************************************************
|
|
//***************************************************************************
|
|
void PASCAL FillDisableCallWaitingListbox( HWND hWnd )
|
|
{
|
|
UINT n;
|
|
UINT nNumStrings;
|
|
#ifdef PARTIAL_UNICODE
|
|
CHAR key[32];
|
|
CHAR buf[MAXLEN_DISABLECALLWAITING];
|
|
#else
|
|
WCHAR buf[MAXLEN_DISABLECALLWAITING];
|
|
WCHAR key[32];
|
|
#endif
|
|
HKEY hKey;
|
|
HKEY hKey2;
|
|
DWORD dwDataType;
|
|
DWORD dwDataSize;
|
|
|
|
|
|
RegOpenKeyExW(
|
|
HKEY_LOCAL_MACHINE,
|
|
gszTelephonyKey,
|
|
0,
|
|
KEY_READ,
|
|
&hKey2
|
|
);
|
|
|
|
RegOpenKeyExW(
|
|
hKey2,
|
|
gszLocationsW,
|
|
0,
|
|
KEY_READ,
|
|
&hKey
|
|
);
|
|
|
|
dwDataSize = sizeof(nNumStrings);
|
|
nNumStrings = 0;
|
|
RegQueryValueExW(
|
|
hKey,
|
|
gszDisableCallWaitingW,
|
|
0,
|
|
&dwDataType,
|
|
(LPBYTE)&nNumStrings,
|
|
&dwDataSize
|
|
);
|
|
|
|
//BUGBUG if # == 0, pull from RES and write to Reg
|
|
|
|
|
|
//
|
|
// Put the strings in the DisableCallWaiting listbox
|
|
//
|
|
for (n = 0; n < nNumStrings; n++)
|
|
{
|
|
#ifdef PARTIAL_UNICODE
|
|
wsprintf(key, "%ls%d", gszDisableCallWaitingW, n);
|
|
#else
|
|
wsprintfW(key, L"%ls%d", gszDisableCallWaitingW, n);
|
|
#endif
|
|
|
|
dwDataSize = sizeof(buf);
|
|
buf[0] = '\0';
|
|
#ifdef PARTIAL_UNICODE
|
|
RegQueryValueEx(
|
|
#else
|
|
RegQueryValueExW(
|
|
#endif
|
|
hKey,
|
|
key,
|
|
0,
|
|
&dwDataType,
|
|
(LPBYTE)buf,
|
|
&dwDataSize
|
|
);
|
|
buf[dwDataSize/sizeof(WCHAR)] = '\0';
|
|
|
|
#ifdef PARTIAL_UNICODE
|
|
SendDlgItemMessage(
|
|
#else
|
|
SendDlgItemMessageW(
|
|
#endif
|
|
hWnd,
|
|
IDCC_DL_CALLWAITING,
|
|
CB_ADDSTRING,
|
|
0,
|
|
(LPARAM)buf
|
|
);
|
|
|
|
}
|
|
|
|
RegCloseKey( hKey );
|
|
RegCloseKey( hKey2);
|
|
}
|
|
|
|
|
|
//***************************************************************************
|
|
//***************************************************************************
|
|
//***************************************************************************
|
|
void PASCAL FillDialingPropertyDialog( HWND hWnd, PLOCATION CurrentLocation)
|
|
{
|
|
LONG lCurCountry;
|
|
LONG nNumCountries;
|
|
LONG n;
|
|
#ifdef PARTIAL_UNICODE
|
|
CHAR szTempString[MAXLEN_NAME];
|
|
#endif
|
|
|
|
|
|
#ifdef PARTIAL_UNICODE
|
|
WideCharToMultiByte(
|
|
GetACP(),
|
|
0,
|
|
CurrentLocation->NameW,
|
|
-1,
|
|
szTempString,
|
|
sizeof(szTempString),
|
|
NULL,
|
|
NULL
|
|
);
|
|
#endif
|
|
|
|
|
|
//
|
|
// Select the proper location
|
|
//
|
|
#ifdef PARTIAL_UNICODE
|
|
SendDlgItemMessage(
|
|
#else
|
|
SendDlgItemMessageW(
|
|
#endif
|
|
hWnd,
|
|
IDCC_DL_NAME,
|
|
CB_SELECTSTRING,
|
|
(WPARAM)-1,
|
|
#ifdef PARTIAL_UNICODE
|
|
(LPARAM)szTempString
|
|
#else
|
|
(LPARAM)CurrentLocation->NameW
|
|
#endif
|
|
);
|
|
|
|
|
|
#ifdef PARTIAL_UNICODE
|
|
WideCharToMultiByte(
|
|
GetACP(),
|
|
0,
|
|
CurrentLocation->AreaCodeW,
|
|
-1,
|
|
szTempString,
|
|
sizeof(szTempString),
|
|
NULL,
|
|
NULL
|
|
);
|
|
#endif
|
|
|
|
//
|
|
// Set the Area Code field
|
|
//
|
|
#ifdef PARTIAL_UNICODE
|
|
SetDlgItemText(
|
|
#else
|
|
SetDlgItemTextW(
|
|
#endif
|
|
hWnd,
|
|
IDCE_DL_AREACODE,
|
|
#ifdef PARTIAL_UNICODE
|
|
szTempString);
|
|
#else
|
|
CurrentLocation->AreaCodeW);
|
|
#endif
|
|
|
|
|
|
//
|
|
// Set the correct country
|
|
//
|
|
nNumCountries = SendDlgItemMessage( hWnd,
|
|
IDCC_DL_COUNTRY,
|
|
CB_GETCOUNT,
|
|
0,
|
|
0);
|
|
|
|
lCurCountry = (LONG)CurrentLocation->dwCountry;
|
|
|
|
//
|
|
// Run through the country list looking for a match
|
|
//
|
|
for (n=0; n < nNumCountries; n++)
|
|
{
|
|
LONG lCountryID;
|
|
|
|
lCountryID = SendDlgItemMessage( hWnd,
|
|
IDCC_DL_COUNTRY,
|
|
CB_GETITEMDATA,
|
|
(WPARAM)n,
|
|
0);
|
|
|
|
if ( lCountryID == lCurCountry )
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
SendDlgItemMessage( hWnd,
|
|
IDCC_DL_COUNTRY,
|
|
CB_SETCURSEL,
|
|
(WPARAM)n,
|
|
0);
|
|
|
|
|
|
|
|
#ifdef PARTIAL_UNICODE
|
|
WideCharToMultiByte(
|
|
GetACP(),
|
|
0,
|
|
CurrentLocation->OutsideAccessW,
|
|
-1,
|
|
szTempString,
|
|
sizeof(szTempString),
|
|
NULL,
|
|
NULL
|
|
);
|
|
#endif
|
|
|
|
//
|
|
// Set the Outside Access field
|
|
//
|
|
#ifdef PARTIAL_UNICODE
|
|
SetDlgItemText(
|
|
#else
|
|
SetDlgItemTextW(
|
|
#endif
|
|
hWnd,
|
|
IDCE_DL_OUTSIDEACCESS,
|
|
#ifdef PARTIAL_UNICODE
|
|
szTempString);
|
|
#else
|
|
CurrentLocation->OutsideAccessW);
|
|
#endif
|
|
|
|
|
|
#ifdef PARTIAL_UNICODE
|
|
WideCharToMultiByte(
|
|
GetACP(),
|
|
0,
|
|
CurrentLocation->LongDistanceAccessW,
|
|
-1,
|
|
szTempString,
|
|
sizeof(szTempString),
|
|
NULL,
|
|
NULL
|
|
);
|
|
#endif
|
|
|
|
// Set the Long Distance Access field
|
|
//
|
|
#ifdef PARTIAL_UNICODE
|
|
SetDlgItemText(
|
|
#else
|
|
SetDlgItemTextW(
|
|
#endif
|
|
hWnd,
|
|
IDCE_DL_LONGDISTANCEACCESS,
|
|
#ifdef PARTIAL_UNICODE
|
|
szTempString);
|
|
#else
|
|
CurrentLocation->LongDistanceAccessW);
|
|
#endif
|
|
|
|
|
|
//
|
|
// Set the Tone & Pulse buttons
|
|
//
|
|
CheckRadioButton( hWnd,
|
|
IDCR_PULSE,
|
|
IDCR_TONE,
|
|
(CurrentLocation->dwFlags & LOCATION_USETONEDIALING) ?
|
|
IDCR_TONE :
|
|
IDCR_PULSE);
|
|
|
|
|
|
|
|
//
|
|
// Set the calling card checkbox and calling card name field
|
|
//
|
|
CheckDlgButton( hWnd,
|
|
IDCK_DL_CALLINGCARD,
|
|
(CurrentLocation->dwFlags & LOCATION_USECALLINGCARD) );
|
|
|
|
|
|
n = GetCardIndexFromID( CurrentLocation->dwCallingCard,
|
|
gpCardList,
|
|
gpnStuff[2]
|
|
);
|
|
|
|
if ( (LONG)(-1) == n )
|
|
{
|
|
n = 0;
|
|
}
|
|
|
|
|
|
#ifdef PARTIAL_UNICODE
|
|
WideCharToMultiByte(
|
|
GetACP(),
|
|
0,
|
|
gpCardList[n].NameW,
|
|
-1,
|
|
szTempString,
|
|
MAXLEN_NAME,
|
|
NULL,
|
|
NULL
|
|
);
|
|
#endif
|
|
|
|
#ifdef PARTIAL_UNICODE
|
|
SetDlgItemText(
|
|
#else
|
|
SetDlgItemTextW(
|
|
#endif
|
|
hWnd,
|
|
IDCE_DL_CALLINGCARD,
|
|
#ifdef PARTIAL_UNICODE
|
|
szTempString
|
|
#else
|
|
gpCardList[n].NameW
|
|
#endif
|
|
);
|
|
|
|
|
|
//
|
|
// Does this location use a calling card?
|
|
//
|
|
if ( CurrentLocation->dwFlags & LOCATION_USECALLINGCARD )
|
|
{
|
|
EnableWindow( GetDlgItem(hWnd, IDCE_DL_CALLINGCARD), TRUE );
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Disable the Calling Card name field
|
|
//
|
|
EnableWindow( GetDlgItem(hWnd, IDCE_DL_CALLINGCARD), FALSE );
|
|
}
|
|
|
|
|
|
//
|
|
// Set the callwaiting checkbox and callwaiting string
|
|
//
|
|
CheckDlgButton( hWnd,
|
|
IDCK_DL_CALLWAITING,
|
|
(CurrentLocation->dwFlags & LOCATION_HASCALLWAITING) );
|
|
|
|
|
|
EnableWindow( GetDlgItem(hWnd, IDCC_DL_CALLWAITING),
|
|
(CurrentLocation->dwFlags & LOCATION_HASCALLWAITING) ?
|
|
TRUE :
|
|
FALSE
|
|
);
|
|
|
|
|
|
#ifdef PARTIAL_UNICODE
|
|
WideCharToMultiByte(
|
|
GetACP(),
|
|
0,
|
|
CurrentLocation->DisableCallWaitingW,
|
|
-1,
|
|
szTempString,
|
|
sizeof(szTempString),
|
|
NULL,
|
|
NULL
|
|
);
|
|
#endif
|
|
|
|
//
|
|
// Set the Outside Access field (even if the field is disabled. We
|
|
// wanna show what it was, or would be, or clear it out from the last
|
|
// location.)
|
|
//
|
|
#ifdef PARTIAL_UNICODE
|
|
SetDlgItemText(
|
|
#else
|
|
SetDlgItemTextW(
|
|
#endif
|
|
hWnd,
|
|
IDCC_DL_CALLWAITING,
|
|
#ifdef PARTIAL_UNICODE
|
|
szTempString);
|
|
#else
|
|
CurrentLocation->DisableCallWaitingW);
|
|
#endif
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
//***************************************************************************
|
|
//***************************************************************************
|
|
//***************************************************************************
|
|
BOOL ToneDialingIsDefault( void )
|
|
{
|
|
TCHAR sBuffer[8]; // In case the string is "PULSE" instead of "P"
|
|
LONG lBuffLen = sizeof(sBuffer);
|
|
LONG lBuffType = 0;
|
|
LONG lRetCode;
|
|
HKEY hKey;
|
|
|
|
|
|
lRetCode = RegOpenKey( HKEY_CURRENT_USER,
|
|
"Control Panel\\International",
|
|
&hKey);
|
|
|
|
lRetCode = RegQueryValueEx( hKey,
|
|
"DefaultDialMode",
|
|
NULL,
|
|
&lBuffType,
|
|
sBuffer,
|
|
&lBuffLen);
|
|
|
|
lRetCode = RegCloseKey( hKey );
|
|
|
|
|
|
//
|
|
// If the type is a STRING, _and_ the first char is 'P', then
|
|
// we set the tone/pulse default to PULSE. Otherwise, the
|
|
// default is TONE.
|
|
if (
|
|
( lBuffType == REG_SZ )
|
|
&&
|
|
( sBuffer[0] == 'P' )
|
|
)
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
|
|
//***************************************************************************
|
|
//***************************************************************************
|
|
//***************************************************************************
|
|
BOOL IsBadCountryCode( UINT nCountryCode )
|
|
{
|
|
LONG lResult;
|
|
LPLINECOUNTRYLIST pLCL;
|
|
|
|
lResult = ReadCountries( &pLCL, nCountryCode, 0 );
|
|
|
|
if ( pLCL )
|
|
ClientFree( pLCL );
|
|
|
|
return lResult;
|
|
}
|
|
|
|
|
|
|
|
//***************************************************************************
|
|
//***************************************************************************
|
|
//***************************************************************************
|
|
|
|
static TCHAR gszInternationalSec[] = "intl";
|
|
static TCHAR gszCountryEntry[] = "iCountry";
|
|
|
|
UINT GetCountryCodeFromiCountry()
|
|
{
|
|
UINT nCountryCode;
|
|
|
|
|
|
nCountryCode = GetProfileInt( gszInternationalSec,
|
|
gszCountryEntry,
|
|
1 );
|
|
|
|
|
|
InternalDebugOut((20, "Entering GetCountryCodeFromiCountry"));
|
|
//
|
|
// Verify that we believe that the iCountry setting is a country
|
|
// code _we_ know about as well.
|
|
//
|
|
if ( IsBadCountryCode(nCountryCode) )
|
|
{
|
|
//
|
|
// This don't seem like a valid country code.
|
|
//*** *** ***Spit out a debug message, (maybe a msgbox for users?).
|
|
//
|
|
InternalDebugOut((1, "IsBadCountryCode, nCountryCode= 0x%08lx", (DWORD)nCountryCode));
|
|
nCountryCode = 1;
|
|
}
|
|
|
|
InternalDebugOut((20, "Leaving GetCountryCodeFromiCountry, nCountryCode= 0x%08lx", (DWORD)nCountryCode));
|
|
return nCountryCode;
|
|
}
|
|
|
|
|
|
|
|
//***************************************************************************
|
|
//***************************************************************************
|
|
//***************************************************************************
|
|
void AllocNewID( HKEY MainKey, LPDWORD lpdw )
|
|
{
|
|
LONG lResult;
|
|
|
|
//
|
|
// Is this a new LocationID?
|
|
//
|
|
if ( HKEY_LOCAL_MACHINE == MainKey )
|
|
{
|
|
FUNC_ARGS funcArgs =
|
|
{
|
|
MAKELONG (LINE_FUNC | SYNC | 1, tAllocNewID),
|
|
{
|
|
(DWORD)lpdw
|
|
},
|
|
|
|
{
|
|
lpDword
|
|
}
|
|
};
|
|
|
|
//
|
|
// Yes, let TAPISRV do it without danger of AV interruption from
|
|
// another thread
|
|
//
|
|
|
|
lResult = DOFUNC (&funcArgs, "TAllocNewID");
|
|
|
|
}
|
|
else
|
|
{
|
|
|
|
HKEY hKey;
|
|
HKEY hKey2;
|
|
DWORD dwDataSize;
|
|
DWORD dwDataType;
|
|
DWORD dwNewID;
|
|
DWORD dwDisposition;
|
|
|
|
RegCreateKeyExW(
|
|
HKEY_CURRENT_USER,
|
|
gszTelephonyKey,
|
|
0,
|
|
gszNullStringW,
|
|
REG_OPTION_NON_VOLATILE,
|
|
KEY_READ,
|
|
0,
|
|
&hKey2,
|
|
&dwDisposition
|
|
);
|
|
|
|
RegCreateKeyExW(
|
|
hKey2,
|
|
gszCardsW,
|
|
0,
|
|
gszNullStringW,
|
|
REG_OPTION_NON_VOLATILE,
|
|
KEY_ALL_ACCESS,
|
|
0,
|
|
&hKey,
|
|
&dwDisposition
|
|
);
|
|
|
|
dwDataSize = sizeof(DWORD);
|
|
|
|
//
|
|
// Use 1 as the first ID.
|
|
//
|
|
*lpdw = 1;
|
|
RegQueryValueExW(
|
|
hKey,
|
|
gszNextIDW,
|
|
0,
|
|
&dwDataType,
|
|
(LPBYTE)lpdw,
|
|
&dwDataSize
|
|
);
|
|
|
|
|
|
dwNewID = *lpdw + 1;
|
|
|
|
RegSetValueExW(
|
|
hKey,
|
|
gszNextIDW,
|
|
0,
|
|
REG_DWORD,
|
|
(LPBYTE)&dwNewID,
|
|
sizeof(DWORD)
|
|
);
|
|
|
|
RegCloseKey( hKey );
|
|
RegCloseKey( hKey2);
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//***************************************************************************
|
|
//***************************************************************************
|
|
//***************************************************************************
|
|
BOOL PASCAL SimpleProcessing(
|
|
HWND hWnd,
|
|
PLOCATION pThisLocation
|
|
)
|
|
{
|
|
LPLINECOUNTRYLIST pLCL;
|
|
UINT n;
|
|
|
|
n = ReadCountries( &pLCL, pThisLocation->dwCountry, 0 );
|
|
|
|
if (
|
|
( 0 == lstrlenW( pThisLocation->AreaCodeW ) )
|
|
&&
|
|
( 0 == n )
|
|
)
|
|
{
|
|
LPLINECOUNTRYENTRY pCountryEntry;
|
|
|
|
pCountryEntry = (LPLINECOUNTRYENTRY)
|
|
(((LPBYTE) pLCL) + pLCL->dwCountryListOffset);
|
|
|
|
//
|
|
// Does this country HAVE TO have an area code?
|
|
//
|
|
if ( wcschr ( (PWSTR)((LPBYTE)pLCL +
|
|
pCountryEntry->dwLongDistanceRuleOffset),
|
|
'F' ) )
|
|
{
|
|
PWSTR buf1;
|
|
PWSTR buf2;
|
|
|
|
buf1 = ClientAlloc( 512 * sizeof(WCHAR));
|
|
buf2 = ClientAlloc( 512 * sizeof(WCHAR));
|
|
|
|
LoadStringW(ghInst, IDS_WRN_AREA_CODE_REQUIRED, buf1, 512 );
|
|
LoadStringW(ghInst, DIALINGPROPERTIES_NAME, buf2, 512 );
|
|
|
|
MessageBoxW( hWnd,
|
|
buf1,
|
|
buf2,
|
|
MB_OK
|
|
);
|
|
|
|
ClientFree( buf1 );
|
|
ClientFree( buf2 );
|
|
|
|
SetFocus(GetDlgItem(hWnd, IDCE_DL_AREACODE));
|
|
|
|
SetWindowLong( hWnd, DWL_MSGRESULT, TRUE );
|
|
|
|
ClientFree( pLCL );
|
|
|
|
return TRUE;
|
|
}
|
|
}
|
|
|
|
if ( pLCL )
|
|
{
|
|
ClientFree( pLCL );
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
//***************************************************************************
|
|
//***************************************************************************
|
|
//***************************************************************************
|
|
/*--------------------------------------------------------------------------*\
|
|
|
|
Function: LocDefineDlgSimple
|
|
|
|
Purpose:
|
|
|
|
\*--------------------------------------------------------------------------*/
|
|
|
|
BOOL CALLBACK LocDefineDlgSimple( HWND hWnd,
|
|
UINT uMessage,
|
|
WPARAM wParam,
|
|
LPARAM lParam )
|
|
{
|
|
UINT uResult=TRUE;
|
|
WPARAM wCmdId=0;
|
|
WPARAM wCmdCbn=0;
|
|
LONG lResult=0;
|
|
LONG n;
|
|
LONG nNumCountries;
|
|
LONG nCurrentCountry;
|
|
LONG nCountryID;
|
|
|
|
LONG lThisCountryIndex;
|
|
static PLOCATION pThisLocation = NULL;
|
|
|
|
#ifdef PARTIAL_UNICODE
|
|
CHAR szTempString[MAXLEN_NAME];
|
|
#endif
|
|
|
|
// table of controls and context-sensitive help IDs
|
|
|
|
static DWORD aIds[] =
|
|
{
|
|
IDCS_DL_AREACODE, IDH_TAPI_AREA_CODE,
|
|
IDCE_DL_AREACODE, IDH_TAPI_AREA_CODE,
|
|
IDCS_DL_COUNTRY, IDH_TAPI_COUNTRY,
|
|
IDCC_DL_COUNTRY, IDH_TAPI_COUNTRY,
|
|
IDCE_DL_OUTSIDEACCESS, IDH_TAPI_ACCESS_LINE,
|
|
IDCS_DL_OUTSIDEACCESS, IDH_TAPI_ACCESS_LINE,
|
|
IDCR_PULSE, IDH_TAPI_LOCATION_PULSE,
|
|
IDCR_TONE, IDH_TAPI_LOCATION_PULSE,
|
|
0, 0
|
|
};
|
|
|
|
|
|
switch (uMessage)
|
|
{
|
|
// Process clicks on controls after Context Help mode selected
|
|
case WM_HELP:
|
|
InternalDebugOut((50, " WM_HELP in LocDefineDlgSimple"));
|
|
WinHelp (((LPHELPINFO) lParam)->hItemHandle, "windows.hlp", HELP_WM_HELP,
|
|
(DWORD)(LPSTR) aIds);
|
|
uResult = FALSE;
|
|
break;
|
|
|
|
|
|
// Process right-clicks on controls
|
|
case WM_CONTEXTMENU:
|
|
InternalDebugOut((50, " WM_CONTEXTMENU in LocDefineDlgSimple"));
|
|
WinHelp ((HWND) wParam, "windows.hlp", HELP_CONTEXTMENU, (DWORD)(LPVOID) aIds);
|
|
uResult = FALSE;
|
|
break;
|
|
|
|
|
|
case WM_INITDIALOG:
|
|
|
|
InternalDebugOut((50, " WM_INITDIALOG in LocDefineDlgSimple"));
|
|
|
|
|
|
//
|
|
// Don't let a user cancel out of here
|
|
//
|
|
//(Do one for simple, one for wiz...
|
|
//
|
|
EnableWindow( GetDlgItem(hWnd, IDCANCEL), FALSE);
|
|
EnableWindow( GetDlgItem(GetParent(hWnd), IDCANCEL), FALSE);
|
|
|
|
|
|
pThisLocation = ClientAlloc( sizeof(LOCATION) );
|
|
|
|
if ( NULL == pThisLocation )
|
|
{
|
|
InternalDebugOut((1, "Memory alloc failed!"));
|
|
return LINEERR_NOMEM;
|
|
}
|
|
|
|
//
|
|
// Fill in some default fields
|
|
//
|
|
LoadStringW(
|
|
ghInst,
|
|
IDS_NEWLOCATION,
|
|
pThisLocation->NameW,
|
|
MAXLEN_NAME
|
|
);
|
|
|
|
pThisLocation->dwFlags = ToneDialingIsDefault() ?
|
|
LOCATION_USETONEDIALING :
|
|
0;
|
|
|
|
|
|
AllocNewID( HKEY_LOCAL_MACHINE,
|
|
&(pThisLocation->dwID) );
|
|
|
|
FillCountriesListbox( hWnd );
|
|
|
|
|
|
nCurrentCountry = GetCountryCodeFromiCountry();
|
|
|
|
//
|
|
// Set the correct country
|
|
//
|
|
nNumCountries = SendDlgItemMessage( hWnd,
|
|
IDCC_DL_COUNTRY,
|
|
CB_GETCOUNT,
|
|
0,
|
|
0
|
|
);
|
|
|
|
//
|
|
// Run through the country list looking for a match
|
|
//
|
|
for (n=0; n < nNumCountries; n++)
|
|
{
|
|
nCountryID = SendDlgItemMessage( hWnd,
|
|
IDCC_DL_COUNTRY,
|
|
CB_GETITEMDATA,
|
|
(WPARAM)n,
|
|
0);
|
|
|
|
if ( nCountryID == nCurrentCountry )
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Did we find a hit?
|
|
//
|
|
if ( n == nNumCountries )
|
|
{
|
|
//
|
|
// No. Use the top country.
|
|
//
|
|
n = 0;
|
|
}
|
|
|
|
SendDlgItemMessage( hWnd,
|
|
IDCC_DL_COUNTRY,
|
|
CB_SETCURSEL,
|
|
(WPARAM)n,
|
|
0);
|
|
|
|
pThisLocation->dwCountry = SendDlgItemMessage(
|
|
hWnd,
|
|
IDCC_DL_COUNTRY,
|
|
CB_GETITEMDATA,
|
|
n,
|
|
0);
|
|
|
|
|
|
|
|
// EnableWindow( GetDlgItem(hWnd, IDCANCEL), FALSE );
|
|
|
|
//
|
|
// Set some limits on the edit fields
|
|
//
|
|
SendDlgItemMessage(
|
|
hWnd,
|
|
IDCC_DL_NAME,
|
|
EM_LIMITTEXT,
|
|
MAXLEN_NAME,
|
|
0);
|
|
SendDlgItemMessage(
|
|
hWnd,
|
|
IDCE_DL_AREACODE,
|
|
EM_LIMITTEXT,
|
|
MAXLEN_AREACODE,
|
|
0);
|
|
SendDlgItemMessage(
|
|
hWnd,
|
|
IDCE_DL_OUTSIDEACCESS,
|
|
EM_LIMITTEXT,
|
|
MAXLEN_OUTSIDEACCESS,
|
|
0);
|
|
|
|
|
|
//11/19 if ((uResult = CntrySetFocus( hWnd, IDCC_DL_COUNTRY_CODE, (LpLocGetDefault())->dwCountryCode )) != CPL_SUCCESS )
|
|
//11/19 goto LError;
|
|
|
|
SetDlgItemText( hWnd, IDCE_DL_OUTSIDEACCESS, NULL );
|
|
|
|
SetDlgItemText( hWnd, IDCE_DL_AREACODE, NULL );
|
|
|
|
|
|
CheckRadioButton( hWnd,
|
|
IDCR_PULSE,
|
|
IDCR_TONE,
|
|
ToneDialingIsDefault() ?
|
|
IDCR_TONE
|
|
: IDCR_PULSE );
|
|
|
|
|
|
//
|
|
// Is an area code required?
|
|
//
|
|
//BUGBUG: Disable CLOSE button until user enters a valid area code (if req'd)
|
|
|
|
|
|
//
|
|
// Should we use the "Your modem's been inited" text instead?
|
|
//
|
|
if ( lParam )
|
|
{
|
|
#ifdef PARTIAL_UNICODE
|
|
LPSTR lpString;
|
|
#else
|
|
LPWSTR lpString;
|
|
#endif
|
|
|
|
lpString = ClientAlloc(1524);
|
|
|
|
if ( NULL != lpString )
|
|
{
|
|
#ifdef PARTIAL_UNICODE
|
|
LoadString(
|
|
#else
|
|
LoadStringW(
|
|
#endif
|
|
ghInst,
|
|
IDS_MSG_SIMPLEMSG_MDMINSTALLED,
|
|
lpString,
|
|
ClientSize(lpString) / sizeof(WCHAR) );
|
|
|
|
#ifdef PARTIAL_UNICODE
|
|
SetDlgItemText(
|
|
#else
|
|
SetDlgItemTextW(
|
|
#endif
|
|
hWnd,
|
|
IDCS_DL_SILENTTEXT,
|
|
lpString
|
|
);
|
|
|
|
ClientFree(lpString);
|
|
}
|
|
}
|
|
|
|
uResult = TRUE;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case WM_NOTIFY:
|
|
{
|
|
NMHDR *pnm;
|
|
|
|
InternalDebugOut((50, " WM_NOTIFY in LocDefineDlgSimple"));
|
|
|
|
pnm = (NMHDR *)lParam;
|
|
|
|
switch(pnm->code)
|
|
{
|
|
// case PSN_APPLY:
|
|
case PSN_KILLACTIVE:
|
|
{
|
|
if ( SimpleProcessing( hWnd, pThisLocation ) )
|
|
{
|
|
return TRUE;
|
|
}
|
|
|
|
WriteLocations(
|
|
pThisLocation,
|
|
1,
|
|
CHANGEDFLAGS_REALCHANGE |
|
|
CHANGEDFLAGS_CURLOCATIONCHANGED,
|
|
pThisLocation
|
|
);
|
|
|
|
ClientFree( pThisLocation );
|
|
|
|
// Need this?? EndDialog( hWnd, 0);
|
|
}
|
|
break;
|
|
|
|
|
|
case PSN_SETACTIVE:
|
|
{
|
|
// Only allow the Next button. The user cannot go back and
|
|
// change the settings.
|
|
PropSheet_SetWizButtons(GetParent(hWnd), PSWIZB_NEXT);
|
|
}
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
break;
|
|
|
|
|
|
|
|
case WM_COMMAND:
|
|
InternalDebugOut((50, " WM_COMMAND in LocDefineDlgSimple"));
|
|
|
|
switch ( wCmdId = GET_WM_COMMAND_ID( wParam, lParam) )
|
|
{
|
|
case IDOK:
|
|
{
|
|
if ( SimpleProcessing( hWnd, pThisLocation ) )
|
|
{
|
|
return TRUE;
|
|
}
|
|
|
|
WriteLocations(
|
|
pThisLocation,
|
|
1,
|
|
CHANGEDFLAGS_REALCHANGE |
|
|
CHANGEDFLAGS_CURLOCATIONCHANGED,
|
|
pThisLocation
|
|
);
|
|
|
|
ClientFree( pThisLocation );
|
|
|
|
EndDialog( hWnd, 0);
|
|
|
|
}
|
|
break;
|
|
|
|
|
|
// case IDCANCEL:
|
|
// {
|
|
// PTCHAR pText;
|
|
// PTCHAR pTitle;
|
|
//
|
|
// pText = ClientAlloc(1024);
|
|
// pTitle = ClientAlloc(1024);
|
|
//
|
|
// if (!LoadString( ghInst,
|
|
// IDS_WRN_QUITING_WIZ,
|
|
// pText,
|
|
// ClientSize(pText) ) )
|
|
// {
|
|
////11/19 UtilErrorRpt( NULL, CPL_ERR_LOAD_STRING );
|
|
// }
|
|
//
|
|
// if (!LoadString( ghInst,
|
|
// IDS_WRN_TITLE_WARNING,
|
|
// pTitle,
|
|
// ClientSize(pTitle) ) )
|
|
// {
|
|
////11/19 UtilErrorRpt( NULL, CPL_ERR_LOAD_STRING );
|
|
// }
|
|
//
|
|
// if ( IDNO == MessageBox( hWnd,
|
|
// pText,
|
|
// pTitle,
|
|
// MB_YESNO | MB_DEFBUTTON2 | MB_TASKMODAL ) )
|
|
// {
|
|
// break;
|
|
// }
|
|
//
|
|
// ClientFree( pText );
|
|
// ClientFree( pTitle );
|
|
//
|
|
// EndDialog( hWnd, 0);
|
|
//
|
|
//
|
|
// if ( pThisLocation )
|
|
// ClientFree( pThisLocation );
|
|
//
|
|
// }
|
|
// break;
|
|
|
|
|
|
|
|
case IDCR_PULSE:
|
|
case IDCR_TONE:
|
|
{
|
|
pThisLocation->dwFlags ^= LOCATION_USETONEDIALING;
|
|
|
|
CheckRadioButton( hWnd, IDCR_PULSE, IDCR_TONE, wCmdId );
|
|
}
|
|
break;
|
|
|
|
|
|
|
|
case IDCC_DL_COUNTRY:
|
|
{
|
|
if ( GET_WM_COMMAND_CMD(wParam, lParam) == CBN_SELCHANGE )
|
|
{
|
|
lThisCountryIndex = SendDlgItemMessage(
|
|
hWnd,
|
|
IDCC_DL_COUNTRY,
|
|
CB_GETCURSEL,
|
|
0,
|
|
0);
|
|
|
|
pThisLocation->dwCountry = SendDlgItemMessage(
|
|
hWnd,
|
|
IDCC_DL_COUNTRY,
|
|
CB_GETITEMDATA,
|
|
lThisCountryIndex,
|
|
0);
|
|
}
|
|
}
|
|
break;
|
|
|
|
|
|
|
|
case IDCE_DL_AREACODE:
|
|
{
|
|
if ( EN_CHANGE == HIWORD(wParam) )
|
|
{
|
|
|
|
if ( 0 == UtilGetEditNumStr(
|
|
hWnd,
|
|
IDCE_DL_AREACODE,
|
|
UTIL_NUMBER
|
|
)
|
|
)
|
|
{
|
|
//BUGBUG: Disable CLOSE button until user enters a valid area code
|
|
SetDlgItemTextW(
|
|
hWnd,
|
|
LOWORD(wParam),
|
|
pThisLocation->AreaCodeW);
|
|
break;
|
|
}
|
|
|
|
|
|
#ifdef PARTIAL_UNICODE
|
|
GetDlgItemText(
|
|
#else
|
|
GetDlgItemTextW(
|
|
#endif
|
|
hWnd,
|
|
LOWORD(wParam),
|
|
#ifdef PARTIAL_UNICODE
|
|
szTempString,
|
|
#else
|
|
pThisLocation->AreaCodeW,
|
|
#endif
|
|
MAXLEN_AREACODE);
|
|
|
|
#ifdef PARTIAL_UNICODE
|
|
MultiByteToWideChar(
|
|
GetACP(),
|
|
MB_PRECOMPOSED,
|
|
szTempString,
|
|
-1,
|
|
pThisLocation->AreaCodeW,
|
|
MAXLEN_AREACODE
|
|
);
|
|
#endif
|
|
|
|
}
|
|
}
|
|
break;
|
|
|
|
|
|
|
|
case IDCE_DL_OUTSIDEACCESS:
|
|
{
|
|
//
|
|
// Get the new value
|
|
//
|
|
if ( EN_CHANGE == HIWORD(wParam) )
|
|
{
|
|
#ifdef PARTIAL_UNICODE
|
|
GetDlgItemText( hWnd,
|
|
IDCE_DL_OUTSIDEACCESS,
|
|
szTempString,
|
|
MAXLEN_OUTSIDEACCESS
|
|
);
|
|
#else
|
|
GetDlgItemTextW( hWnd,
|
|
IDCE_DL_OUTSIDEACCESS,
|
|
pThisLocation->OutsideAccessW,
|
|
MAXLEN_OUTSIDEACCESS
|
|
);
|
|
#endif
|
|
|
|
|
|
#ifdef PARTIAL_UNICODE
|
|
MultiByteToWideChar(
|
|
GetACP(),
|
|
MB_PRECOMPOSED,
|
|
szTempString,
|
|
-1,
|
|
pThisLocation->OutsideAccessW,
|
|
MAXLEN_OUTSIDEACCESS
|
|
);
|
|
#endif
|
|
|
|
//
|
|
// We'll _assume_ that the LD is the same access
|
|
//
|
|
lstrcpyW( pThisLocation->LongDistanceAccessW,
|
|
pThisLocation->OutsideAccessW);
|
|
|
|
}
|
|
}
|
|
break;
|
|
|
|
|
|
|
|
}
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
uResult = FALSE;
|
|
|
|
}
|
|
|
|
return( uResult );
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
//***************************************************************************
|
|
//***************************************************************************
|
|
//***************************************************************************
|
|
BOOL
|
|
CALLBACK
|
|
LocWizardDlgProc(
|
|
HWND hWnd,
|
|
UINT uMessage,
|
|
WPARAM wParam,
|
|
LPARAM lParam
|
|
)
|
|
{
|
|
return LocDefineDlgSimple( hWnd,
|
|
uMessage,
|
|
wParam,
|
|
lParam
|
|
);
|
|
}
|
|
|
|
|
|
|
|
//***************************************************************************
|
|
//***************************************************************************
|
|
//***************************************************************************
|
|
// Returns pointer to matching prefix within (cached) current location entry
|
|
// or NULL, if the subscriber number's prefix isn't in the list.
|
|
//
|
|
LPWSTR PASCAL InPrefixList(LPWSTR lpSubscriberW, PLOCATION pLocation)
|
|
{
|
|
//BUGBUG: assumption - that a toll prefix is 3 tchars
|
|
WCHAR pTempW[] = L",XXX,";
|
|
|
|
if (
|
|
(!IsBadStringPtrW(lpSubscriberW, 512))
|
|
&&
|
|
(lstrlenW(lpSubscriberW) > 2)
|
|
)
|
|
{
|
|
//
|
|
// We _assume_ that the tolllist is of the form:
|
|
// ",nnn,nnn,nnn," then this routine is simply:
|
|
//
|
|
pTempW[1] = lpSubscriberW[0];
|
|
pTempW[2] = lpSubscriberW[1];
|
|
pTempW[3] = lpSubscriberW[2];
|
|
|
|
InternalDebugOut((11, "Looking for [%ls] in [%ls]", pTempW, pLocation->TollListW));
|
|
|
|
return wcsstr( pLocation->TollListW, pTempW);
|
|
}
|
|
else
|
|
{
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
//***************************************************************************
|
|
//***************************************************************************
|
|
//***************************************************************************
|
|
LONG PASCAL BreakupCanonicalW( LPWSTR pAddressIn,
|
|
LPWSTR *pCountry,
|
|
LPWSTR *pCity,
|
|
LPWSTR *pSubscriber
|
|
)
|
|
{
|
|
LONG lResult = 0;
|
|
BOOL fInCityCode = FALSE;
|
|
|
|
|
|
//
|
|
// Get past any (illegal) leading spaces
|
|
//
|
|
while ( *pAddressIn == ' ' )
|
|
{
|
|
pAddressIn++;
|
|
}
|
|
|
|
|
|
//
|
|
// Leading zeros are very bad. Don't allow them.
|
|
// We're now at the first non-space. Better not be a '0'.
|
|
//
|
|
if ( *pAddressIn == '0' )
|
|
{
|
|
//
|
|
// There are leading zeros!
|
|
//
|
|
DBGOUT((1, " Canonical numbers are not allowed to have leading zeros"));
|
|
lResult = LINEERR_INVALADDRESS;
|
|
goto cleanup;
|
|
}
|
|
|
|
|
|
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
//
|
|
// Parse the canonical number into its component pieces
|
|
//
|
|
|
|
//
|
|
// Do country first
|
|
//
|
|
*pCountry = pAddressIn;
|
|
|
|
//
|
|
// Now get to past this
|
|
//
|
|
while ( IsWDigit(*pAddressIn) )
|
|
{
|
|
pAddressIn++;
|
|
}
|
|
|
|
//
|
|
// We hit something that's not a digit...
|
|
// Make sure it's not the end of the string...
|
|
//
|
|
if ( *pAddressIn != '\0' )
|
|
{
|
|
//
|
|
// Remember whether this was the open paren of a city code
|
|
//
|
|
if ( *pAddressIn == '(' )
|
|
{
|
|
fInCityCode = TRUE;
|
|
}
|
|
|
|
|
|
//
|
|
// Make this a little stringlet
|
|
//
|
|
*pAddressIn = '\0';
|
|
pAddressIn++;
|
|
}
|
|
|
|
|
|
//
|
|
// Now get past any junk to the next set
|
|
//
|
|
|
|
|
|
//
|
|
// Ignore any spaces
|
|
//*** *** ***BUGBUG This will also skip GARBAGE!!!
|
|
//
|
|
while ( (!IsWDigit(*pAddressIn)) && (*pAddressIn != (WCHAR)NULL) &&
|
|
(*pAddressIn != ')') && (*pAddressIn != '(') )
|
|
{
|
|
pAddressIn++;
|
|
}
|
|
|
|
|
|
//
|
|
// If the previous char is a paren, this must be a city code
|
|
// Or, if we've previously hit the open paren, we're there as well...
|
|
//
|
|
if ( *(pAddressIn-1) == '(' || (*pAddressIn == '(') || fInCityCode )
|
|
{
|
|
//
|
|
// Ignore any spaces
|
|
//*** *** ***BUGBUG This will also skip GARBAGE!!!
|
|
//
|
|
while ( (!IsWDigit(*pAddressIn)) && (*pAddressIn != (WCHAR)NULL) && (*pAddressIn != ')') )
|
|
{
|
|
pAddressIn++;
|
|
}
|
|
|
|
//
|
|
// We just hit a digit
|
|
//
|
|
*pCity = pAddressIn;
|
|
|
|
|
|
//
|
|
// Now get to past this
|
|
//
|
|
while ( IsWDigit(*pAddressIn) )
|
|
{
|
|
pAddressIn++;
|
|
}
|
|
|
|
//
|
|
// We hit somthing that's not a digit...
|
|
// Make sure it's not the end of the string...
|
|
//
|
|
if ( (WCHAR)NULL != *pAddressIn)
|
|
{
|
|
|
|
//*** *** ***BUGBUG Do we have to verify the ')' ?
|
|
|
|
//
|
|
// Make this a little stringlet
|
|
//
|
|
*pAddressIn = '\0';
|
|
pAddressIn++;
|
|
}
|
|
|
|
//
|
|
// Ignore any spaces
|
|
//*** *** ***BUGBUG This will also skip GARBAGE!!!
|
|
//
|
|
while ( (!IsWDigit(*pAddressIn)) && (*pAddressIn != (WCHAR)NULL) && (*pAddressIn != ')') )
|
|
{
|
|
pAddressIn++;
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// There seems to be no city code. Ok, go straight to
|
|
// subscriber number
|
|
//
|
|
*pCity = NULL;
|
|
}
|
|
|
|
|
|
//
|
|
// Nothing left to do but put the icing on the cake
|
|
//
|
|
*pSubscriber = pAddressIn;
|
|
|
|
if (
|
|
IsBadStringPtrW( *pSubscriber, 512 )
|
|
||
|
|
lstrlenW( *pSubscriber ) == 0
|
|
)
|
|
{
|
|
//
|
|
// Obviously not canonical
|
|
//
|
|
DBGOUT((1, " Canonical numbers must have a subscriber number"));
|
|
lResult = LINEERR_INVALADDRESS;
|
|
goto cleanup;
|
|
}
|
|
|
|
|
|
cleanup:
|
|
|
|
return lResult;
|
|
}
|
|
|
|
|
|
|
|
//***************************************************************************
|
|
//***************************************************************************
|
|
//***************************************************************************
|
|
|
|
void UpdateNumberField( HWND hWnd, LPCWSTR lpszAddressIn );
|
|
|
|
|
|
|
|
BOOL
|
|
CALLBACK
|
|
LocationsDlgProc(
|
|
HWND hWnd,
|
|
UINT msg,
|
|
WPARAM wParam,
|
|
LPARAM lParam
|
|
)
|
|
{
|
|
UINT n;
|
|
UINT nCurrent;
|
|
BOOL fFoundACleanNumber;
|
|
PWSTR buf1;
|
|
PWSTR buf2;
|
|
|
|
// static index of last location name that was edited
|
|
static int iStaticLastNameEdited = -1;
|
|
|
|
//
|
|
// table of controls and context-sensitive help IDs
|
|
//
|
|
static DWORD aIds[] = {
|
|
//#if WINNT
|
|
// These codes aren't in the NT help.h yet...
|
|
//#else
|
|
IDCS_DL_NAME, IDH_TAPI_LOCATIONS,
|
|
IDCC_DL_NAME, IDH_TAPI_LOCATIONS,
|
|
IDCB_DL_NEW_LOCATION, IDH_TAPI_LOCATION_NEW,
|
|
IDCB_DL_REMOVE_LOCATION, IDH_TAPI_LOCATION_REMOVE,
|
|
IDCS_DL_AREACODE, IDH_TAPI_AREA_CODE,
|
|
IDCE_DL_AREACODE, IDH_TAPI_AREA_CODE,
|
|
IDCS_DL_COUNTRY, IDH_TAPI_COUNTRY,
|
|
IDCC_DL_COUNTRY, IDH_TAPI_COUNTRY,
|
|
IDCS_DL_OUTSIDE, IDH_TAPI_ACCESS_LINE,
|
|
IDCE_DL_OUTSIDEACCESS, IDH_TAPI_ACCESS_LINE,
|
|
IDCS_DL_OUTSIDEACCESS, IDH_TAPI_ACCESS_LINE,
|
|
IDCE_DL_LONGDISTANCEACCESS, IDH_TAPI_ACCESS_LINE,
|
|
IDCS_DL_LONGDISTANCEACCESS, IDH_TAPI_ACCESS_LINE,
|
|
IDCK_DL_CALLINGCARD, IDH_TAPI_LOCATION_CARD,
|
|
IDCE_DL_CALLINGCARD, IDH_TAPI_LOCATION_CARD,
|
|
IDCB_DL_CHANGE_CARD, IDH_TAPI_LOCATION_CARD_CHANGE,
|
|
IDCK_DL_CALLWAITING, IDH_TAPI_LOCATION_CALL_WAIT,
|
|
IDCC_DL_CALLWAITING, IDH_TAPI_LOCATION_CALL_WAIT,
|
|
IDCR_PULSE, IDH_TAPI_LOCATION_PULSE,
|
|
IDCR_TONE, IDH_TAPI_LOCATION_PULSE,
|
|
IDCS_DIAL_NUMBER_TEXT, IDH_TAPI_LOCATION_PHONE,
|
|
IDCS_DL_DIAL_NUMBER, IDH_TAPI_LOCATION_PHONE,
|
|
IDCK_DL_IN_LOCAL, IDH_TAPI_LONG_DISTANCE,
|
|
IDC_STATIC+2, (DWORD)-1,
|
|
//#endif
|
|
0, 0
|
|
};
|
|
|
|
static LPWSTR pAddressIn = NULL;
|
|
static LPWSTR pCountry = NULL;
|
|
static LPWSTR pCity = NULL;
|
|
static LPWSTR pSubscriber = NULL;
|
|
|
|
#ifdef PARTIAL_UNICODE
|
|
CHAR szTempString[MAXLEN_NAME];
|
|
#endif
|
|
|
|
static BOOL fInInit;
|
|
|
|
static DWORD dwDialChangedFlags;
|
|
//
|
|
// gpCurrentLocation is needed because when a user types in the
|
|
// name field, we get no notification that it's about to happen
|
|
// (CBN_EDITUPDATE happens before the screen update, but AFTER the
|
|
// listbox has been updated) (it's also used in the calling card
|
|
// dialog proc)
|
|
//
|
|
|
|
|
|
switch (msg)
|
|
{
|
|
case WM_INITDIALOG:
|
|
{
|
|
|
|
InternalDebugOut((10, " WM_INITDIALOG"));
|
|
|
|
fInInit = TRUE;
|
|
|
|
//
|
|
// Read in the cards once. And leave them in mem until
|
|
// we leave.
|
|
//
|
|
|
|
ReadCardsEasy( &gpCardList, &gpnStuff );
|
|
|
|
|
|
//
|
|
// Set some limits on the edit fields
|
|
//
|
|
SendDlgItemMessage(
|
|
hWnd,
|
|
IDCC_DL_NAME,
|
|
EM_LIMITTEXT,
|
|
MAXLEN_NAME,
|
|
0);
|
|
SendDlgItemMessage(
|
|
hWnd,
|
|
IDCE_DL_AREACODE,
|
|
EM_LIMITTEXT,
|
|
MAXLEN_AREACODE,
|
|
0);
|
|
SendDlgItemMessage(
|
|
hWnd,
|
|
IDCE_DL_OUTSIDEACCESS,
|
|
EM_LIMITTEXT,
|
|
MAXLEN_OUTSIDEACCESS,
|
|
0);
|
|
SendDlgItemMessage(
|
|
hWnd,
|
|
IDCE_DL_LONGDISTANCEACCESS,
|
|
EM_LIMITTEXT,
|
|
MAXLEN_LONGDISTANCEACCESS,
|
|
0);
|
|
|
|
|
|
|
|
FillCountriesListbox( hWnd );
|
|
|
|
FillLocationsListbox( hWnd );
|
|
|
|
FillDisableCallWaitingListbox( hWnd );
|
|
|
|
//
|
|
// Ok, now fill in everything else (ie: the things that
|
|
// _might_ change)
|
|
//
|
|
gpCurrentLocation = &gLocationList[GetLocationIndexFromID(gnCurrentLocationID, NULL, 0)];
|
|
FillDialingPropertyDialog( hWnd, gpCurrentLocation );
|
|
|
|
InternalDebugOut((80, " WM_INIT gpCurrentLocation=0x%08lx", (DWORD)gpCurrentLocation));
|
|
InternalDebugOut((80, " WM_INIT gpCurrentLocation->Name=%ls", gpCurrentLocation->NameW));
|
|
|
|
//
|
|
// Start with a clean slate...
|
|
//
|
|
dwDialChangedFlags = 0;
|
|
|
|
|
|
|
|
//
|
|
// If we didn't get an address, don't display the phone number fields
|
|
//
|
|
if (
|
|
(NULL == gpszAddress)
|
|
||
|
|
(gpszAddress[0] == '\0')
|
|
||
|
|
(IsBadStringPtrW(gpszAddress, 512))
|
|
)
|
|
{
|
|
ShowWindow( GetDlgItem( hWnd, IDCS_DIAL_NUMBER_TEXT), SW_HIDE);
|
|
ShowWindow( GetDlgItem( hWnd, IDCS_DL_DIAL_NUMBER), SW_HIDE);
|
|
ShowWindow( GetDlgItem( hWnd, IDCK_DL_IN_LOCAL), SW_HIDE);
|
|
}
|
|
else
|
|
{
|
|
UpdateNumberField( hWnd, gpszAddress);
|
|
|
|
pAddressIn = ClientAlloc( (lstrlenW(gpszAddress) + 1) *sizeof(WCHAR));
|
|
lstrcpyW( pAddressIn, gpszAddress );
|
|
|
|
//
|
|
//WARNING!! CODE BELOW DEPENDS ON 'n' BEING PRESERVED!!!!
|
|
//
|
|
n = BreakupCanonicalW( pAddressIn+1,
|
|
&pCountry,
|
|
&pCity,
|
|
&pSubscriber
|
|
);
|
|
|
|
// //
|
|
// // If the caller is really trying to annoy us, let's ignore what
|
|
// // he's saying
|
|
// //
|
|
// if ( n )
|
|
// {
|
|
// ShowWindow( GetDlgItem( hWnd, IDCK_DL_IN_LOCAL), SW_HIDE);
|
|
// ShowWindow( GetDlgItem( hWnd, IDCS_DIAL_NUMBER_TEXT), SW_HIDE);
|
|
// ShowWindow( GetDlgItem( hWnd, IDCS_DL_DIAL_NUMBER), SW_HIDE);
|
|
// ShowWindow( GetDlgItem( hWnd, IDCK_DL_IN_LOCAL), SW_HIDE);
|
|
// }
|
|
|
|
if ( gpCurrentLocation->dwCountry != 1 )
|
|
{
|
|
ShowWindow( GetDlgItem( hWnd, IDCK_DL_IN_LOCAL), SW_HIDE);
|
|
}
|
|
else
|
|
{
|
|
|
|
// Set or clear the "Dial as long distance" button as appropriate
|
|
// (Or maybe don't show it at all...)
|
|
|
|
//
|
|
// We're in the US - we require area codes, if this is not one,
|
|
// or the dialing number area code is different from the current,
|
|
// or if the canonical breakup failed, this is not a canonical
|
|
// number and _can't_ have the option of being in the Tolllist
|
|
//
|
|
if (
|
|
(pCity == NULL)
|
|
||
|
|
(n != 0)
|
|
||
|
|
( lstrcmpiW( pCity, gpCurrentLocation->AreaCodeW ) )
|
|
)
|
|
{
|
|
ShowWindow( GetDlgItem( hWnd, IDCK_DL_IN_LOCAL), SW_HIDE);
|
|
}
|
|
else
|
|
{
|
|
if ( InPrefixList(pSubscriber, gpCurrentLocation) )
|
|
{
|
|
CheckDlgButton( hWnd, IDCK_DL_IN_LOCAL, TRUE );
|
|
}
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
//
|
|
// If there is only one location, disable the remove button
|
|
//
|
|
n = SendDlgItemMessage(
|
|
hWnd,
|
|
IDCC_DL_NAME,
|
|
CB_GETCOUNT,
|
|
0,
|
|
0
|
|
);
|
|
|
|
if ( n < 2 ) // (use < 2 not == 1 "just in case")
|
|
{
|
|
EnableWindow( GetDlgItem(hWnd, IDCB_DL_REMOVE_LOCATION), FALSE );
|
|
}
|
|
|
|
|
|
fInInit = FALSE;
|
|
}
|
|
break;
|
|
|
|
|
|
// Process clicks on controls after Context Help mode selected
|
|
case WM_HELP:
|
|
InternalDebugOut((50, " WM_HELP in LocDefineDlg"));
|
|
WinHelp (((LPHELPINFO) lParam)->hItemHandle, "windows.hlp", HELP_WM_HELP,
|
|
(DWORD)(LPSTR) aIds);
|
|
// uResult = FALSE;
|
|
break;
|
|
|
|
|
|
// Process right-clicks on controls
|
|
case WM_CONTEXTMENU:
|
|
InternalDebugOut((50, " WM_CONTEXT_MENU in LocationsDlgProc"));
|
|
WinHelp ((HWND) wParam, "windows.hlp", HELP_CONTEXTMENU, (DWORD)(LPVOID) aIds);
|
|
// uResult = FALSE;
|
|
break;
|
|
|
|
|
|
case WM_NOTIFY:
|
|
{
|
|
LPNMHDR lpnm = (LPNMHDR)lParam;
|
|
|
|
switch ( lpnm->code )
|
|
{
|
|
|
|
case PSN_APPLY: /* case IDOK */
|
|
{
|
|
LPLINECOUNTRYLIST pLCL;
|
|
|
|
InternalDebugOut((80, " PSN_APPLY - Locations"));
|
|
|
|
if (!CheckForDupLocation(hWnd,
|
|
iStaticLastNameEdited))
|
|
{
|
|
SetWindowLong( hWnd, DWL_MSGRESULT, TRUE );
|
|
return TRUE;
|
|
}
|
|
|
|
//
|
|
// Is the user just trying to annoy us?
|
|
//
|
|
if ( 0 == UtilGetEditNumStr(
|
|
hWnd,
|
|
IDCE_DL_AREACODE,
|
|
UTIL_BIG_EXTENDED
|
|
)
|
|
)
|
|
{
|
|
SetWindowLong( hWnd, DWL_MSGRESULT, TRUE );
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
//
|
|
// Does this country require an area code and is one supplied?
|
|
//
|
|
if ( SimpleProcessing( hWnd, gpCurrentLocation ) )
|
|
{
|
|
return( TRUE );
|
|
}
|
|
|
|
|
|
//
|
|
// Write locations info out (in case they changed)
|
|
//
|
|
|
|
EnterCriticalSection( &gUICriticalSection );
|
|
|
|
WriteLocations( gLocationList, gnNumLocations,
|
|
dwDialChangedFlags, gpCurrentLocation );
|
|
|
|
dwDialChangedFlags = 0;
|
|
|
|
|
|
//
|
|
// Did the user press OK? (As opposed to APPLY)
|
|
//
|
|
if ( ((LPPSHNOTIFY)lpnm)->lParam )
|
|
{
|
|
//
|
|
// Yes. Let's free this stuff.
|
|
//
|
|
Free_gLocationList();
|
|
|
|
|
|
if (gpCardList)
|
|
ClientFree(gpCardList);
|
|
|
|
if (gpnStuff)
|
|
ClientFree(gpnStuff);
|
|
|
|
if ( pAddressIn )
|
|
ClientFree( pAddressIn );
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// If the user checked the "disable call waiting" box,
|
|
// but didn't enter anything, disable it again
|
|
//
|
|
CheckDlgButton( hWnd,
|
|
IDCK_DL_CALLWAITING,
|
|
(gpCurrentLocation->dwFlags & LOCATION_HASCALLWAITING) );
|
|
|
|
EnableWindow( GetDlgItem(hWnd, IDCC_DL_CALLWAITING),
|
|
(gpCurrentLocation->dwFlags & LOCATION_HASCALLWAITING) ?
|
|
TRUE :
|
|
FALSE
|
|
);
|
|
|
|
}
|
|
|
|
|
|
LeaveCriticalSection( &gUICriticalSection );
|
|
|
|
}
|
|
break;
|
|
|
|
|
|
|
|
case PSN_RESET: /* case IDCANCEL: */
|
|
{
|
|
InternalDebugOut((80, " PSN_RESET - Locations"));
|
|
//
|
|
// Yes. Let's free this stuff.
|
|
//
|
|
Free_gLocationList();
|
|
|
|
if (gpCardList)
|
|
ClientFree(gpCardList);
|
|
if (gpnStuff)
|
|
ClientFree(gpnStuff);
|
|
|
|
if ( pAddressIn )
|
|
ClientFree( pAddressIn );
|
|
}
|
|
break;
|
|
|
|
|
|
#if DBG
|
|
case PSN_SETACTIVE:
|
|
InternalDebugOut((80, " PSN_SETACTIVE - Locations"));
|
|
break;
|
|
|
|
|
|
case PSN_KILLACTIVE:
|
|
InternalDebugOut((80, " PSN_KILLACTIVE - Locations"));
|
|
break;
|
|
#endif
|
|
|
|
|
|
}
|
|
}
|
|
break;
|
|
|
|
|
|
case WM_COMMAND:
|
|
{
|
|
LONG lThisItemIndex;
|
|
PLOCATION pThisLocation;
|
|
|
|
|
|
// InternalDebugOut((80, " dwDialChangedFlags=0x%08lx",(DWORD)dwDialChangedFlags));
|
|
|
|
|
|
//
|
|
// Get our pointer to the location struct
|
|
//
|
|
pThisLocation = gpCurrentLocation;
|
|
|
|
#if DBG
|
|
if ( gLocationList )
|
|
{
|
|
InternalDebugOut((11, " pThisLocation ->%ls", (LPSTR)pThisLocation->NameW));
|
|
//DBGOUT((0, " gpCurrentLocation ->%s", (LPSTR)gpCurrentLocation->Name));
|
|
}
|
|
else
|
|
{
|
|
InternalDebugOut((10, " --- gLocationList has been freed! Why am I here?"));
|
|
}
|
|
#endif
|
|
|
|
switch (LOWORD(wParam))
|
|
{
|
|
case IDCB_DL_CHANGE_CARD:
|
|
{
|
|
|
|
//
|
|
// Compare calling card before and after
|
|
//
|
|
n = pThisLocation->dwCallingCard;
|
|
|
|
#ifdef PARTIAL_UNICODE
|
|
DialogBox(
|
|
ghInst,
|
|
MAKEINTRESOURCE(IDD_CALLING_CARD_CHANGE),
|
|
hWnd,
|
|
CallingCardProc
|
|
);
|
|
#else
|
|
DialogBoxW(
|
|
ghInst,
|
|
MAKEINTRESOURCEW(IDD_CALLING_CARD_CHANGE),
|
|
hWnd,
|
|
CallingCardProc
|
|
);
|
|
#endif
|
|
|
|
if ( n != pThisLocation->dwCallingCard )
|
|
{
|
|
//
|
|
// Update the calingcard name field in case it changed
|
|
//
|
|
n = GetCardIndexFromID( pThisLocation->dwCallingCard,
|
|
gpCardList,
|
|
gpnStuff[2]
|
|
);
|
|
|
|
if ( (UINT)(-1) == n )
|
|
{
|
|
n = 0;
|
|
}
|
|
|
|
#ifdef PARTIAL_UNICODE
|
|
WideCharToMultiByte(
|
|
GetACP(),
|
|
0,
|
|
gpCardList[n].NameW,
|
|
-1,
|
|
szTempString,
|
|
MAXLEN_NAME,
|
|
NULL,
|
|
NULL
|
|
);
|
|
#endif
|
|
|
|
|
|
#ifdef PARTIAL_UNICODE
|
|
SetDlgItemText(
|
|
#else
|
|
SetDlgItemTextW(
|
|
#endif
|
|
hWnd,
|
|
IDCE_DL_CALLINGCARD,
|
|
#ifdef PARTIAL_UNICODE
|
|
szTempString
|
|
#else
|
|
gpCardList[n].NameW
|
|
#endif
|
|
);
|
|
|
|
|
|
dwDialChangedFlags |= CHANGEDFLAGS_REALCHANGE;
|
|
|
|
UpdateNumberField( hWnd, gpszAddress);
|
|
|
|
//
|
|
// Activate the APPLY button if not already done
|
|
//
|
|
PropSheet_Changed(GetParent(hWnd), hWnd);
|
|
}
|
|
|
|
}
|
|
break;
|
|
|
|
|
|
|
|
case IDCB_DL_NEW_LOCATION:
|
|
{
|
|
PLOCATION pTemp;
|
|
|
|
|
|
//
|
|
//
|
|
//BUGBUG performance(minor): Should first scan for deleted location entries
|
|
pTemp = ClientAlloc( (gnNumLocations+1)*sizeof(LOCATION) );
|
|
|
|
if ( pTemp )
|
|
{
|
|
//
|
|
// Fill in with the old contents
|
|
//
|
|
CopyMemory( pTemp,
|
|
gLocationList,
|
|
gnNumLocations * sizeof(LOCATION)
|
|
);
|
|
|
|
|
|
|
|
//
|
|
// Fill in with the defaults of the current location
|
|
//
|
|
CopyMemory( &pTemp[gnNumLocations],
|
|
gpCurrentLocation,
|
|
sizeof(LOCATION)
|
|
);
|
|
|
|
|
|
EnterCriticalSection( &gUICriticalSection );
|
|
|
|
//
|
|
// gLocationList is dead. Long live gLocationList
|
|
//
|
|
ClientFree( gLocationList );
|
|
gLocationList = pTemp;
|
|
|
|
LeaveCriticalSection( &gUICriticalSection );
|
|
|
|
|
|
//
|
|
// Make this new location the current location
|
|
//
|
|
gpCurrentLocation = &gLocationList[gnNumLocations];
|
|
|
|
//
|
|
// Get a proper new location ID
|
|
//
|
|
AllocNewID( HKEY_LOCAL_MACHINE,
|
|
&(gpCurrentLocation->dwID) );
|
|
|
|
|
|
dwDialChangedFlags |= ( CHANGEDFLAGS_CURLOCATIONCHANGED |
|
|
CHANGEDFLAGS_TOLLLIST );
|
|
|
|
//BUGBUG Should this really be done?
|
|
gnCurrentLocationID = gpCurrentLocation->dwID;
|
|
|
|
gnNumLocations++;
|
|
|
|
UpdateNumberField( hWnd, gpszAddress);
|
|
|
|
|
|
if (
|
|
(gpCurrentLocation->dwCountry == 1)
|
|
&&
|
|
(NULL != gpszAddress)
|
|
&&
|
|
(gpszAddress[0] != '\0')
|
|
)
|
|
{
|
|
ShowWindow( GetDlgItem( hWnd, IDCK_DL_IN_LOCAL), SW_SHOW);
|
|
}
|
|
else
|
|
{
|
|
ShowWindow( GetDlgItem( hWnd, IDCK_DL_IN_LOCAL), SW_HIDE);
|
|
}
|
|
|
|
buf1 = ClientAlloc( sizeof(gpCurrentLocation->NameW) );
|
|
|
|
//
|
|
// Get in the default name
|
|
//
|
|
LoadStringW( ghInst,
|
|
IDS_NEWLOCATION,
|
|
buf1,
|
|
MAXLEN_NAME);
|
|
|
|
//
|
|
// First, look for the vanilla name
|
|
//
|
|
lstrcpyW( gpCurrentLocation->NameW, buf1 );
|
|
|
|
|
|
//
|
|
// Make sure we don't duplicate the name
|
|
//
|
|
|
|
n = 1;
|
|
fFoundACleanNumber = FALSE;
|
|
|
|
while( FALSE == fFoundACleanNumber )
|
|
{
|
|
|
|
//DBGOUT((1, "gnNumLocations=0x%08lx", gnNumLocations));
|
|
|
|
//
|
|
// Is this number in the list?
|
|
//
|
|
for (
|
|
nCurrent=0;
|
|
nCurrent < gnNumLocations;
|
|
nCurrent++
|
|
)
|
|
{
|
|
|
|
//DBGOUT((1, "gLocation[nCurrent]=0x%08lx gpCurrentloc=0x%08lx",
|
|
//&(gLocationList[nCurrent]), gpCurrentLocation));
|
|
|
|
//
|
|
// Don't check the new location
|
|
//
|
|
if ( &(gLocationList[nCurrent]) != gpCurrentLocation )
|
|
{
|
|
|
|
//DBGOUT((1, "loclist[n]=[%ls] curloc->name=[%ls]",
|
|
// gLocationList[nCurrent].NameW,
|
|
// gpCurrentLocation->NameW ));
|
|
|
|
//
|
|
// Is it in the list already?
|
|
//
|
|
if ( 0 == lstrcmpiW(
|
|
gLocationList[nCurrent].NameW,
|
|
gpCurrentLocation->NameW
|
|
)
|
|
)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if ( nCurrent == gnNumLocations )
|
|
{
|
|
fFoundACleanNumber = TRUE;
|
|
continue;
|
|
}
|
|
|
|
//
|
|
// Set up the string for the next contestant
|
|
//
|
|
n++;
|
|
wsprintfW(
|
|
gpCurrentLocation->NameW,
|
|
L"%ls (%ld)",
|
|
buf1,
|
|
n
|
|
);
|
|
}
|
|
|
|
RedoLocationListbox( hWnd,
|
|
gLocationList,
|
|
gnNumLocations,
|
|
gpCurrentLocation
|
|
);
|
|
|
|
//
|
|
// We just added a location, so we _KNOW_ there are at
|
|
// least 2 locations...
|
|
//
|
|
EnableWindow( GetDlgItem(hWnd, IDCB_DL_REMOVE_LOCATION), TRUE );
|
|
|
|
//
|
|
// Update the dialog box
|
|
//
|
|
FillDialingPropertyDialog( hWnd, gpCurrentLocation);
|
|
|
|
//
|
|
// We've already allocated buf1, so just get buf2 here.
|
|
//
|
|
buf2 = ClientAlloc( sizeof(gpCurrentLocation->NameW) );
|
|
|
|
LoadStringW(ghInst, IDCS_DL_CREATED_LOCATION, buf1, 512 );
|
|
LoadStringW(ghInst, DIALINGPROPERTIES_NAME, buf2, 512 );
|
|
|
|
MessageBoxW( hWnd,
|
|
buf1,
|
|
buf2,
|
|
MB_OK
|
|
);
|
|
|
|
ClientFree( buf1 );
|
|
ClientFree( buf2 );
|
|
|
|
SetFocus(GetDlgItem(hWnd, IDCC_DL_NAME));
|
|
}
|
|
#if DBG
|
|
else
|
|
{
|
|
InternalDebugOut((1, "Out of mem for new location!"));
|
|
}
|
|
#endif
|
|
}
|
|
break;
|
|
|
|
|
|
case IDCB_DL_REMOVE_LOCATION:
|
|
{
|
|
|
|
//
|
|
// Ask the user if he's sure
|
|
//
|
|
|
|
buf1 = ClientAlloc( 512 * sizeof(WCHAR) );
|
|
buf2 = ClientAlloc( 512 * sizeof(WCHAR) );
|
|
|
|
LoadStringW(ghInst, REMOVE_LOCATION, buf1, 512 );
|
|
LoadStringW(ghInst, IDS_WRN_TITLE_SURE, buf2, 512 );
|
|
|
|
if ( MessageBoxW( hWnd,
|
|
buf1,
|
|
buf2,
|
|
MB_YESNO | MB_DEFBUTTON2
|
|
)
|
|
== IDYES )
|
|
{
|
|
|
|
//
|
|
// Activate the APPLY button if not already done
|
|
//
|
|
PropSheet_Changed(GetParent(hWnd), hWnd);
|
|
|
|
|
|
dwDialChangedFlags |= CHANGEDFLAGS_REALCHANGE;
|
|
|
|
|
|
//
|
|
// Mark this location as being "dead"
|
|
//
|
|
pThisLocation->NameW[0] = '\0';
|
|
|
|
|
|
lThisItemIndex = SendDlgItemMessage(
|
|
hWnd,
|
|
IDCC_DL_NAME,
|
|
CB_GETCURSEL,
|
|
0,
|
|
0);
|
|
if (lThisItemIndex == -1 )
|
|
{
|
|
DBGOUT((0, "Found one(2)!!!!"));
|
|
}
|
|
|
|
SendDlgItemMessage(
|
|
hWnd,
|
|
IDCC_DL_NAME,
|
|
CB_DELETESTRING,
|
|
(WPARAM)lThisItemIndex,
|
|
0
|
|
);
|
|
|
|
SendDlgItemMessage(
|
|
hWnd,
|
|
IDCC_DL_NAME,
|
|
CB_SETCURSEL,
|
|
0,
|
|
0
|
|
);
|
|
|
|
dwDialChangedFlags |= CHANGEDFLAGS_CURLOCATIONCHANGED;
|
|
//
|
|
// Get our pointer to the location struct
|
|
//
|
|
gpCurrentLocation = (PLOCATION)(SendDlgItemMessage(
|
|
hWnd,
|
|
IDCC_DL_NAME,
|
|
CB_GETITEMDATA,
|
|
0,
|
|
0));
|
|
pThisLocation = gpCurrentLocation;
|
|
|
|
UpdateNumberField( hWnd, gpszAddress);
|
|
|
|
|
|
if (
|
|
(gpCurrentLocation->dwCountry == 1)
|
|
&&
|
|
(NULL != gpszAddress)
|
|
&&
|
|
(gpszAddress[0] != '\0')
|
|
)
|
|
{
|
|
ShowWindow( GetDlgItem( hWnd, IDCK_DL_IN_LOCAL), SW_SHOW);
|
|
}
|
|
else
|
|
{
|
|
ShowWindow( GetDlgItem( hWnd, IDCK_DL_IN_LOCAL), SW_HIDE);
|
|
}
|
|
|
|
|
|
//
|
|
// If the user deletes a location and there's only one left,
|
|
// disable the remove button
|
|
//
|
|
lThisItemIndex = SendDlgItemMessage(
|
|
hWnd,
|
|
IDCC_DL_NAME,
|
|
CB_GETCOUNT,
|
|
0,
|
|
0
|
|
);
|
|
|
|
if ( lThisItemIndex < 2 ) // (use < 2 not == 1 "just in case")
|
|
{
|
|
EnableWindow( GetDlgItem(hWnd, IDCB_DL_REMOVE_LOCATION), FALSE );
|
|
}
|
|
|
|
}
|
|
|
|
ClientFree( buf1 );
|
|
ClientFree( buf2 );
|
|
|
|
}
|
|
break;
|
|
|
|
|
|
case IDCE_DL_AREACODE:
|
|
{
|
|
//
|
|
// But only do this stuff if something changed...
|
|
//
|
|
if ( EN_CHANGE == HIWORD(wParam) && !fInInit )
|
|
{
|
|
|
|
if ( 0 == UtilGetEditNumStr(
|
|
hWnd,
|
|
LOWORD(wParam),
|
|
UTIL_NUMBER
|
|
)
|
|
)
|
|
{
|
|
//BUGBUG: Disable CLOSE button until user enters a valid area code?
|
|
break;
|
|
}
|
|
|
|
|
|
dwDialChangedFlags |= CHANGEDFLAGS_REALCHANGE;
|
|
|
|
//BUGBUG: Need to warn the user that he's about to throw away his tolllist!!
|
|
|
|
pThisLocation->TollListW[0] = (WCHAR)'\0';
|
|
|
|
//
|
|
// Activate the APPLY button if not already done
|
|
//
|
|
PropSheet_Changed(GetParent(hWnd), hWnd);
|
|
|
|
#ifdef PARTIAL_UNICODE
|
|
GetDlgItemText(
|
|
#else
|
|
GetDlgItemTextW(
|
|
#endif
|
|
hWnd,
|
|
LOWORD(wParam),
|
|
#ifdef PARTIAL_UNICODE
|
|
szTempString,
|
|
#else
|
|
pThisLocation->AreaCodeW,
|
|
#endif
|
|
MAXLEN_AREACODE);
|
|
|
|
#ifdef PARTIAL_UNICODE
|
|
MultiByteToWideChar(
|
|
GetACP(),
|
|
MB_PRECOMPOSED,
|
|
szTempString,
|
|
-1,
|
|
pThisLocation->AreaCodeW,
|
|
MAXLEN_AREACODE
|
|
);
|
|
#endif
|
|
|
|
ShowWindow(
|
|
GetDlgItem( hWnd, IDCK_DL_IN_LOCAL),
|
|
lstrcmpiW(pCity, gpCurrentLocation->AreaCodeW) ?
|
|
SW_HIDE :
|
|
SW_SHOW
|
|
);
|
|
|
|
UpdateNumberField( hWnd, gpszAddress);
|
|
|
|
}
|
|
}
|
|
break;
|
|
|
|
|
|
case IDCE_DL_OUTSIDEACCESS:
|
|
case IDCE_DL_LONGDISTANCEACCESS:
|
|
{
|
|
|
|
//
|
|
// But only do this stuff if something changed...
|
|
//
|
|
if ( EN_CHANGE == HIWORD(wParam) )
|
|
{
|
|
dwDialChangedFlags |= CHANGEDFLAGS_REALCHANGE;
|
|
|
|
//
|
|
// Activate the APPLY button if not already done
|
|
//
|
|
PropSheet_Changed(GetParent(hWnd), hWnd);
|
|
|
|
|
|
#ifdef PARTIAL_UNICODE
|
|
GetDlgItemText(
|
|
#else
|
|
GetDlgItemTextW(
|
|
#endif
|
|
hWnd,
|
|
LOWORD(wParam),
|
|
#ifdef PARTIAL_UNICODE
|
|
szTempString,
|
|
#else
|
|
LOWORD(wParam) == IDCE_DL_OUTSIDEACCESS ?
|
|
pThisLocation->OutsideAccessW :
|
|
pThisLocation->LongDistanceAccessW,
|
|
#endif
|
|
MAXLEN_OUTSIDEACCESS);
|
|
|
|
#ifdef PARTIAL_UNICODE
|
|
MultiByteToWideChar(
|
|
GetACP(),
|
|
MB_PRECOMPOSED,
|
|
szTempString,
|
|
-1,
|
|
LOWORD(wParam) == IDCE_DL_OUTSIDEACCESS ?
|
|
pThisLocation->OutsideAccessW :
|
|
pThisLocation->LongDistanceAccessW,
|
|
MAXLEN_OUTSIDEACCESS
|
|
);
|
|
#endif
|
|
|
|
UpdateNumberField( hWnd, gpszAddress);
|
|
|
|
}
|
|
}
|
|
break;
|
|
|
|
|
|
case IDCK_DL_CALLWAITING:
|
|
{
|
|
dwDialChangedFlags |= CHANGEDFLAGS_REALCHANGE;
|
|
|
|
pThisLocation->dwFlags ^= LOCATION_HASCALLWAITING;
|
|
|
|
|
|
//
|
|
// if box is now checked, enable dropdown
|
|
//
|
|
|
|
EnableWindow( GetDlgItem(hWnd, IDCC_DL_CALLWAITING),
|
|
(pThisLocation->dwFlags & LOCATION_HASCALLWAITING) ?
|
|
TRUE :
|
|
FALSE );
|
|
|
|
|
|
//
|
|
// Activate the APPLY button if not already done
|
|
//
|
|
PropSheet_Changed(GetParent(hWnd), hWnd);
|
|
|
|
UpdateNumberField( hWnd, gpszAddress);
|
|
|
|
}
|
|
break;
|
|
|
|
|
|
case IDCC_DL_CALLWAITING:
|
|
{
|
|
//
|
|
// Process only when something changes
|
|
//
|
|
if ( CBN_EDITCHANGE == HIWORD(wParam) )
|
|
{
|
|
|
|
dwDialChangedFlags |= CHANGEDFLAGS_REALCHANGE;
|
|
|
|
#ifdef PARTIAL_UNICODE
|
|
GetDlgItemText(
|
|
#else
|
|
GetDlgItemTextW(
|
|
#endif
|
|
hWnd,
|
|
LOWORD(wParam),
|
|
#ifdef PARTIAL_UNICODE
|
|
szTempString,
|
|
#else
|
|
pThisLocation->DisableCallWaitingW,
|
|
#endif
|
|
MAXLEN_DISABLECALLWAITING);
|
|
|
|
#ifdef PARTIAL_UNICODE
|
|
MultiByteToWideChar(
|
|
GetACP(),
|
|
MB_PRECOMPOSED,
|
|
szTempString,
|
|
-1,
|
|
pThisLocation->DisableCallWaitingW,
|
|
MAXLEN_DISABLECALLWAITING
|
|
);
|
|
#endif
|
|
|
|
UpdateNumberField( hWnd, gpszAddress);
|
|
|
|
PropSheet_Changed(GetParent(hWnd), hWnd);
|
|
|
|
}
|
|
else
|
|
{
|
|
if ( CBN_SELCHANGE == HIWORD(wParam) )
|
|
{
|
|
|
|
//
|
|
// Get our pointer to the location struct
|
|
//
|
|
n = SendDlgItemMessage(
|
|
hWnd,
|
|
IDCC_DL_CALLWAITING,
|
|
CB_GETCURSEL,
|
|
0,
|
|
0);
|
|
#ifdef PARTIAL_UNICODE
|
|
SendDlgItemMessage(
|
|
#else
|
|
SendDlgItemMessageW(
|
|
#endif
|
|
hWnd,
|
|
IDCC_DL_CALLWAITING,
|
|
CB_GETLBTEXT,
|
|
n,
|
|
#ifdef PARTIAL_UNICODE
|
|
(LPARAM)szTempString
|
|
#else
|
|
(LPARAM)pThisLocation->DisableCallWaitingW
|
|
#endif
|
|
);
|
|
|
|
#ifdef PARTIAL_UNICODE
|
|
MultiByteToWideChar(
|
|
GetACP(),
|
|
MB_PRECOMPOSED,
|
|
szTempString,
|
|
-1,
|
|
pThisLocation->DisableCallWaitingW,
|
|
MAXLEN_AREACODE
|
|
);
|
|
#endif
|
|
|
|
InternalDebugOut((20, " Presto-changeo - %ls", pThisLocation->DisableCallWaitingW));
|
|
|
|
UpdateNumberField( hWnd, gpszAddress);
|
|
|
|
PropSheet_Changed(GetParent(hWnd), hWnd);
|
|
}
|
|
}
|
|
|
|
}
|
|
break;
|
|
|
|
|
|
case IDCK_DL_IN_LOCAL:
|
|
{
|
|
LPWSTR pPrefixLocation = NULL;
|
|
|
|
// LPTSTR pCountry = NULL;
|
|
// LPTSTR pCity = NULL;
|
|
// LPTSTR pSubscriber = NULL;
|
|
// LPTSTR pAddressIn;
|
|
//
|
|
// pAddressIn = ClientAlloc( lstrlen(gpszAddress) + 1);
|
|
// lstrcpy( pAddressIn, gpszAddress );
|
|
//
|
|
//
|
|
// //
|
|
// // Need to pass the pointer to Breakup pointer past the '+'
|
|
// //
|
|
// if ( *pAddressIn == '+' )
|
|
// {
|
|
// pAddressIn++;
|
|
// }
|
|
//
|
|
//
|
|
// BreakupCanonical( pAddressIn,
|
|
// &pCountry,
|
|
// &pCity,
|
|
// &pSubscriber
|
|
// );
|
|
|
|
|
|
pPrefixLocation = InPrefixList(pSubscriber, gpCurrentLocation);
|
|
|
|
if ( IsDlgButtonChecked(hWnd, IDCK_DL_IN_LOCAL) )
|
|
{
|
|
//
|
|
// Make sure this prefix is in the list (add if necessary)
|
|
//
|
|
if ( pPrefixLocation == NULL )
|
|
{
|
|
//
|
|
// If this is the first entry, start the list off right
|
|
//
|
|
if ( pThisLocation->TollListW[0] == (WCHAR)'\0' )
|
|
{
|
|
lstrcatW( pThisLocation->TollListW, L",");
|
|
}
|
|
|
|
|
|
//
|
|
// The entry is not in the list. Add it.
|
|
//
|
|
|
|
//
|
|
// Ok, the data's valid. We won't need to use
|
|
// pSubscriber again, so we'll trash it a bit.
|
|
//
|
|
//BUGBUG: assumption - that a toll prefix is 3 tchars
|
|
pSubscriber[3] = ',';
|
|
pSubscriber[4] = '\0';
|
|
|
|
|
|
lstrcatW( gpCurrentLocation->TollListW, pSubscriber );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Make sure this prefix is not in the list (remove if necessary)
|
|
//
|
|
if (
|
|
(pPrefixLocation != NULL)
|
|
&&
|
|
(lstrlenW(pPrefixLocation) > 1)
|
|
)
|
|
{
|
|
lstrcpyW( pPrefixLocation, wcschr( pPrefixLocation+1, ',') );
|
|
}
|
|
}
|
|
|
|
|
|
// ClientFree( pAddressIn );
|
|
|
|
|
|
dwDialChangedFlags |= CHANGEDFLAGS_TOLLLIST;
|
|
|
|
UpdateNumberField( hWnd, gpszAddress);
|
|
|
|
//
|
|
// Activate the APPLY button if not already done
|
|
//
|
|
PropSheet_Changed(GetParent(hWnd), hWnd);
|
|
|
|
}
|
|
break;
|
|
|
|
|
|
|
|
case IDCK_DL_CALLINGCARD:
|
|
{
|
|
dwDialChangedFlags |= CHANGEDFLAGS_REALCHANGE;
|
|
|
|
pThisLocation->dwFlags ^= LOCATION_USECALLINGCARD;
|
|
|
|
//if this box is being checked, and
|
|
//if the user has no calling card selected, he must choose one now
|
|
//if the user cancels out of choosing the calling card, this
|
|
//check box should be unchecked
|
|
|
|
|
|
//
|
|
// Does this location use a calling card?
|
|
//
|
|
if ( pThisLocation->dwFlags & LOCATION_USECALLINGCARD )
|
|
{
|
|
EnableWindow( GetDlgItem(hWnd, IDCE_DL_CALLINGCARD), TRUE );
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Disable the Calling Card name field
|
|
//
|
|
EnableWindow( GetDlgItem(hWnd, IDCE_DL_CALLINGCARD), FALSE );
|
|
}
|
|
|
|
|
|
//
|
|
// Activate the APPLY button if not already done
|
|
//
|
|
PropSheet_Changed(GetParent(hWnd), hWnd);
|
|
|
|
UpdateNumberField( hWnd, gpszAddress);
|
|
|
|
}
|
|
break;
|
|
|
|
|
|
case IDCR_TONE:
|
|
case IDCR_PULSE:
|
|
{
|
|
dwDialChangedFlags |= CHANGEDFLAGS_REALCHANGE;
|
|
|
|
pThisLocation->dwFlags ^= LOCATION_USETONEDIALING;
|
|
FillDialingPropertyDialog( hWnd, pThisLocation );
|
|
|
|
// UpdateNumberField( hWnd, gpszAddress);
|
|
|
|
//
|
|
// Activate the APPLY button if not already done
|
|
//
|
|
PropSheet_Changed(GetParent(hWnd), hWnd);
|
|
|
|
}
|
|
break;
|
|
|
|
|
|
case IDCC_DL_COUNTRY:
|
|
{
|
|
LONG lThisCountryIndex;
|
|
|
|
//
|
|
// Only process if something is changing
|
|
//
|
|
switch HIWORD(wParam)
|
|
{
|
|
case CBN_SELCHANGE:
|
|
{
|
|
|
|
dwDialChangedFlags |= CHANGEDFLAGS_REALCHANGE;
|
|
|
|
lThisCountryIndex = SendDlgItemMessage(
|
|
hWnd,
|
|
IDCC_DL_COUNTRY,
|
|
CB_GETCURSEL,
|
|
0,
|
|
0);
|
|
|
|
pThisLocation->dwCountry = SendDlgItemMessage(
|
|
hWnd,
|
|
IDCC_DL_COUNTRY,
|
|
CB_GETITEMDATA,
|
|
lThisCountryIndex,
|
|
0);
|
|
|
|
|
|
UpdateNumberField( hWnd, gpszAddress);
|
|
|
|
|
|
if (
|
|
(gpCurrentLocation->dwCountry == 1)
|
|
&&
|
|
(NULL != gpszAddress)
|
|
&&
|
|
(gpszAddress[0] != '\0')
|
|
)
|
|
{
|
|
ShowWindow( GetDlgItem( hWnd, IDCK_DL_IN_LOCAL), SW_SHOW);
|
|
}
|
|
else
|
|
{
|
|
ShowWindow( GetDlgItem( hWnd, IDCK_DL_IN_LOCAL), SW_HIDE);
|
|
}
|
|
|
|
|
|
//
|
|
// Activate the APPLY button if not already done
|
|
//
|
|
PropSheet_Changed(GetParent(hWnd), hWnd);
|
|
}
|
|
|
|
}
|
|
}
|
|
break;
|
|
|
|
|
|
case IDCC_DL_NAME:
|
|
{
|
|
switch (HIWORD(wParam))
|
|
{
|
|
|
|
case CBN_EDITCHANGE:
|
|
{
|
|
WCHAR szTempString1[MAXLEN_NAME];
|
|
|
|
//
|
|
// The user is typing in the name edit area
|
|
//
|
|
|
|
// Get the new name
|
|
GetDlgItemTextW(
|
|
hWnd,
|
|
IDCC_DL_NAME,
|
|
szTempString1,
|
|
MAXLEN_NAME
|
|
);
|
|
|
|
// check for null name
|
|
if (szTempString1[0] == L'\0')
|
|
{
|
|
PWSTR buf1;
|
|
PWSTR buf2;
|
|
|
|
buf1 = ClientAlloc( 512 * sizeof(WCHAR));
|
|
buf2 = ClientAlloc( 512 * sizeof(WCHAR));
|
|
|
|
// put up dialog
|
|
LoadStringW(ghInst, IDS_DL_NULL_NAME, buf1, 512 );
|
|
LoadStringW(ghInst, IDS_DL_NULL_NAME_CAPTION, buf2, 512 );
|
|
|
|
MessageBoxW( hWnd,
|
|
buf1,
|
|
buf2,
|
|
MB_OK
|
|
);
|
|
|
|
ClientFree( buf1 );
|
|
ClientFree( buf2 );
|
|
|
|
// redo the listbox to get what was there
|
|
// before the item was made null
|
|
SendDlgItemMessage(
|
|
hWnd,
|
|
IDCC_DL_NAME,
|
|
CB_GETEDITSEL,
|
|
(DWORD)&n,
|
|
(DWORD)&nCurrent);
|
|
|
|
RedoLocationListbox( hWnd,
|
|
gLocationList,
|
|
gnNumLocations,
|
|
gpCurrentLocation);
|
|
|
|
SendDlgItemMessage(
|
|
hWnd,
|
|
IDCC_DL_NAME,
|
|
CB_SETEDITSEL,
|
|
0,
|
|
MAKELPARAM( n, nCurrent) );
|
|
|
|
iStaticLastNameEdited = SendDlgItemMessage(hWnd,
|
|
IDCC_DL_NAME,
|
|
CB_GETCURSEL,
|
|
0,
|
|
0);
|
|
|
|
// set the focus too
|
|
SetFocus(GetDlgItem(hWnd,
|
|
IDCC_DL_NAME));
|
|
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
// copy sztempstring1 to pThisLocation
|
|
#ifdef PARTIAL_UNICODE
|
|
MultiByteToWideChar(
|
|
GetACP(),
|
|
MB_PRECOMPOSED,
|
|
szTempString1,
|
|
-1,
|
|
pThisLocation->NameW,
|
|
MAXLEN_NAME
|
|
);
|
|
#else
|
|
lstrcpyW(pThisLocation->NameW, szTempString1);
|
|
#endif
|
|
|
|
SendDlgItemMessage(
|
|
hWnd,
|
|
IDCC_DL_NAME,
|
|
CB_GETEDITSEL,
|
|
(DWORD)&n,
|
|
(DWORD)&nCurrent);
|
|
|
|
RedoLocationListbox( hWnd,
|
|
gLocationList,
|
|
gnNumLocations,
|
|
gpCurrentLocation);
|
|
|
|
SendDlgItemMessage(
|
|
hWnd,
|
|
IDCC_DL_NAME,
|
|
CB_SETEDITSEL,
|
|
0,
|
|
MAKELPARAM( n, nCurrent) );
|
|
|
|
iStaticLastNameEdited = SendDlgItemMessage(hWnd,
|
|
IDCC_DL_NAME,
|
|
CB_GETCURSEL,
|
|
0,
|
|
0);
|
|
|
|
dwDialChangedFlags |= CHANGEDFLAGS_REALCHANGE;
|
|
|
|
PropSheet_Changed(GetParent(hWnd), hWnd);
|
|
}
|
|
break;
|
|
|
|
case CBN_SELCHANGE:
|
|
{
|
|
// if the name is a dupe.
|
|
// tell user and "reselect" "current" item
|
|
|
|
if (!CheckForDupLocation(hWnd,
|
|
iStaticLastNameEdited))
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
//
|
|
// Get the current (or being-changed-to) location index
|
|
//
|
|
lThisItemIndex = SendDlgItemMessage(
|
|
hWnd,
|
|
IDCC_DL_NAME,
|
|
CB_GETCURSEL,
|
|
0,
|
|
0);
|
|
if (lThisItemIndex == -1 )
|
|
{
|
|
DBGOUT((0, "Found one(3)!!!!"));
|
|
}
|
|
|
|
//
|
|
// Get our pointer to the location struct
|
|
//
|
|
pThisLocation = (PLOCATION)(SendDlgItemMessage(
|
|
hWnd,
|
|
IDCC_DL_NAME,
|
|
CB_GETITEMDATA,
|
|
lThisItemIndex,
|
|
0));
|
|
if ( pThisLocation == (PLOCATION)-1 )
|
|
{ //this is a test
|
|
// Get the new name
|
|
#ifdef PARTIAL_UNICODE
|
|
GetDlgItemText(
|
|
#else
|
|
GetDlgItemTextW(
|
|
#endif
|
|
hWnd,
|
|
IDCC_DL_NAME,
|
|
#ifdef PARTIAL_UNICODE
|
|
szTempString,
|
|
#else
|
|
pThisLocation->NameW,
|
|
#endif
|
|
MAXLEN_NAME
|
|
);
|
|
|
|
#ifdef PARTIAL_UNICODE
|
|
MultiByteToWideChar(
|
|
GetACP(),
|
|
MB_PRECOMPOSED,
|
|
szTempString,
|
|
-1,
|
|
pThisLocation->NameW,
|
|
MAXLEN_NAME
|
|
);
|
|
#endif
|
|
|
|
|
|
RedoLocationListbox( hWnd,
|
|
gLocationList,
|
|
gnNumLocations,
|
|
gpCurrentLocation);
|
|
pThisLocation = gpCurrentLocation;
|
|
}
|
|
|
|
//
|
|
// Update our "local global static location" pointer
|
|
//
|
|
gpCurrentLocation = pThisLocation;
|
|
|
|
|
|
InternalDebugOut((10, "New name->%ls", pThisLocation->NameW));
|
|
|
|
dwDialChangedFlags |= CHANGEDFLAGS_CURLOCATIONCHANGED;
|
|
|
|
//
|
|
// Since we're going to do something that's going to cause
|
|
// the dialog box to update, let's save the _real_
|
|
// changedflags state and restore after the turmoil.
|
|
//
|
|
{
|
|
DWORD dwTemp;
|
|
|
|
dwTemp = dwDialChangedFlags;
|
|
FillDialingPropertyDialog( hWnd, pThisLocation );
|
|
dwDialChangedFlags = dwTemp;
|
|
}
|
|
|
|
|
|
//this should be a "new location" button press
|
|
|
|
//
|
|
// If there is only one location, disable the remove button
|
|
//
|
|
n = SendDlgItemMessage(
|
|
hWnd,
|
|
IDCC_DL_NAME,
|
|
CB_GETCOUNT,
|
|
0,
|
|
0
|
|
);
|
|
|
|
if ( n < 2 )
|
|
{
|
|
EnableWindow( GetDlgItem(hWnd, IDCB_DL_REMOVE_LOCATION), FALSE );
|
|
}
|
|
else
|
|
{
|
|
EnableWindow( GetDlgItem(hWnd, IDCB_DL_REMOVE_LOCATION), TRUE );
|
|
}
|
|
|
|
|
|
UpdateNumberField( hWnd, gpszAddress);
|
|
|
|
//
|
|
// Activate the APPLY button if not already done
|
|
//
|
|
PropSheet_Changed(GetParent(hWnd), hWnd);
|
|
|
|
}
|
|
|
|
break;
|
|
}
|
|
}
|
|
|
|
}
|
|
}
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
//***************************************************************************
|
|
//***************************************************************************
|
|
//***************************************************************************
|
|
void PASCAL AddAPropertyPage(
|
|
#ifdef PARTIAL_UNICODE
|
|
PROPSHEETHEADER *ppsh,
|
|
#else
|
|
PROPSHEETHEADERW *ppsh,
|
|
#endif
|
|
DLGPROC dlgproc,
|
|
DWORD dwTemplate,
|
|
LPARAM lParam
|
|
)
|
|
{
|
|
#ifdef PARTIAL_UNICODE
|
|
PROPSHEETPAGE psp;
|
|
#else
|
|
PROPSHEETPAGEW psp;
|
|
#endif
|
|
|
|
psp.dwSize = sizeof(psp);
|
|
psp.dwFlags = PSP_DEFAULT;
|
|
psp.hInstance = ghInst; //GetModuleHandle (NULL);
|
|
#ifdef PARTIAL_UNICODE
|
|
psp.pszTemplate = MAKEINTRESOURCE(dwTemplate);
|
|
#else
|
|
psp.pszTemplate = MAKEINTRESOURCEW(dwTemplate);
|
|
#endif
|
|
psp.pfnDlgProc = dlgproc;
|
|
|
|
psp.lParam = lParam;
|
|
|
|
#ifdef PARTIAL_UNICODE
|
|
ppsh->phpage[ppsh->nPages] = CreatePropertySheetPage(&psp);
|
|
#else
|
|
ppsh->phpage[ppsh->nPages] = CreatePropertySheetPageW(&psp);
|
|
#endif
|
|
|
|
if (ppsh->phpage[ppsh->nPages])
|
|
{
|
|
ppsh->nPages++;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
//***************************************************************************
|
|
//***************************************************************************
|
|
//***************************************************************************
|
|
LONG
|
|
WINAPI
|
|
lineTranslateDialogW(
|
|
HLINEAPP hLineApp,
|
|
DWORD dwDeviceID,
|
|
DWORD dwAPIVersion,
|
|
HWND hwndOwner,
|
|
LPCWSTR lpszAddressIn
|
|
)
|
|
{
|
|
|
|
HPROPSHEETPAGE rPages[MAXPROPPAGES];
|
|
PROPSHEETPAGE psp;
|
|
#ifdef PARTIAL_UNICODE
|
|
CHAR szCaption[128];
|
|
PROPSHEETHEADER psh;
|
|
#else
|
|
WCHAR szCaption[128];
|
|
PROPSHEETHEADERW psh;
|
|
#endif
|
|
LONG lResult;
|
|
UINT uUpdated;
|
|
|
|
PLOCATION MyLocationList = NULL;
|
|
// PCARD MyCardList = NULL;
|
|
PUINT pnStuff = NULL;
|
|
|
|
|
|
|
|
if (!gbInternalTranslate)
|
|
{
|
|
lResult = IsThisAPIVersionInvalid( dwAPIVersion );
|
|
if ( lResult )
|
|
{
|
|
DBGOUT((1, "Bad dwAPIVersion - 0x%08lx", dwAPIVersion));
|
|
return lResult;
|
|
}
|
|
}
|
|
|
|
|
|
if ( lpszAddressIn && IsBadStringPtrW(lpszAddressIn, (UINT)-1) )
|
|
{
|
|
DBGOUT((1, "Bad lpszAddressIn pointer (0x%08lx)", lpszAddressIn));
|
|
return( LINEERR_INVALPOINTER);
|
|
}
|
|
|
|
|
|
CheckCards();
|
|
|
|
|
|
if (hwndOwner && !IsWindow (hwndOwner))
|
|
{
|
|
InternalDebugOut((1, " hwndOwner is bogus"));
|
|
return LINEERR_INVALPARAM;
|
|
}
|
|
|
|
|
|
|
|
lResult = ReadLocations( &MyLocationList,
|
|
&pnStuff,
|
|
hLineApp,
|
|
dwDeviceID,
|
|
dwAPIVersion,
|
|
CHECKPARMS_DWHLINEAPP |
|
|
CHECKPARMS_DWDEVICEID |
|
|
CHECKPARMS_DWAPIVERSION
|
|
);
|
|
if (
|
|
(0 != lResult)
|
|
&&
|
|
( lResult != LINEERR_INIFILECORRUPT )
|
|
)
|
|
{
|
|
InternalDebugOut((1, "Leaving lineTranslateDialogW result=0x%08lx", lResult));
|
|
return lResult;
|
|
}
|
|
|
|
|
|
|
|
// pdwStuff[2] = nNumLocations;
|
|
|
|
if (
|
|
(lResult == LINEERR_INIFILECORRUPT)
|
|
||
|
|
(0 == pnStuff[2])
|
|
||
|
|
gbTranslateSimple
|
|
)
|
|
{
|
|
#ifdef PARTIAL_UNICODE
|
|
DialogBoxParam(
|
|
ghInst,
|
|
MAKEINTRESOURCE(IDD_DEFINE_LOCATION_SIMPLE),
|
|
hwndOwner,
|
|
LocDefineDlgSimple,
|
|
gbTranslateSilent
|
|
);
|
|
#else
|
|
DialogBoxParamW(
|
|
ghInst,
|
|
MAKEINTRESOURCEW(IDD_DEFINE_LOCATION_SIMPLE),
|
|
hwndOwner,
|
|
LocDefineDlgSimple,
|
|
gbTranslateSilent
|
|
);
|
|
#endif
|
|
|
|
if (gbTranslateSimple)
|
|
{
|
|
gbTranslateSimple = FALSE;
|
|
gbTranslateSilent = FALSE;
|
|
return 0;
|
|
}
|
|
|
|
// return 0;
|
|
// After displaying the MiniDialHelper, fall through to the main
|
|
// DialingProperties
|
|
|
|
}
|
|
|
|
|
|
gpszAddress = (PWSTR)lpszAddressIn;
|
|
|
|
|
|
//*** *** ***BUGBUG set event so no other process starts one of these
|
|
|
|
psh.dwSize = sizeof(psh);
|
|
psh.dwFlags = PSH_DEFAULT; //PSH_NOAPPLYNOW;
|
|
psh.hwndParent = hwndOwner; //GetFocus(); //NULL; //hwnd;
|
|
psh.hInstance = ghInst; //GetModuleHandle(NULL);
|
|
|
|
#ifdef PARTIAL_UNICODE
|
|
LoadString(
|
|
#else
|
|
LoadStringW(
|
|
#endif
|
|
ghInst,
|
|
DIALINGPROPERTIES_NAME,
|
|
szCaption,
|
|
sizeof(szCaption) / sizeof(WCHAR)
|
|
);
|
|
|
|
psh.pszCaption = szCaption;
|
|
psh.nPages = 0;
|
|
psh.nStartPage = 0;
|
|
psh.phpage = rPages;
|
|
|
|
|
|
// psp.dwSize = sizeof(psp);
|
|
// psp.dwFlags = PSP_DEFAULT;
|
|
// psp.hInstance = ghInst; //GetModuleHandle (NULL);
|
|
// psp.pszTemplate = MAKEINTRESOURCE(IDD_DEFINE_LOCATION);
|
|
// psp.pfnDlgProc = (DLGPROC) LocationsDlgProc;
|
|
// psp.lParam = (LPARAM)lpszAddressIn; //(LPARAM) NULL; // lpszAddressIn;
|
|
//
|
|
// psh.phpage[psh.nPages] = CreatePropertySheetPage (&psp);
|
|
//
|
|
// if (psh.phpage[psh.nPages])
|
|
// {
|
|
// psh.nPages++;
|
|
// }
|
|
|
|
AddAPropertyPage(
|
|
&psh,
|
|
LocationsDlgProc,
|
|
IDD_DEFINE_LOCATION,
|
|
(LPARAM)lpszAddressIn
|
|
);
|
|
|
|
/*
|
|
BUGBUG: This is removed until the story is worked out...
|
|
|
|
AddAPropertyPage(
|
|
&psh,
|
|
GeneralDlgProc,
|
|
IDD_GENERAL,
|
|
0
|
|
);
|
|
*/
|
|
|
|
/*******************************************************************
|
|
********************************************************************
|
|
NOTE: lineTranslateDialog no longer brings up the ConfigureProviders
|
|
tab, since that is only for the telephony cpl. A new internal
|
|
entry point has been added to do both the dialing properties and
|
|
configure providers - internalConfigure(HWND)
|
|
*******************************************************************/
|
|
|
|
if (gbInternalTranslate)
|
|
{
|
|
|
|
{
|
|
#include "..\cpl\resource.h"
|
|
#include "..\cpl\drv.h"
|
|
|
|
//
|
|
// Now build the drivers tab
|
|
//
|
|
|
|
extern CPL gCPL; // app global
|
|
|
|
// init global static data
|
|
//------------------------
|
|
gCPL.hCplInst = ghInst;
|
|
gCPL.uCplApplets = 0;
|
|
gCPL.uInstances = 0;
|
|
gCPL.hCtl3DInst = NULL;
|
|
|
|
lResult = CplInit( hwndOwner, TRUE, &uUpdated );
|
|
|
|
|
|
// psp.dwSize = sizeof(psp);
|
|
// psp.dwFlags = PSP_DEFAULT;
|
|
// psp.hInstance = ghInst;
|
|
// psp.pszTemplate = MAKEINTRESOURCE(IDD_DRIVER_SETUP);
|
|
// psp.pfnDlgProc = (DLGPROC)FDlgDriverList;
|
|
//// psp.lParam = lParam;
|
|
// psp.lParam = 0;
|
|
//
|
|
//
|
|
// psh.phpage[psh.nPages] = CreatePropertySheetPage(&psp);
|
|
//
|
|
//
|
|
// if (psh.phpage[psh.nPages])
|
|
// {
|
|
// psh.nPages++;
|
|
// }
|
|
|
|
AddAPropertyPage(
|
|
&psh,
|
|
FDlgDriverList,
|
|
IDD_DRIVER_SETUP,
|
|
0
|
|
);
|
|
|
|
|
|
}
|
|
|
|
gbInternalTranslate = FALSE;
|
|
|
|
} // if bInternalTranslate
|
|
|
|
|
|
#ifdef PARTIAL_UNICODE
|
|
if (PropertySheet(&psh) < 0)
|
|
#else
|
|
if (PropertySheetW(&psh) < 0)
|
|
#endif
|
|
{
|
|
// lRetval = LINEERR_OPERATIONFAILED;
|
|
InternalDebugOut((1, " PropertySheet(&psh) returns <0 (OPERATION FAILED)"));
|
|
}
|
|
else
|
|
{
|
|
// lRetval = 0L;
|
|
}
|
|
|
|
|
|
if (MyLocationList)
|
|
ClientFree( MyLocationList );
|
|
if (pnStuff)
|
|
ClientFree( pnStuff );
|
|
|
|
|
|
return (0);
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////
|
|
///////////////////////////////////////////////////////////////////////
|
|
// internalConfigure now does exactly what lineTranslateDialog used
|
|
// to do - bring up both dialing properties and configure providers
|
|
///////////////////////////////////////////////////////////////////////
|
|
///////////////////////////////////////////////////////////////////////
|
|
|
|
LONG
|
|
WINAPI
|
|
internalConfig(HWND hwndOwner)
|
|
{
|
|
gbInternalTranslate = TRUE;
|
|
return (lineTranslateDialogW(0,
|
|
0,
|
|
TAPI_VERSION2_0,
|
|
hwndOwner,
|
|
NULL));
|
|
|
|
}
|
|
|
|
|
|
//***************************************************************************
|
|
//***************************************************************************
|
|
//***************************************************************************
|
|
LONG
|
|
WINAPI
|
|
lineTranslateDialogA(
|
|
HLINEAPP hLineApp,
|
|
DWORD dwDeviceID,
|
|
DWORD dwAPIVersion,
|
|
HWND hwndOwner,
|
|
LPCSTR lpszAddressIn
|
|
)
|
|
{
|
|
PWSTR szAddressInW = NULL;
|
|
LONG lResult;
|
|
|
|
|
|
if ( lpszAddressIn && IsBadStringPtr(lpszAddressIn, 512) )
|
|
{
|
|
DBGOUT((1, "Bad string pointer passed to lineTranslateDialog"));
|
|
return LINEERR_INVALPOINTER;
|
|
}
|
|
else
|
|
{
|
|
szAddressInW = MultiToWide( lpszAddressIn );
|
|
}
|
|
|
|
lResult = lineTranslateDialogW(
|
|
hLineApp,
|
|
dwDeviceID,
|
|
dwAPIVersion,
|
|
hwndOwner,
|
|
szAddressInW
|
|
);
|
|
|
|
if ( szAddressInW )
|
|
{
|
|
ClientFree( szAddressInW );
|
|
}
|
|
|
|
return lResult;
|
|
}
|
|
|
|
|
|
//***************************************************************************
|
|
//***************************************************************************
|
|
//***************************************************************************
|
|
LONG
|
|
WINAPI
|
|
lineTranslateDialog(
|
|
HLINEAPP hLineApp,
|
|
DWORD dwDeviceID,
|
|
DWORD dwAPIVersion,
|
|
HWND hwndOwner,
|
|
LPCSTR lpszAddressIn
|
|
)
|
|
{
|
|
return lineTranslateDialogA(
|
|
hLineApp,
|
|
dwDeviceID,
|
|
dwAPIVersion,
|
|
hwndOwner,
|
|
lpszAddressIn
|
|
);
|
|
}
|
|
|
|
|
|
//***************************************************************************
|
|
//***************************************************************************
|
|
//***************************************************************************
|
|
void PASCAL LayDownString( LPCWSTR pInString,
|
|
LPSTR pBuffer,
|
|
LPSTR *ppCurrentIndex,
|
|
LPDWORD pSize // this is the Len & Offset pair
|
|
)
|
|
{
|
|
UINT nTemp;
|
|
LPSTR pTempString;
|
|
|
|
InternalDebugOut((70, "putstring [%ls] at: pbuf:0x%08lx *currind:0x%08lx currind:0x%08lx pSize:0x%08lx",
|
|
pInString, (DWORD)pBuffer, (DWORD)*ppCurrentIndex,
|
|
ppCurrentIndex, pSize));
|
|
|
|
|
|
nTemp = lstrlenW( pInString );
|
|
|
|
//
|
|
// Get some space in which to convert Unicode to local
|
|
//
|
|
pTempString = ClientAlloc( nTemp + 2);
|
|
|
|
|
|
//
|
|
// Also copy and count the NULL terminator
|
|
//
|
|
pSize[0] = nTemp + 1;
|
|
|
|
|
|
//
|
|
// Ultra paranoid because of PPC alignment problems
|
|
// Make sure we're starting on a DWORD boundry
|
|
//
|
|
*ppCurrentIndex = (LPSTR) ((DWORD)( *ppCurrentIndex + 3 ) & ( ~3 ));
|
|
|
|
|
|
pSize[1] = *ppCurrentIndex - pBuffer;
|
|
|
|
InternalDebugOut((71, "Offset= 0x%08lx", (DWORD)pSize[1]));
|
|
|
|
if ( nTemp != 0 )
|
|
{
|
|
WideCharToMultiByte(
|
|
GetACP(),
|
|
0,
|
|
pInString,
|
|
-1,
|
|
pTempString,
|
|
nTemp+1,
|
|
NULL,
|
|
NULL
|
|
);
|
|
|
|
lstrcpy( *ppCurrentIndex, pTempString );
|
|
*ppCurrentIndex += nTemp;
|
|
}
|
|
|
|
//
|
|
// Let's not forget to account for the NULL shall we?
|
|
//
|
|
**ppCurrentIndex = '\0';
|
|
(LPBYTE)*ppCurrentIndex += 1;
|
|
|
|
ClientFree(pTempString);
|
|
}
|
|
|
|
|
|
|
|
//***************************************************************************
|
|
//***************************************************************************
|
|
//***************************************************************************
|
|
void PASCAL LayDownStringW(LPCWSTR pInString,
|
|
LPWSTR pBuffer,
|
|
LPWSTR *ppCurrentIndex,
|
|
LPDWORD pSize // this is the Len & Offset pair
|
|
)
|
|
{
|
|
UINT nTemp;
|
|
|
|
|
|
InternalDebugOut((70, "putstring [%ls] at: pbuf:0x%08lx *currind:0x%08lx currind:0x%08lx pSize:0x%08lx",
|
|
pInString, (DWORD)pBuffer, (DWORD)*ppCurrentIndex,
|
|
ppCurrentIndex, pSize));
|
|
|
|
|
|
nTemp = lstrlenW( pInString );
|
|
|
|
//
|
|
// Also copy and count the NULL terminator
|
|
//
|
|
pSize[0] = (nTemp + 1) * sizeof(WCHAR);
|
|
|
|
|
|
//
|
|
// Ultra paranoid because of PPC alignment problems (and future)
|
|
// Make sure we're starting on a double DWORD boundry
|
|
//
|
|
*ppCurrentIndex = (LPWSTR) ((DWORD)( *ppCurrentIndex + 7 ) & ( ~7 ));
|
|
|
|
|
|
pSize[1] = (LPBYTE)*ppCurrentIndex - (LPBYTE)pBuffer;
|
|
|
|
InternalDebugOut((71, "Offset= 0x%08lx", (DWORD)pSize[1]));
|
|
|
|
if ( nTemp != 0 )
|
|
{
|
|
lstrcpyW( *ppCurrentIndex, pInString );
|
|
*ppCurrentIndex += nTemp;
|
|
}
|
|
|
|
//
|
|
// Let's not forget to account for the NULL shall we?
|
|
//
|
|
**ppCurrentIndex = '\0';
|
|
(LPBYTE)*ppCurrentIndex += 1;
|
|
}
|
|
|
|
|
|
|
|
//***************************************************************************
|
|
//***************************************************************************
|
|
//***************************************************************************
|
|
LONG
|
|
WINAPI
|
|
lineGetTranslateCapsW(
|
|
HLINEAPP hLineApp,
|
|
DWORD dwAPIVersion,
|
|
LPLINETRANSLATECAPS lpTranslateCaps
|
|
)
|
|
{
|
|
|
|
LONG lResult = 0;
|
|
PLOCATION MyLocationList = NULL;
|
|
PCARD MyCardList = NULL;
|
|
PUINT pnStuff = NULL;
|
|
PUINT pnCardStuff = NULL;
|
|
PBYTE pCurrentIndex;
|
|
PBYTE pMyBuffer = NULL;
|
|
register UINT nTemp;
|
|
UINT nFinalSize;
|
|
|
|
UINT nLocationsSize;
|
|
UINT nLocationsStart;
|
|
UINT nCardsSize;
|
|
UINT nCardsStart;
|
|
|
|
|
|
lResult = IsThisAPIVersionInvalid( dwAPIVersion );
|
|
if ( lResult )
|
|
{
|
|
DBGOUT((1, "Bad dwAPIVersion - 0x%08lx", dwAPIVersion));
|
|
return lResult;
|
|
}
|
|
|
|
|
|
if ( IsBadWritePtr(lpTranslateCaps, sizeof(DWORD)*3) )
|
|
{
|
|
InternalDebugOut((1, "lpTranslateCaps not a valid pointer"));
|
|
return LINEERR_INVALPOINTER;
|
|
}
|
|
|
|
|
|
if ( lpTranslateCaps->dwTotalSize < sizeof(LINETRANSLATECAPS))
|
|
{
|
|
InternalDebugOut((1, "Not even enough room for the fixed portion"));
|
|
lResult = LINEERR_STRUCTURETOOSMALL;
|
|
}
|
|
else
|
|
{
|
|
PCARD pThisCard;
|
|
LINECARDENTRY *pThisCardEntry;
|
|
PLOCATION pThisLocation;
|
|
LINELOCATIONENTRY *pThisLocationEntry;
|
|
UINT n;
|
|
|
|
|
|
lResult = ReadLocations( &MyLocationList,
|
|
&pnStuff,
|
|
hLineApp,
|
|
0,
|
|
dwAPIVersion,
|
|
CHECKPARMS_DWHLINEAPP |
|
|
CHECKPARMS_DWAPIVERSION
|
|
);
|
|
if ( 0 != lResult )
|
|
{
|
|
InternalDebugOut((1, "Leaving lineGetTranslateCapsW result=0x%08lx", lResult));
|
|
return lResult;
|
|
}
|
|
|
|
|
|
ReadCardsEasy( &MyCardList, &pnCardStuff );
|
|
|
|
//*** *** ***BUGBUG (dial.c GetTranslateCaps) Need to check return code!
|
|
|
|
|
|
// pdwStuff[0] = nCurrentLocationID;
|
|
// pdwStuff[1] = pLocationList;
|
|
// pdwStuff[2] = nNumLocations;
|
|
|
|
|
|
//
|
|
// Allocate a temp buffer to put the data into.
|
|
// Prepare for worst case
|
|
//
|
|
pMyBuffer = ClientAlloc( (pnStuff[2] *
|
|
(sizeof(LINELOCATIONENTRY) +
|
|
(MAXLEN_NAME *sizeof(WCHAR)) +
|
|
(MAXLEN_AREACODE *sizeof(WCHAR)) +
|
|
(MAXLEN_OUTSIDEACCESS *sizeof(WCHAR)) +
|
|
(MAXLEN_LONGDISTANCEACCESS *sizeof(WCHAR)) +
|
|
(MAXLEN_DISABLECALLWAITING *sizeof(WCHAR)) +
|
|
(MAXLEN_TOLLLIST*sizeof(WCHAR)) +
|
|
100 //mmmm fudge...
|
|
)
|
|
)
|
|
+
|
|
( pnCardStuff[2] *
|
|
(sizeof(LINECARDENTRY) +
|
|
(MAXLEN_CARDNAME *sizeof(WCHAR)) +
|
|
(MAXLEN_PIN *sizeof(WCHAR)) +
|
|
(MAXLEN_RULE*sizeof(WCHAR)) + //Local
|
|
MAXLEN_RULE*sizeof(WCHAR) + //LongDistance
|
|
MAXLEN_RULE*sizeof(WCHAR) + //International
|
|
100 //mmmm fudge...
|
|
)
|
|
)
|
|
);
|
|
|
|
InternalDebugOut((70, "Ptr=0x%08lx Size is:0x%ld",
|
|
pMyBuffer, (DWORD)ClientSize( pMyBuffer )));
|
|
|
|
if ( NULL == pMyBuffer )
|
|
{
|
|
InternalDebugOut((1, " Secondary memory alloc failed!"));
|
|
lResult = LINEERR_NOMEM;
|
|
goto cleanup;
|
|
}
|
|
|
|
|
|
//
|
|
// Start filling in after the main struct
|
|
//
|
|
|
|
|
|
//
|
|
// Do the Location Entries first
|
|
//
|
|
|
|
|
|
pThisLocation = MyLocationList;
|
|
pThisLocationEntry = (LPLINELOCATIONENTRY)((LPBYTE)pMyBuffer +
|
|
sizeof(LINETRANSLATECAPS));
|
|
|
|
nLocationsStart = sizeof(LINETRANSLATECAPS);
|
|
|
|
//
|
|
// Ok, we'll fill in locationentries below. So, now we offset
|
|
// out pointer so we're pointing to where we'll start copying strings.
|
|
//
|
|
pCurrentIndex = (LPBYTE)pThisLocationEntry +
|
|
(sizeof(LINELOCATIONENTRY) * pnStuff[2]);
|
|
|
|
//BUGBUG Backward compatibility! Fix for version 1.3!
|
|
|
|
for ( n = 0; n < pnStuff[2]; n++ )
|
|
{
|
|
|
|
|
|
InternalDebugOut((70, "pThisLoc=0x%08lx pThisLocEntry=0x%08lx pCurIndex=0x%08lx offset=0x%08lx",
|
|
(DWORD)pThisLocation,
|
|
(DWORD)pThisLocationEntry,
|
|
(DWORD)pCurrentIndex,
|
|
(DWORD)((LPBYTE)pCurrentIndex - pMyBuffer) ));
|
|
|
|
//
|
|
// Is this the current location?
|
|
//
|
|
if ( pThisLocation->dwID == pnStuff[0] )
|
|
{
|
|
//
|
|
// Yes. Get the CallingCard ID of this location.
|
|
//
|
|
((LPLINETRANSLATECAPS)pMyBuffer)->dwCurrentPreferredCardID =
|
|
pThisLocation->dwCallingCard;
|
|
}
|
|
|
|
|
|
pThisLocationEntry->dwPermanentLocationID = pThisLocation->dwID;
|
|
|
|
LayDownStringW( pThisLocation->NameW,
|
|
(PWSTR)pMyBuffer,
|
|
(PWSTR *)&pCurrentIndex,
|
|
&(pThisLocationEntry->dwLocationNameSize));
|
|
|
|
pThisLocationEntry->dwCountryCode = pThisLocation->dwCountry;
|
|
|
|
LayDownStringW( pThisLocation->AreaCodeW,
|
|
(PWSTR)pMyBuffer,
|
|
(PWSTR *)&pCurrentIndex,
|
|
&(pThisLocationEntry->dwCityCodeSize));
|
|
|
|
//
|
|
// Only give a CC ID if the "Use Calling Card" flag is set
|
|
//
|
|
if ( LOCATION_USECALLINGCARD & pThisLocation->dwFlags )
|
|
{
|
|
pThisLocationEntry->dwPreferredCardID = pThisLocation->dwCallingCard;
|
|
}
|
|
else
|
|
{
|
|
pThisLocationEntry->dwPreferredCardID = 0;
|
|
}
|
|
|
|
|
|
|
|
//*** *** ***BUGBUG 1.3!
|
|
//if > ver 1.3
|
|
LayDownStringW( pThisLocation->OutsideAccessW,
|
|
(PWSTR)pMyBuffer,
|
|
(PWSTR *)&pCurrentIndex,
|
|
&(pThisLocationEntry->dwLocalAccessCodeSize));
|
|
|
|
LayDownStringW( pThisLocation->LongDistanceAccessW,
|
|
(PWSTR)pMyBuffer,
|
|
(PWSTR *)&pCurrentIndex,
|
|
&(pThisLocationEntry->dwLongDistanceAccessCodeSize));
|
|
|
|
LayDownStringW( pThisLocation->TollListW,
|
|
(PWSTR)pMyBuffer,
|
|
(PWSTR *)&pCurrentIndex,
|
|
&(pThisLocationEntry->dwTollPrefixListSize));
|
|
|
|
pThisLocationEntry->dwCountryID = pThisLocation->dwCountry;
|
|
|
|
pThisLocationEntry->dwOptions = !(pThisLocation->dwFlags &
|
|
LOCATION_USETONEDIALING);
|
|
|
|
LayDownStringW( pThisLocation->DisableCallWaitingW,
|
|
(PWSTR)pMyBuffer,
|
|
(PWSTR *)&pCurrentIndex,
|
|
&(pThisLocationEntry->dwCancelCallWaitingSize));
|
|
|
|
//endif ver > 1.3
|
|
|
|
pThisLocation++;
|
|
pThisLocationEntry++;
|
|
}
|
|
|
|
|
|
//WHAT THE HELL WAS THE +16 FOR?nLocationsSize = pCurrentIndex - pMyBuffer+16;
|
|
nLocationsSize = pCurrentIndex - (pMyBuffer+nLocationsStart);
|
|
|
|
|
|
|
|
pThisCard = MyCardList;
|
|
|
|
//
|
|
// Make sure this is double DWORD aligned for PPC (and future)
|
|
//
|
|
pThisCardEntry = (LINECARDENTRY*)((DWORD)(pCurrentIndex + 7) & (~7)) ;
|
|
|
|
nCardsStart = (LPSTR)pThisCardEntry - pMyBuffer;
|
|
|
|
|
|
//
|
|
// Update the offset pointer to write strings after the CARD structs
|
|
//
|
|
pCurrentIndex = (LPSTR)pThisCardEntry + ( sizeof(LINECARDENTRY) *
|
|
pnCardStuff[2] );
|
|
|
|
for ( n = 0; n < pnCardStuff[2]; n++ )
|
|
{
|
|
|
|
|
|
InternalDebugOut((70, " pThisCard=0x%08lx pCurrentIndex=0x%08lx offset=0x%08lx",
|
|
(DWORD)pThisCard,
|
|
(DWORD)pCurrentIndex,
|
|
(DWORD)((LPBYTE)pCurrentIndex - pMyBuffer) ));
|
|
|
|
pThisCardEntry->dwPermanentCardID = pThisCard->dwID;
|
|
|
|
LayDownStringW( pThisCard->NameW,
|
|
(PWSTR)pMyBuffer,
|
|
(PWSTR *)&pCurrentIndex,
|
|
&(pThisCardEntry->dwCardNameSize));
|
|
|
|
LayDownStringW( pThisCard->LocalRuleW,
|
|
(PWSTR)pMyBuffer,
|
|
(PWSTR *)&pCurrentIndex,
|
|
&(pThisCardEntry->dwSameAreaRuleSize));
|
|
|
|
LayDownStringW( pThisCard->LDRuleW,
|
|
(PWSTR)pMyBuffer,
|
|
(PWSTR *)&pCurrentIndex,
|
|
&(pThisCardEntry->dwLongDistanceRuleSize));
|
|
|
|
LayDownStringW( pThisCard->InternationalRuleW,
|
|
(PWSTR)pMyBuffer,
|
|
(PWSTR *)&pCurrentIndex,
|
|
&(pThisCardEntry->dwInternationalRuleSize));
|
|
|
|
pThisCardEntry->dwCardNumberDigits = lstrlenW(pThisCard->PinW);
|
|
|
|
|
|
pThisCardEntry->dwOptions = pThisCard->dwFlags;
|
|
|
|
|
|
pThisCard++;
|
|
pThisCardEntry++;
|
|
}
|
|
|
|
|
|
nCardsSize = pCurrentIndex - (pMyBuffer+nCardsStart);
|
|
|
|
|
|
//BUGBUG What's the "+16" for?
|
|
nFinalSize = pCurrentIndex - pMyBuffer + 16;
|
|
|
|
|
|
((LPLINETRANSLATECAPS)pMyBuffer)->dwTotalSize = lpTranslateCaps->dwTotalSize;
|
|
|
|
((LPLINETRANSLATECAPS)pMyBuffer)->dwNeededSize = nFinalSize;
|
|
|
|
((LPLINETRANSLATECAPS)pMyBuffer)->dwNumLocations = pnStuff[2];
|
|
|
|
((LPLINETRANSLATECAPS)pMyBuffer)->dwLocationListSize = nFinalSize - sizeof(LINETRANSLATECAPS);
|
|
((LPLINETRANSLATECAPS)pMyBuffer)->dwLocationListOffset =
|
|
sizeof(LINETRANSLATECAPS);
|
|
|
|
((LPLINETRANSLATECAPS)pMyBuffer)->dwCurrentLocationID = pnStuff[0];
|
|
|
|
((LPLINETRANSLATECAPS)pMyBuffer)->dwNumCards = pnCardStuff[2];
|
|
((LPLINETRANSLATECAPS)pMyBuffer)->dwCardListSize = nCardsSize;
|
|
((LPLINETRANSLATECAPS)pMyBuffer)->dwCardListOffset = nCardsStart;
|
|
|
|
|
|
if ( lpTranslateCaps->dwTotalSize < nFinalSize )
|
|
{
|
|
InternalDebugOut((1, "Not enough space to copy the entire buffer"));
|
|
InternalDebugOut((1, "Needed %ld, but had %ld available",
|
|
nFinalSize, lpTranslateCaps->dwTotalSize));
|
|
|
|
((LPLINETRANSLATECAPS)pMyBuffer)->dwUsedSize = sizeof(LINETRANSLATECAPS);
|
|
CopyMemory(
|
|
lpTranslateCaps,
|
|
pMyBuffer,
|
|
sizeof(LINETRANSLATECAPS)
|
|
);
|
|
}
|
|
else
|
|
{
|
|
((LPLINETRANSLATECAPS)pMyBuffer)->dwUsedSize = nFinalSize;
|
|
CopyMemory(
|
|
lpTranslateCaps,
|
|
pMyBuffer,
|
|
nFinalSize
|
|
);
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
if (pMyBuffer)
|
|
ClientFree( pMyBuffer );
|
|
|
|
if (MyLocationList)
|
|
ClientFree( MyLocationList );
|
|
if (MyCardList)
|
|
ClientFree( MyCardList );
|
|
|
|
if (pnCardStuff)
|
|
ClientFree( pnCardStuff );
|
|
if (pnStuff)
|
|
ClientFree( pnStuff );
|
|
|
|
|
|
|
|
|
|
InternalDebugOut((1, " Leaving lineGetTranslateCapsW result=0x%08lx", lResult));
|
|
return (lResult);
|
|
}
|
|
|
|
|
|
|
|
//***************************************************************************
|
|
//***************************************************************************
|
|
//***************************************************************************
|
|
LONG
|
|
WINAPI
|
|
lineGetTranslateCapsA(
|
|
HLINEAPP hLineApp,
|
|
DWORD dwAPIVersion,
|
|
LPLINETRANSLATECAPS lpTranslateCaps
|
|
)
|
|
{
|
|
LONG lResult = 0;
|
|
PLOCATION MyLocationList = NULL;
|
|
PCARD MyCardList = NULL;
|
|
PUINT pnStuff = NULL;
|
|
PUINT pnCardStuff = NULL;
|
|
PBYTE pCurrentIndex;
|
|
PBYTE pMyBuffer = NULL;
|
|
register UINT nTemp;
|
|
UINT nFinalSize;
|
|
|
|
UINT nCardsSize;
|
|
UINT nCardsStart;
|
|
|
|
UINT uLocationEntrySize;
|
|
UINT uCardEntrySize;
|
|
|
|
|
|
lResult = IsThisAPIVersionInvalid( dwAPIVersion );
|
|
if ( lResult )
|
|
{
|
|
DBGOUT((1, "Bad dwAPIVersion - 0x%08lx", dwAPIVersion));
|
|
return lResult;
|
|
}
|
|
|
|
|
|
if ( IsBadWritePtr(lpTranslateCaps, sizeof(DWORD)*3) )
|
|
{
|
|
InternalDebugOut((1, "lpTranslateCaps not a valid pointer"));
|
|
return LINEERR_INVALPOINTER;
|
|
}
|
|
|
|
|
|
if ( TAPI_VERSION1_0 == dwAPIVersion )
|
|
{
|
|
uLocationEntrySize = 28;
|
|
uCardEntrySize = 12;
|
|
}
|
|
else
|
|
{
|
|
uLocationEntrySize = sizeof(LINELOCATIONENTRY);
|
|
uCardEntrySize = sizeof(LINECARDENTRY);
|
|
}
|
|
|
|
|
|
|
|
|
|
if ( lpTranslateCaps->dwTotalSize < sizeof(LINETRANSLATECAPS))
|
|
{
|
|
InternalDebugOut((1, "Not even enough room for the fixed portion"));
|
|
lResult = LINEERR_STRUCTURETOOSMALL;
|
|
}
|
|
else
|
|
{
|
|
PCARD pThisCard;
|
|
LINECARDENTRY *pThisCardEntry;
|
|
PLOCATION pThisLocation;
|
|
LINELOCATIONENTRY *pThisLocationEntry;
|
|
UINT n;
|
|
|
|
|
|
lResult = ReadLocations( &MyLocationList,
|
|
&pnStuff,
|
|
hLineApp,
|
|
0,
|
|
dwAPIVersion,
|
|
CHECKPARMS_DWAPIVERSION |
|
|
CHECKPARMS_DWHLINEAPP
|
|
);
|
|
if ( 0 != lResult )
|
|
{
|
|
InternalDebugOut((1, "Leaving lineGetTranslateCaps result=0x%08lx", lResult));
|
|
return lResult;
|
|
}
|
|
|
|
|
|
ReadCardsEasy( &MyCardList, &pnCardStuff );
|
|
|
|
//*** *** ***BUGBUG (dial.c GetTranslateCaps) Need to check return code!
|
|
|
|
|
|
// pdwStuff[0] = nCurrentLocationID;
|
|
// pdwStuff[1] = pLocationList;
|
|
// pdwStuff[2] = nNumLocations;
|
|
|
|
|
|
//
|
|
// Allocate a temp buffer to put the data into.
|
|
// Prepare for worst case
|
|
//
|
|
pMyBuffer = ClientAlloc( (pnStuff[2] *
|
|
(sizeof(LINELOCATIONENTRY) +
|
|
MAXLEN_NAME +
|
|
MAXLEN_AREACODE +
|
|
MAXLEN_OUTSIDEACCESS +
|
|
MAXLEN_LONGDISTANCEACCESS +
|
|
MAXLEN_DISABLECALLWAITING +
|
|
MAXLEN_TOLLLIST +
|
|
100 //mmmm fudge...
|
|
)
|
|
)
|
|
+
|
|
( pnCardStuff[2] *
|
|
(sizeof(LINECARDENTRY) +
|
|
MAXLEN_CARDNAME +
|
|
MAXLEN_PIN +
|
|
MAXLEN_RULE + //Local
|
|
MAXLEN_RULE + //LongDistance
|
|
MAXLEN_RULE + //International
|
|
100 //mmmm fudge...
|
|
)
|
|
)
|
|
);
|
|
|
|
InternalDebugOut((70, "Ptr=0x%08lx Size is:0x%ld",
|
|
pMyBuffer, (DWORD)ClientSize( pMyBuffer )));
|
|
|
|
if ( NULL == pMyBuffer )
|
|
{
|
|
InternalDebugOut((1, " Secondary memory alloc failed!"));
|
|
lResult = LINEERR_NOMEM;
|
|
goto cleanup;
|
|
}
|
|
|
|
|
|
//
|
|
// Start filling in after the main struct
|
|
//
|
|
|
|
|
|
//
|
|
// Do the Location Entries first
|
|
//
|
|
|
|
|
|
pThisLocation = MyLocationList;
|
|
pThisLocationEntry = (LPLINELOCATIONENTRY)((LPBYTE)pMyBuffer +
|
|
sizeof(LINETRANSLATECAPS));
|
|
|
|
//
|
|
// Ok, we'll fill in locationentries below. So, now we offset
|
|
// out pointer so we're pointing to where we'll start copying strings.
|
|
//
|
|
pCurrentIndex = (LPBYTE)pThisLocationEntry +
|
|
(uLocationEntrySize * pnStuff[2]);
|
|
|
|
|
|
for ( n = 0; n < pnStuff[2]; n++ )
|
|
{
|
|
|
|
|
|
InternalDebugOut((70, "pThisLoc=0x%08lx pThisLocEntry=0x%08lx pCurIndex=0x%08lx offset=0x%08lx",
|
|
(DWORD)pThisLocation,
|
|
(DWORD)pThisLocationEntry,
|
|
(DWORD)pCurrentIndex,
|
|
(DWORD)((LPBYTE)pCurrentIndex - pMyBuffer) ));
|
|
|
|
pThisLocationEntry->dwPermanentLocationID = pThisLocation->dwID;
|
|
|
|
LayDownString( pThisLocation->NameW,
|
|
pMyBuffer,
|
|
&pCurrentIndex,
|
|
&(pThisLocationEntry->dwLocationNameSize));
|
|
|
|
pThisLocationEntry->dwCountryCode = pThisLocation->dwCountry;
|
|
|
|
LayDownString( pThisLocation->AreaCodeW,
|
|
pMyBuffer,
|
|
&pCurrentIndex,
|
|
&(pThisLocationEntry->dwCityCodeSize));
|
|
|
|
//
|
|
// Only give a CC ID if the "Use Calling Card" flag is set
|
|
//
|
|
if ( LOCATION_USECALLINGCARD & pThisLocation->dwFlags )
|
|
{
|
|
pThisLocationEntry->dwPreferredCardID = pThisLocation->dwCallingCard;
|
|
}
|
|
else
|
|
{
|
|
pThisLocationEntry->dwPreferredCardID = 0;
|
|
}
|
|
|
|
|
|
//
|
|
// Is this the current location?
|
|
//
|
|
if ( pThisLocation->dwID == pnStuff[0] )
|
|
{
|
|
//
|
|
// Yes. Get the CallingCard ID of this location.
|
|
//
|
|
((LPLINETRANSLATECAPS)pMyBuffer)->dwCurrentPreferredCardID =
|
|
pThisLocation->dwCallingCard;
|
|
}
|
|
|
|
|
|
if ( dwAPIVersion != TAPI_VERSION1_0 )
|
|
{
|
|
LayDownString( pThisLocation->OutsideAccessW,
|
|
pMyBuffer,
|
|
&pCurrentIndex,
|
|
&(pThisLocationEntry->dwLocalAccessCodeSize));
|
|
|
|
LayDownString( pThisLocation->LongDistanceAccessW,
|
|
pMyBuffer,
|
|
&pCurrentIndex,
|
|
&(pThisLocationEntry->dwLongDistanceAccessCodeSize));
|
|
|
|
LayDownString( pThisLocation->TollListW,
|
|
pMyBuffer,
|
|
&pCurrentIndex,
|
|
&(pThisLocationEntry->dwTollPrefixListSize));
|
|
|
|
pThisLocationEntry->dwCountryID = pThisLocation->dwCountry;
|
|
|
|
pThisLocationEntry->dwOptions = !(pThisLocation->dwFlags &
|
|
LOCATION_USETONEDIALING);
|
|
|
|
LayDownString( pThisLocation->DisableCallWaitingW,
|
|
pMyBuffer,
|
|
&pCurrentIndex,
|
|
&(pThisLocationEntry->dwCancelCallWaitingSize));
|
|
|
|
}
|
|
|
|
|
|
pThisLocation++;
|
|
(LPBYTE)pThisLocationEntry += uLocationEntrySize;
|
|
}
|
|
|
|
|
|
|
|
|
|
pThisCard = MyCardList;
|
|
|
|
//
|
|
// Make sure this is double DWORD aligned for PPC (and future)
|
|
//
|
|
pThisCardEntry = (LINECARDENTRY*)((DWORD)(pCurrentIndex + 7) & (~7)) ;
|
|
|
|
nCardsStart = (LPSTR)pThisCardEntry - pMyBuffer;
|
|
|
|
|
|
//
|
|
// Update the offset pointer to write strings after the CARD structs
|
|
//
|
|
pCurrentIndex = (LPSTR)pThisCardEntry + ( uCardEntrySize *
|
|
pnCardStuff[2] );
|
|
|
|
for ( n = 0; n < pnCardStuff[2]; n++ )
|
|
{
|
|
|
|
|
|
InternalDebugOut((70, " pThisCard=0x%08lx pCurrentIndex=0x%08lx offset=0x%08lx",
|
|
(DWORD)pThisCard,
|
|
(DWORD)pCurrentIndex,
|
|
(DWORD)((LPBYTE)pCurrentIndex - pMyBuffer) ));
|
|
|
|
pThisCardEntry->dwPermanentCardID = pThisCard->dwID;
|
|
|
|
LayDownString( pThisCard->NameW,
|
|
pMyBuffer,
|
|
&pCurrentIndex,
|
|
&(pThisCardEntry->dwCardNameSize));
|
|
|
|
|
|
if ( TAPI_VERSION1_0 != dwAPIVersion )
|
|
{
|
|
LayDownString( pThisCard->LocalRuleW,
|
|
pMyBuffer,
|
|
&pCurrentIndex,
|
|
&(pThisCardEntry->dwSameAreaRuleSize));
|
|
|
|
LayDownString( pThisCard->LDRuleW,
|
|
pMyBuffer,
|
|
&pCurrentIndex,
|
|
&(pThisCardEntry->dwLongDistanceRuleSize));
|
|
|
|
LayDownString( pThisCard->InternationalRuleW,
|
|
pMyBuffer,
|
|
&pCurrentIndex,
|
|
&(pThisCardEntry->dwInternationalRuleSize));
|
|
|
|
pThisCardEntry->dwCardNumberDigits = lstrlenW(pThisCard->PinW);
|
|
|
|
|
|
pThisCardEntry->dwOptions = pThisCard->dwFlags;
|
|
|
|
}
|
|
|
|
|
|
pThisCard++;
|
|
(LPBYTE)pThisCardEntry += uCardEntrySize;
|
|
}
|
|
|
|
|
|
nCardsSize = pCurrentIndex - (pMyBuffer+nCardsStart);
|
|
|
|
|
|
//BUGBUG What's the "+16" for?
|
|
nFinalSize = pCurrentIndex - pMyBuffer + 16;
|
|
|
|
|
|
((LPLINETRANSLATECAPS)pMyBuffer)->dwTotalSize = lpTranslateCaps->dwTotalSize;
|
|
|
|
((LPLINETRANSLATECAPS)pMyBuffer)->dwNeededSize = nFinalSize;
|
|
|
|
((LPLINETRANSLATECAPS)pMyBuffer)->dwNumLocations = pnStuff[2];
|
|
|
|
((LPLINETRANSLATECAPS)pMyBuffer)->dwLocationListSize = nFinalSize - sizeof(LINETRANSLATECAPS);
|
|
((LPLINETRANSLATECAPS)pMyBuffer)->dwLocationListOffset =
|
|
sizeof(LINETRANSLATECAPS);
|
|
|
|
((LPLINETRANSLATECAPS)pMyBuffer)->dwCurrentLocationID = pnStuff[0];
|
|
|
|
((LPLINETRANSLATECAPS)pMyBuffer)->dwNumCards = pnCardStuff[2];
|
|
((LPLINETRANSLATECAPS)pMyBuffer)->dwCardListSize = nCardsSize;
|
|
((LPLINETRANSLATECAPS)pMyBuffer)->dwCardListOffset = nCardsStart;
|
|
|
|
|
|
if ( lpTranslateCaps->dwTotalSize < nFinalSize )
|
|
{
|
|
InternalDebugOut((1, "Not enough space to copy the entire buffer"));
|
|
InternalDebugOut((1, "Needed %ld, but had %ld available",
|
|
nFinalSize, lpTranslateCaps->dwTotalSize));
|
|
|
|
((LPLINETRANSLATECAPS)pMyBuffer)->dwUsedSize = sizeof(LINETRANSLATECAPS);
|
|
CopyMemory(
|
|
lpTranslateCaps,
|
|
pMyBuffer,
|
|
sizeof(LINETRANSLATECAPS)
|
|
);
|
|
}
|
|
else
|
|
{
|
|
((LPLINETRANSLATECAPS)pMyBuffer)->dwUsedSize = nFinalSize;
|
|
CopyMemory(
|
|
lpTranslateCaps,
|
|
pMyBuffer,
|
|
nFinalSize
|
|
);
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
if (pMyBuffer)
|
|
ClientFree( pMyBuffer );
|
|
|
|
if (MyLocationList)
|
|
ClientFree( MyLocationList );
|
|
if (MyCardList)
|
|
ClientFree( MyCardList );
|
|
|
|
if (pnCardStuff)
|
|
ClientFree( pnCardStuff );
|
|
if (pnStuff)
|
|
ClientFree( pnStuff );
|
|
|
|
|
|
|
|
InternalDebugOut((1, " Leaving lineGetTranslateCaps result=0x%08lx", lResult));
|
|
return (lResult);
|
|
}
|
|
|
|
|
|
|
|
//***************************************************************************
|
|
//***************************************************************************
|
|
//***************************************************************************
|
|
LONG
|
|
WINAPI
|
|
lineGetTranslateCaps(
|
|
HLINEAPP hLineApp,
|
|
DWORD dwAPIVersion,
|
|
LPLINETRANSLATECAPS lpTranslateCaps
|
|
)
|
|
{
|
|
return lineGetTranslateCapsA(
|
|
hLineApp,
|
|
dwAPIVersion,
|
|
lpTranslateCaps
|
|
);
|
|
}
|
|
|
|
|
|
//***************************************************************************
|
|
//***************************************************************************
|
|
//***************************************************************************
|
|
// Copy a char into lpDest, reserving *lpEnd for '\0'. Returns NULL on overrun.
|
|
// Returns next character else.
|
|
// NOTE: depends on there being at least one char in lpDest at first call.
|
|
//
|
|
// Returns
|
|
// ptr to next char on success
|
|
// NULL on failure
|
|
LPWSTR NEAR CopyChar(WCHAR c, LPWSTR lpDest, LPWSTR lpEnd)
|
|
{
|
|
if (lpDest == NULL || lpDest >= lpEnd)
|
|
{
|
|
InternalDebugOut((1, " Spillage in CopyChar!"));
|
|
return NULL;
|
|
}
|
|
|
|
|
|
// *lpDest = c;
|
|
// if ( isDBCSLeadByte( (BYTE)*lpDest ) )
|
|
// *lpDest = c or two bytes
|
|
//*** *** ***
|
|
// lpDest = AnsiNext( lpDest );
|
|
|
|
*lpDest++ = c;
|
|
|
|
return lpDest;
|
|
}
|
|
|
|
|
|
|
|
//***************************************************************************
|
|
//***************************************************************************
|
|
//***************************************************************************
|
|
// Copies only digits up to end of string. (simply end of string
|
|
// if pNext is NULL.) if lpSrc is NULL returns lpDest.
|
|
|
|
LPWSTR PASCAL CopyDigits( LPWSTR lpSrc,
|
|
LPWSTR lpDest,
|
|
LPWSTR lpEnd,
|
|
BOOL fAndModifiers
|
|
)
|
|
{
|
|
if (lpSrc != NULL)
|
|
{
|
|
while (*lpSrc != '\0')
|
|
{
|
|
|
|
if ( IsWDigit(*lpSrc) || ( fAndModifiers && wcschr(csBADCO, *lpSrc)))
|
|
{
|
|
lpDest = CopyChar(*lpSrc,lpDest,lpEnd);
|
|
}
|
|
|
|
//don't need now that it's Unicode... lpSrc = CharNext( lpSrc );
|
|
lpSrc++;
|
|
}
|
|
}
|
|
return lpDest;
|
|
}
|
|
|
|
|
|
|
|
//***************************************************************************
|
|
//***************************************************************************
|
|
//***************************************************************************
|
|
// Matches JUST the digits in lpSegment and lpPrefix, returning TRUE if
|
|
// lpSegment starts with lpPrefix. if matches, lpTail will be the next
|
|
// character after the match. lpPrefix is 0 length (starts with '\0'
|
|
// or otherDelimiter) returns FALSE unless lpSegment is NULL. if lpPrefix
|
|
// is not 0 length, returns FALSE if lpSegment is NULL.
|
|
// if commas are not allowed in prefix (dialing rules allow commas, toll
|
|
// prefixes do not), pass ',' for otherDelimiter, else 0.
|
|
// NOTE: lpPrefix is a dialing rule or toll list so it must be terminated
|
|
// by " or ,
|
|
// NOTE: if lpSegment or plpTail is NULL, lpTail is not returned
|
|
//
|
|
BOOL PASCAL PrefixMatch( LPWSTR lpSegment,
|
|
LPWSTR lpPrefix,
|
|
LPWSTR *plpTail,
|
|
WCHAR otherDelimiter,
|
|
BOOL fNeedExactMatch
|
|
)
|
|
{
|
|
BOOL returnResult = TRUE;
|
|
LPWSTR lpPre = lpPrefix;
|
|
|
|
if (lpSegment != NULL)
|
|
{
|
|
while ( *lpSegment != '\0' &&
|
|
*lpPre != '\0' &&
|
|
*lpPre != otherDelimiter)
|
|
{
|
|
if (IsWDigit(*lpSegment))
|
|
{
|
|
if (IsWDigit(*lpPre))
|
|
{
|
|
if (*lpSegment != *lpPre)
|
|
{
|
|
returnResult = FALSE;
|
|
goto cleanup;
|
|
}
|
|
lpSegment++;
|
|
lpPre++;
|
|
}
|
|
else lpPre++;
|
|
}
|
|
else
|
|
{
|
|
lpSegment++;
|
|
if (!IsDigit(*lpPre))
|
|
lpPre++;
|
|
}
|
|
}
|
|
|
|
if (plpTail)
|
|
*plpTail = lpSegment;
|
|
|
|
returnResult = (lpPre != lpPrefix);
|
|
}
|
|
returnResult = returnResult && (*lpPre == '\0' || *lpPre == otherDelimiter);
|
|
|
|
|
|
if ( fNeedExactMatch && lpSegment)
|
|
{
|
|
returnResult &= !(IsDigit(*lpSegment));
|
|
}
|
|
|
|
|
|
cleanup:
|
|
return returnResult;
|
|
}
|
|
|
|
|
|
|
|
//***************************************************************************
|
|
//***************************************************************************
|
|
//***************************************************************************
|
|
// Returns CITY_MANDATORY if rule contains an F (ie city code mandatory),
|
|
// Returns CITY_OPTIONAL if rule contains an I (ie city code optional)
|
|
// Returns CITY_NONE if rule contains neither
|
|
// NOTE: Rules terminate in " character, not '\0'
|
|
//
|
|
int IsCityRule(LPWSTR lpRule)
|
|
{
|
|
WCHAR c;
|
|
|
|
while ((c = *lpRule++) != '\0')
|
|
{
|
|
if (c == 'F') return CITY_MANDATORY;
|
|
if (c == 'I') return CITY_OPTIONAL;
|
|
}
|
|
return CITY_NONE;
|
|
}
|
|
|
|
|
|
|
|
//***************************************************************************
|
|
//***************************************************************************
|
|
//***************************************************************************
|
|
|
|
// Implements 7.5.7 in TAPIADDR spec. Returns the relevant bits in a DWORD,
|
|
// suitable for ORing with dwTranslateResults.
|
|
// NOTE: due to misspecification of input numbers, any of the subcomponents
|
|
// may be NULL.
|
|
DWORD PASCAL CategorizeNumber(
|
|
DWORD dwPCCode,
|
|
LPWSTR lpCity,
|
|
LPWSTR lpSubscriber,
|
|
PLOCATION pCurrentLocation,
|
|
LPLINECOUNTRYLIST lpCountryList
|
|
)
|
|
{
|
|
DWORD dwTranslateResults = 0;
|
|
LPWSTR lpLDRule = NULL;
|
|
LPWSTR lpNewDestCityCode = NULL; // Win95C 10057
|
|
LPWSTR lpNewCurCityCode = NULL; // Win95C 10057
|
|
|
|
LPLINECOUNTRYENTRY lplce;
|
|
|
|
|
|
lplce = (LPLINECOUNTRYENTRY)
|
|
((LPBYTE)lpCountryList + lpCountryList->dwCountryListOffset);
|
|
|
|
|
|
// If destination country and current country don't match, this is an
|
|
// international call. If they do and current country uses city codes
|
|
// and city codes don't match, then this is long distance. Otherwise
|
|
// it is local and for North America, we check toll list and set proper
|
|
// bits.
|
|
if (lplce->dwCountryCode != dwPCCode)
|
|
{
|
|
dwTranslateResults = LINETRANSLATERESULT_INTERNATIONAL;
|
|
}
|
|
else
|
|
{
|
|
|
|
lpLDRule = (LPWSTR)( (LPBYTE)lpCountryList +
|
|
lplce->dwLongDistanceRuleOffset);
|
|
|
|
|
|
//
|
|
// WIN95C 10057 - If the user's typed in the LD prefix as if it were
|
|
// part of the city code, give 'em a break and let it slide.
|
|
// (different comment on the same thing)
|
|
// WIN95C 10057 - If the current city code has the long distance
|
|
// prefix attached to it (because the user is clueless), ensure we
|
|
// do a good compare
|
|
//
|
|
// At this point, we know this is not an international call, so we can
|
|
// use the lpLDRule to compare
|
|
//
|
|
if (
|
|
(lpCity != NULL)
|
|
&&
|
|
lpLDRule
|
|
&&
|
|
(*lpLDRule == *lpCity)
|
|
)
|
|
{
|
|
lpNewDestCityCode = lpCity + 1;
|
|
}
|
|
else
|
|
{
|
|
lpNewDestCityCode = lpCity;
|
|
}
|
|
|
|
|
|
//
|
|
// WIN95C 10057 - If the current city code has the long distance
|
|
// prefix attached to it (because the user is clueless), ensure we
|
|
// do a good compare
|
|
//
|
|
// At this point, we know this is not an international call, so we can
|
|
// use the lpLDRule to compare
|
|
//
|
|
// This is the same logic as above but the above code handles the
|
|
// dest address, and this is for the current location
|
|
//
|
|
if (
|
|
( *lpLDRule == *pCurrentLocation->AreaCodeW )
|
|
)
|
|
{
|
|
lpNewCurCityCode = (LPWSTR)(pCurrentLocation->AreaCodeW)+1;
|
|
}
|
|
else
|
|
{
|
|
lpNewCurCityCode = (LPWSTR)(pCurrentLocation->AreaCodeW);
|
|
}
|
|
|
|
|
|
|
|
|
|
if (
|
|
(
|
|
(IsCityRule(lpLDRule) == CITY_OPTIONAL)
|
|
||
|
|
(
|
|
(IsCityRule(lpLDRule) == CITY_MANDATORY)
|
|
&&
|
|
(lpNewDestCityCode != NULL)
|
|
)
|
|
)
|
|
&&
|
|
!PrefixMatch(lpNewDestCityCode, lpNewCurCityCode, NULL, 0, TRUE)
|
|
)
|
|
{
|
|
dwTranslateResults = LINETRANSLATERESULT_LONGDISTANCE;
|
|
}
|
|
else
|
|
{
|
|
dwTranslateResults = LINETRANSLATERESULT_LOCAL;
|
|
|
|
#define CC_NORTHAMERICA (1)
|
|
|
|
if ( pCurrentLocation->dwCountry == CC_NORTHAMERICA && lpSubscriber)
|
|
{
|
|
dwTranslateResults |=
|
|
InPrefixList(lpSubscriber, pCurrentLocation ) != NULL ?
|
|
LINETRANSLATERESULT_INTOLLLIST :
|
|
LINETRANSLATERESULT_NOTINTOLLLIST;
|
|
}
|
|
}
|
|
}
|
|
|
|
return dwTranslateResults;
|
|
|
|
}
|
|
|
|
|
|
|
|
//***************************************************************************
|
|
//***************************************************************************
|
|
//***************************************************************************
|
|
// Computes the Dialable and Displayable strings, as per 7.5.8.
|
|
// NOTE: dwCard has been vetted by TranslateAddress() so that it should be
|
|
// fine (unless someone wrote on ini file behind our backs)
|
|
// NOTE: due to misspecification of input numbers, any of the subcomponents
|
|
// may be NULL.
|
|
//
|
|
LONG PASCAL BuildDialAndDisplay( PCARD pCard,
|
|
DWORD dwTranslateResults,
|
|
DWORD dwTranslateOptions,
|
|
LPWSTR lpDestCountry,
|
|
LPWSTR lpDestCity,
|
|
LPWSTR lpDestSubscriber,
|
|
LPWSTR lpDialable,
|
|
LPWSTR lpDisplayable,
|
|
UINT strSize,
|
|
PLOCATION pThisLocation,
|
|
LPLINECOUNTRYLIST lpCountryList
|
|
)
|
|
{
|
|
BOOL fNeedBlank = FALSE;
|
|
LPWSTR lpRuleToUse = NULL;
|
|
LPWSTR lpDialEnd = lpDialable+strSize-1;
|
|
LPWSTR lpDisplayEnd = lpDisplayable+strSize-1;
|
|
LPWSTR lpNextSegment = NULL;
|
|
BOOL haveNonBlank = FALSE;
|
|
// BOOL disableF = FALSE; bjm 2/10/96 - not needed anymore
|
|
LONG errorReturn = 0;
|
|
DWORD dwDestPCCode;
|
|
LPWSTR pAccessPrefix = gszNullStringW;
|
|
|
|
LPLINECOUNTRYENTRY lplce;
|
|
|
|
#if DBG
|
|
LPWSTR lpDialableSAVE = lpDialable;
|
|
LPWSTR lpDisplayableSAVE = lpDisplayable;
|
|
#endif
|
|
|
|
InternalDebugOut((10, "Entering BuildDialAndDisplay"));
|
|
InternalDebugOut((11, " lpDestCountry=0x%08lx", lpDestCountry));
|
|
InternalDebugOut((11, " lpDestCity=0x%08lx", lpDestCity ? lpDestCity : L"NULL"));
|
|
InternalDebugOut((11, " lpDestSubscriber=0x%08lx", lpDestSubscriber));
|
|
InternalDebugOut((11, " lpDialable=0x%08lx", lpDialable));
|
|
InternalDebugOut((11, " lpDisplayable=0x%08lx", lpDisplayable));
|
|
InternalDebugOut((11, " strSize=%ld", strSize));
|
|
|
|
|
|
dwDestPCCode = _wtoi(lpDestCountry);
|
|
|
|
|
|
lplce = (LPLINECOUNTRYENTRY)
|
|
((LPBYTE)lpCountryList + lpCountryList->dwCountryListOffset);
|
|
|
|
|
|
if (LINETRANSLATERESULT_INTERNATIONAL & dwTranslateResults)
|
|
{
|
|
//
|
|
// If we're using a card, use that rule, otherwise use the country
|
|
// dialing rule.
|
|
//
|
|
lpRuleToUse = (pCard && pCard->dwID) ?
|
|
pCard->InternationalRuleW :
|
|
(LPWSTR)( (LPBYTE)lpCountryList +
|
|
lplce->dwInternationalRuleOffset
|
|
);
|
|
|
|
pAccessPrefix = &(pThisLocation->LongDistanceAccessW[0]);
|
|
|
|
InternalDebugOut((10, "Going with the international rule [%ls]", lpRuleToUse));
|
|
}
|
|
else
|
|
{
|
|
|
|
if (
|
|
( (LINETRANSLATERESULT_LONGDISTANCE & dwTranslateResults)
|
|
||
|
|
(LINETRANSLATEOPTION_FORCELD & dwTranslateOptions)
|
|
)
|
|
&&
|
|
(!(LINETRANSLATEOPTION_FORCELOCAL & dwTranslateOptions) )
|
|
)
|
|
{
|
|
//
|
|
// If we're using a card, use that rule, otherwise use the country
|
|
// dialing rule.
|
|
//
|
|
lpRuleToUse = (pCard && pCard->dwID) ?
|
|
pCard->LDRuleW :
|
|
(LPWSTR)( (LPBYTE)lpCountryList +
|
|
lplce->dwLongDistanceRuleOffset
|
|
);
|
|
pAccessPrefix = &(pThisLocation->LongDistanceAccessW[0]);
|
|
|
|
InternalDebugOut((10, "Going with the LD rule"));
|
|
}
|
|
else
|
|
{
|
|
|
|
pAccessPrefix = &(pThisLocation->OutsideAccessW[0]);
|
|
|
|
if ( (LINETRANSLATERESULT_INTOLLLIST & dwTranslateResults) &&
|
|
(!(LINETRANSLATEOPTION_FORCELOCAL & dwTranslateOptions) ) )
|
|
{
|
|
//BUGBUG: what's this for? - bjm 2/10/96 not needed anymore
|
|
//*** *** *** disableF = locArgs[LOC_INI_INSERTAC].dwArg == 0;
|
|
|
|
// Well, it's the same area code, but it's a toll call.
|
|
|
|
//
|
|
// If we're using a card, use that rule, otherwise use the
|
|
// country dialing rule.
|
|
//
|
|
lpRuleToUse = (pCard && pCard->dwID) ?
|
|
pCard->LocalRuleW :
|
|
(LPWSTR)( (LPBYTE)lpCountryList +
|
|
lplce->dwLongDistanceRuleOffset
|
|
);
|
|
InternalDebugOut((10, "Going with the .LD rule"));
|
|
}
|
|
else
|
|
{
|
|
// The last choice of the last choice - local call.
|
|
|
|
|
|
//
|
|
// If we're using a card, use that rule, otherwise use the
|
|
// country dialing rule.
|
|
//
|
|
lpRuleToUse = (pCard && pCard->dwID) ?
|
|
pCard->LocalRuleW :
|
|
(LPWSTR)( (LPBYTE)lpCountryList +
|
|
lplce->dwSameAreaRuleOffset
|
|
);
|
|
InternalDebugOut((1, "Going with the local rule"));
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
//
|
|
// Do we have a "Disable call waiting" prefix that the caller wants
|
|
// to use?
|
|
//
|
|
if (
|
|
(dwTranslateOptions & LINETRANSLATEOPTION_CANCELCALLWAITING)
|
|
&&
|
|
(pThisLocation->dwFlags & LOCATION_HASCALLWAITING)
|
|
&&
|
|
( lstrlenW(pThisLocation->DisableCallWaitingW) )
|
|
)
|
|
{
|
|
lpDisplayable = CopyStringToChar(
|
|
pThisLocation->DisableCallWaitingW,
|
|
'\0',
|
|
lpDisplayable,
|
|
lpDisplayEnd
|
|
);
|
|
|
|
lpDialable = CopyStringToChar(
|
|
pThisLocation->DisableCallWaitingW,
|
|
'\0',
|
|
lpDialable,
|
|
lpDialEnd
|
|
);
|
|
|
|
lpDialable = CopyChar(' ',lpDialable,lpDialEnd);
|
|
lpDisplayable = CopyChar(' ',lpDisplayable,lpDisplayEnd);
|
|
}
|
|
|
|
//
|
|
// If we have to do something special for outside access, do it.
|
|
//
|
|
if ( 0 != lstrlenW( pAccessPrefix ) )
|
|
{
|
|
lpDisplayable = CopyStringToChar(pAccessPrefix,'\0',lpDisplayable,lpDisplayEnd);
|
|
lpDialable = CopyStringToChar(pAccessPrefix,'\0',lpDialable,lpDialEnd);
|
|
haveNonBlank = fNeedBlank = TRUE;
|
|
}
|
|
|
|
|
|
//
|
|
// TAPISDK 1361 - if we're calling from Mexico(52) to US(1),
|
|
// hack the string.
|
|
//BUGBUG: Make this special case (Mexico(52) to US(1)) extensible)
|
|
//
|
|
if (
|
|
(pThisLocation->dwCountry == 52)
|
|
&&
|
|
(LINETRANSLATERESULT_INTERNATIONAL & dwTranslateResults)
|
|
&&
|
|
(dwDestPCCode == 1)
|
|
)
|
|
{
|
|
lpRuleToUse = L"95FG";
|
|
}
|
|
|
|
|
|
InternalDebugOut((1, "RuleToUse:[%ls]", lpRuleToUse));
|
|
|
|
while ( lpDisplayable && lpDialable && (*lpRuleToUse != '\0') )
|
|
{
|
|
|
|
InternalDebugOut((10, " Displayable so far: %ls", lpDisplayableSAVE));
|
|
InternalDebugOut((10, " Dialable so far : %ls", lpDialableSAVE));
|
|
|
|
switch (*lpRuleToUse)
|
|
{
|
|
case 'E':
|
|
if (lpDestCountry && (*lpDestCountry != '\0'))
|
|
{
|
|
if (fNeedBlank)
|
|
{
|
|
lpDialable = CopyChar(' ',lpDialable,lpDialEnd);
|
|
lpDisplayable = CopyChar(' ',lpDisplayable,lpDisplayEnd);
|
|
}
|
|
|
|
lpDialable = CopyDigits(lpDestCountry,lpDialable,lpDialEnd, FALSE);
|
|
|
|
lpDisplayable = CopyDigits(lpDestCountry,lpDisplayable,lpDisplayEnd, FALSE);
|
|
|
|
haveNonBlank = fNeedBlank = TRUE;
|
|
}
|
|
break;
|
|
|
|
|
|
|
|
case 'F':
|
|
case 'I':
|
|
if (lpDestCity != NULL && (*lpDestCity != '\0') )
|
|
// bjm 2/10/96 - not needed anymore && !disableF)
|
|
{
|
|
LPWSTR lpNewDestCity; //Win95C 10057
|
|
|
|
|
|
if (fNeedBlank)
|
|
{
|
|
lpDialable = CopyChar (' ',lpDialable,lpDialEnd);
|
|
lpDisplayable = CopyChar(' ',lpDisplayable,lpDisplayEnd);
|
|
}
|
|
|
|
|
|
//
|
|
// Win95C 10057 - if the first digit of the city code is the
|
|
// same as the LD prefix, then strip it off the city code.
|
|
//
|
|
// We have to check the long distance rule of the destination
|
|
// country. Eg: If a user from a country which adds its ld
|
|
// prefix in the city code, and that user goes on the road, all
|
|
// the phone #s in his address book have the ld prefix on the
|
|
// city code.
|
|
//
|
|
{
|
|
LPWSTR lpDestCountryLDRule = NULL;
|
|
LPLINECOUNTRYLIST lpDestCountryList;
|
|
LPLINECOUNTRYENTRY lplceDest;
|
|
|
|
if ( 0 != ReadCountries( &lpDestCountryList,
|
|
dwDestPCCode,
|
|
0
|
|
)
|
|
)
|
|
{
|
|
InternalDebugOut((1, "Error reading country [%ld]", dwDestPCCode));
|
|
return LINEERR_INVALCOUNTRYCODE;
|
|
}
|
|
|
|
lplceDest = (LPLINECOUNTRYENTRY) ((LPBYTE)lpDestCountryList
|
|
+ lpDestCountryList->dwCountryListOffset);
|
|
|
|
lpDestCountryLDRule = (LPWSTR)((LPBYTE)lpDestCountryList +
|
|
lplceDest->dwLongDistanceRuleOffset);
|
|
|
|
//
|
|
// Does the first character of the city code match the
|
|
// longdistance dialing digit?
|
|
//
|
|
if ( *lpDestCity == *lpDestCountryLDRule)
|
|
{
|
|
//
|
|
// Yes. Ok, so don't use that prefix digit.
|
|
//
|
|
lpNewDestCity = lpDestCity + 1;
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Nope. Use the city code as-is.
|
|
//
|
|
lpNewDestCity = lpDestCity;
|
|
}
|
|
|
|
ClientFree( lpDestCountryList );
|
|
}
|
|
|
|
|
|
lpDialable = CopyDigits(lpNewDestCity,lpDialable,lpDialEnd, FALSE);
|
|
|
|
lpDisplayable = CopyDigits(lpNewDestCity,lpDisplayable,lpDisplayEnd, FALSE);
|
|
|
|
haveNonBlank = fNeedBlank = TRUE;
|
|
}
|
|
//
|
|
// These lines are commented out because whether a country REALLY uses
|
|
// city codes is unknown (regardless of what the "rule" says...)
|
|
//
|
|
// else
|
|
// {
|
|
// //
|
|
// // If we're required to have an area code, but we didn't get one,
|
|
// // we signal an error.
|
|
// //
|
|
// if ( 'F' == *lpRuleToUse )
|
|
// {
|
|
// errorReturn = LINEERR_INVALADDRESS;
|
|
// goto cleanup;
|
|
// }
|
|
// }
|
|
break;
|
|
|
|
|
|
|
|
case 'G':
|
|
if (lpDestSubscriber != NULL && (*lpDestSubscriber != '\0'))
|
|
{
|
|
if (fNeedBlank)
|
|
{
|
|
lpDialable = CopyChar(' ',lpDialable,lpDialEnd);
|
|
lpDisplayable = CopyChar(' ',lpDisplayable,lpDisplayEnd);
|
|
}
|
|
|
|
lpDialable = CopyDigits(lpDestSubscriber,lpDialable,lpDialEnd, TRUE);
|
|
|
|
lpDisplayable = CopyStringToChar(lpDestSubscriber,'\0',lpDisplayable,lpDisplayEnd);
|
|
haveNonBlank = fNeedBlank = TRUE;
|
|
}
|
|
break;
|
|
|
|
|
|
|
|
case 'H':
|
|
if (pCard != NULL)
|
|
{
|
|
if (fNeedBlank)
|
|
{
|
|
lpDialable = CopyChar(' ',lpDialable,lpDialEnd);
|
|
lpDisplayable = CopyChar(' ',lpDisplayable,lpDisplayEnd);
|
|
}
|
|
|
|
// This is now being done on read and write.
|
|
//bjm11/15 lpDialable = CopyScrambled( pCard->Pin,
|
|
//bjm11/15 lpDialable,
|
|
//bjm11/15 pCard->dwID
|
|
//bjm11/15 );
|
|
lpDialable = CopyDigits(pCard->PinW, lpDialable, lpDialEnd, FALSE);
|
|
|
|
lpDisplayable = CopyChar('[',lpDisplayable,lpDisplayEnd);
|
|
|
|
lpDisplayable = CopyStringToChar( pCard->NameW,
|
|
'\0',
|
|
lpDisplayable,
|
|
lpDisplayEnd
|
|
);
|
|
lpDisplayable = CopyChar(']',lpDisplayable,lpDisplayEnd);
|
|
|
|
haveNonBlank = fNeedBlank = TRUE;
|
|
}
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
if (fNeedBlank && haveNonBlank)
|
|
{
|
|
lpDialable = CopyChar(' ',lpDialable,lpDialEnd);
|
|
lpDisplayable = CopyChar(' ',lpDisplayable,lpDisplayEnd);
|
|
}
|
|
|
|
fNeedBlank = TRUE;
|
|
haveNonBlank = FALSE;
|
|
lpDialable = CopyChar(*lpRuleToUse,lpDialable,lpDialEnd);
|
|
|
|
if (!wcschr(csDISPSUPRESS,*lpRuleToUse))
|
|
lpDisplayable = CopyChar(*lpRuleToUse,lpDisplayable,lpDisplayEnd);
|
|
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
lpRuleToUse++;
|
|
|
|
}
|
|
|
|
InternalDebugOut((10, " Now done, displayable: %ls", lpDisplayableSAVE));
|
|
InternalDebugOut((10, " Now done, dialable : %ls", lpDialableSAVE));
|
|
|
|
// If we over flowed our string buffers, return LINEERR_INVALADDRESS.
|
|
// NOTE: this is a questionable return result, but what's better?
|
|
if (lpDisplayable == NULL || lpDialable == NULL)
|
|
{
|
|
errorReturn = LINEERR_INVALADDRESS;
|
|
}
|
|
else
|
|
{
|
|
*lpDisplayable = '\0';
|
|
*lpDialable = '\0';
|
|
}
|
|
|
|
|
|
cleanup:
|
|
|
|
return errorReturn;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//***************************************************************************
|
|
//***************************************************************************
|
|
//***************************************************************************
|
|
LONG PASCAL TranslateTheAddress( LPCWSTR lpszAddressIn,
|
|
LPWSTR *pDialableAddressPointer,
|
|
LPWSTR *pDisplayableAddressPointer,
|
|
DWORD dwTranslateOptions,
|
|
LPDWORD lpdwTranslateResults,
|
|
LPDWORD lpdwCountry,
|
|
PCARD pCard,
|
|
PLOCATION pLocation
|
|
)
|
|
{
|
|
WCHAR *pDialable;
|
|
WCHAR *pDisplayable;
|
|
WCHAR *pAddressIn;
|
|
WCHAR *pAddressInSAVE;
|
|
LONG lResult = 0;
|
|
|
|
|
|
*lpdwTranslateResults = 0;
|
|
|
|
|
|
pDialable = ClientAlloc( 500 * sizeof(WCHAR) );
|
|
if (!pDialable)
|
|
{
|
|
DBGOUT((1, "Memory allocation failed"));
|
|
return LINEERR_NOMEM;
|
|
}
|
|
|
|
pDisplayable = ClientAlloc( 500 * sizeof(WCHAR) );
|
|
if (!pDisplayable)
|
|
{
|
|
DBGOUT((1, "Memory allocation failed2"));
|
|
|
|
ClientFree(pDialable);
|
|
|
|
return LINEERR_NOMEM;
|
|
}
|
|
|
|
pAddressInSAVE = pAddressIn = ClientAlloc( (lstrlenW(lpszAddressIn)+1) * sizeof(WCHAR));
|
|
if ( !pAddressIn )
|
|
{
|
|
DBGOUT((1, "Memory allocation failed3"));
|
|
|
|
ClientFree(pDialable);
|
|
ClientFree(pDisplayable);
|
|
|
|
return LINEERR_NOMEM;
|
|
}
|
|
|
|
|
|
*pDialableAddressPointer = pDialable;
|
|
*pDisplayableAddressPointer = pDisplayable;
|
|
|
|
|
|
//
|
|
// Copy the string to our local buffer so we can mangle it
|
|
//
|
|
lstrcpyW( pAddressIn, lpszAddressIn );
|
|
|
|
|
|
//
|
|
// Mark off the end
|
|
//
|
|
// Isolate the piece of lpAddressIn that we will operate upon in
|
|
// szAddressIn. This piece stops at first !,^,CR or \0.
|
|
//
|
|
pAddressIn[wcscspn(pAddressIn,csSCANTO)] = '\0';
|
|
|
|
|
|
//
|
|
// Easy case: first put the T or P in the beginning of the
|
|
// dialable string
|
|
//
|
|
if ( pLocation->dwFlags & LOCATION_USETONEDIALING )
|
|
{
|
|
*pDialable = 'T';
|
|
}
|
|
else
|
|
{
|
|
*pDialable = 'P';
|
|
}
|
|
|
|
pDialable++;
|
|
|
|
|
|
//---------------------------------------------------------------------------
|
|
//
|
|
// Now, do we have a canonical number to deal with, or is it junk?
|
|
//
|
|
if ( lpszAddressIn && (*lpszAddressIn == '+') ) // Check the real _first_ char
|
|
{
|
|
//
|
|
// Ok, it's canonical
|
|
//
|
|
|
|
WCHAR *pDestCountry;
|
|
WCHAR *pDestCity;
|
|
WCHAR *pDestSubscriber;
|
|
LPLINECOUNTRYLIST lpCountryList = NULL;
|
|
|
|
|
|
//
|
|
// Skip the plus
|
|
//
|
|
pAddressIn++;
|
|
|
|
|
|
lResult = BreakupCanonicalW( pAddressIn,
|
|
&pDestCountry,
|
|
&pDestCity,
|
|
&pDestSubscriber
|
|
);
|
|
|
|
if ( lResult )
|
|
{
|
|
return lResult;
|
|
}
|
|
|
|
|
|
DBGOUT((70, "Country:%ls City:%ls Subscriber:%ls",
|
|
pDestCountry ? pDestCountry : L"NULL",
|
|
pDestCity ? pDestCity : L"NULL",
|
|
pDestSubscriber ? pDestSubscriber : L"NULL"
|
|
));
|
|
|
|
|
|
*lpdwTranslateResults |= LINETRANSLATERESULT_CANONICAL;
|
|
|
|
|
|
|
|
//
|
|
// Put the dest country into the dest place
|
|
//
|
|
*lpdwCountry = _wtoi(pDestCountry);
|
|
|
|
|
|
//
|
|
// Ok, now build the strings
|
|
//
|
|
|
|
|
|
if ( 0 != ReadCountries( &lpCountryList,
|
|
pLocation->dwCountry,
|
|
(*lpdwCountry != pLocation->dwCountry) ?
|
|
*lpdwCountry :
|
|
0
|
|
)
|
|
)
|
|
{
|
|
InternalDebugOut((1, "Error reading country [%ld]", pLocation->dwCountry));
|
|
return LINEERR_INVALCOUNTRYCODE;
|
|
}
|
|
|
|
|
|
*lpdwTranslateResults |= CategorizeNumber(
|
|
*lpdwCountry,
|
|
pDestCity,
|
|
pDestSubscriber,
|
|
pLocation,
|
|
lpCountryList
|
|
);
|
|
|
|
|
|
lResult = BuildDialAndDisplay( pCard,
|
|
*lpdwTranslateResults,
|
|
dwTranslateOptions,
|
|
pDestCountry,
|
|
pDestCity,
|
|
pDestSubscriber,
|
|
pDialable,
|
|
pDisplayable,
|
|
ClientSize(pDisplayable) -1, // We inc'ed pDialable for the 'T' or 'P'
|
|
pLocation,
|
|
lpCountryList
|
|
);
|
|
|
|
|
|
ClientFree( lpCountryList );
|
|
|
|
}
|
|
//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
else
|
|
{
|
|
//
|
|
// Nope, it's not canonical
|
|
//
|
|
|
|
|
|
//
|
|
// Leading spaces are strange. Skip them.
|
|
//
|
|
while ( *pAddressIn == ' ' )
|
|
{
|
|
pAddressIn++;
|
|
}
|
|
|
|
|
|
//
|
|
// Make sure there's not already a T or P at the beginning.
|
|
//
|
|
|
|
//
|
|
// If the first non-space char (we've already skipped past the spaces
|
|
// in the code before the "if"...) is T or P, just skip over it.
|
|
// (we don't
|
|
// care if it jibes with what the user selected for this location.)
|
|
//
|
|
if ( *pAddressIn == 'T' || *pAddressIn == 'P' )
|
|
{
|
|
pAddressIn++;
|
|
}
|
|
|
|
|
|
//* {
|
|
//* LPSTR pDest, pSource;
|
|
//*
|
|
//*// pDest = (LPSTR)pDialable+lstrlen(pDestCountry) + 1 +lstrlen(pDestCity) + 1;
|
|
//* pDest = (LPSTR)pDialable;
|
|
//* pSource = pSubscriber;
|
|
//*
|
|
//* while (*pSource)
|
|
//* {
|
|
//*// //BUGBUG *** *** ***This also filters garbage! (is that good or bad?)
|
|
//*// if ( IsDigit(*pSource) )
|
|
//*// {
|
|
//*// *pDest = *pSource;
|
|
//*// }
|
|
//*
|
|
//* if ( *pSource != '-' && *pSource != ' ')
|
|
//* {
|
|
//* *pDest = *pSource;
|
|
//* pDest++;
|
|
//* }
|
|
//*
|
|
//* pSource++;
|
|
//* }
|
|
//* }
|
|
//*
|
|
//* pDisplayable+= lstrlen(lpszAddressIn+1);
|
|
//* pDialable+=lstrlen(pCountry)+lstrlen(pCity)+lstrlen(pSubscriber);
|
|
|
|
|
|
//
|
|
// Let's do our own strcpy, cause we can probably save a couple
|
|
// of cycles (only one pass through original string)
|
|
//
|
|
{
|
|
register WCHAR ch;
|
|
|
|
while ( ch = *pAddressIn )
|
|
{
|
|
//*** *** ***BUGBUG performance: The compiler is turning this into two reads and two
|
|
// writes. Change this code so the compiler does it right.
|
|
// *pDialable = *pDisplayable = *pAddressIn;
|
|
*pDialable = *pDisplayable = ch;
|
|
|
|
pDialable++;
|
|
pDisplayable++;
|
|
pAddressIn++;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Null-terminate the strings
|
|
//
|
|
*pDialable = '\0';
|
|
*pDisplayable = '\0';
|
|
|
|
}
|
|
|
|
|
|
//cleanup:
|
|
|
|
|
|
ClientFree(pAddressInSAVE);
|
|
|
|
|
|
return lResult;
|
|
}
|
|
|
|
|
|
|
|
//***************************************************************************
|
|
//***************************************************************************
|
|
//***************************************************************************
|
|
void UpdateNumberField( HWND hWnd, LPCWSTR lpszAddressIn )
|
|
{
|
|
LPWSTR pDialableAddress;
|
|
LPWSTR pDisplayableAddress;
|
|
DWORD dwCountry;
|
|
DWORD dwTranslateResults;
|
|
PCARD pCard;
|
|
|
|
#ifdef PARTIAL_UNICODE
|
|
LPWSTR pTempString;
|
|
#endif
|
|
|
|
if ( NULL == lpszAddressIn )
|
|
{
|
|
return;
|
|
}
|
|
|
|
if ( gpCurrentLocation->dwFlags & LOCATION_USECALLINGCARD )
|
|
{
|
|
DWORD n;
|
|
|
|
n = GetCardIndexFromID( gpCurrentLocation->dwCallingCard,
|
|
gpCardList,
|
|
gpnStuff[2]
|
|
);
|
|
|
|
if ( (LONG)(-1) == n )
|
|
{
|
|
n = 0;
|
|
}
|
|
|
|
pCard = &(gpCardList[n]);
|
|
}
|
|
else
|
|
{
|
|
pCard = NULL;
|
|
}
|
|
|
|
//
|
|
// If the "Dial as long distance" button is checked, add one more
|
|
// option
|
|
//
|
|
|
|
TranslateTheAddress( lpszAddressIn,
|
|
&pDialableAddress,
|
|
&pDisplayableAddress,
|
|
LINETRANSLATEOPTION_CANCELCALLWAITING
|
|
| (IsDlgButtonChecked(hWnd, IDCK_DL_IN_LOCAL) ?
|
|
LINETRANSLATEOPTION_FORCELD :
|
|
0),
|
|
&dwTranslateResults,
|
|
&dwCountry,
|
|
pCard,
|
|
gpCurrentLocation
|
|
);
|
|
|
|
#ifdef PARTIAL_UNICODE
|
|
pTempString = ClientAlloc((lstrlenW(pDisplayableAddress)+2)* sizeof(WCHAR));
|
|
|
|
|
|
WideCharToMultiByte(
|
|
GetACP(),
|
|
0,
|
|
pDisplayableAddress,
|
|
-1,
|
|
pTempString,
|
|
lstrlenW(pDisplayableAddress)+1,
|
|
NULL,
|
|
NULL
|
|
);
|
|
|
|
SetDlgItemTextW( hWnd, IDCS_DL_DIAL_NUMBER, pTempString);
|
|
|
|
ClientFree( pTempString );
|
|
#else
|
|
SetDlgItemTextW( hWnd, IDCS_DL_DIAL_NUMBER, pDisplayableAddress );
|
|
#endif
|
|
|
|
//Huh? Why was this here? CheckDlgButton( hWnd, IDCK_DL_IN_LOCAL, FALSE );
|
|
//
|
|
// //
|
|
// // If this country is "1" and this _should_ be a local call and
|
|
// // the prefix is in the list, then we'll check the "dial as ld" box
|
|
// //
|
|
// if (
|
|
// (gpCurrentLocation->dwCountry == 1)
|
|
// &&
|
|
// (dwTranslateResults & LINETRANSLATERESULT_LOCAL)
|
|
// )
|
|
// {
|
|
// LPSTR pCountry;
|
|
// LPSTR pCity;
|
|
// LPSTR pSubscriber;
|
|
// LPSTR pAddressIn;
|
|
//
|
|
// pAddressIn = ClientAlloc( lstrlen(lpszAddressIn) + 1);
|
|
// lstrcpy( pAddressIn, lpszAddressIn );
|
|
//
|
|
// BreakupCanonical( pAddressIn,
|
|
// &pCountry,
|
|
// &pCity,
|
|
// &pSubscriber
|
|
// );
|
|
//
|
|
// if ( InPrefixList(pSubscriber, gpCurrentLocation) )
|
|
// {
|
|
// CheckDlgButton( hWnd, IDCK_DL_IN_LOCAL, TRUE );
|
|
// }
|
|
//
|
|
// ClientFree( pAddressIn );
|
|
// }
|
|
|
|
if ( pDisplayableAddress )
|
|
ClientFree( pDisplayableAddress );
|
|
if ( pDialableAddress )
|
|
ClientFree( pDialableAddress );
|
|
|
|
}
|
|
|
|
|
|
|
|
//***************************************************************************
|
|
//***************************************************************************
|
|
//***************************************************************************
|
|
|
|
//Get the current location
|
|
//xlate the number based on that
|
|
LONG
|
|
WINAPI
|
|
lineTranslateAddressW(
|
|
HLINEAPP hLineApp,
|
|
DWORD dwDeviceID,
|
|
DWORD dwAPIVersion,
|
|
LPCWSTR lpszAddressIn,
|
|
DWORD dwCard,
|
|
DWORD dwTranslateOptions,
|
|
LPLINETRANSLATEOUTPUT lpTranslateOutput
|
|
)
|
|
{
|
|
UINT n;
|
|
LONG lResult;
|
|
LPWSTR lpszDialable = NULL;
|
|
LPWSTR lpszDisplayable = NULL;
|
|
DWORD dwDialableSize = 0;
|
|
DWORD dwDisplayableSize = 0;
|
|
DWORD dwTranslateResults = 0;
|
|
DWORD dwCountry = 0;
|
|
|
|
PUINT pnStuff = NULL;
|
|
PLOCATION MyLocationList = NULL;
|
|
PLOCATION pThisLocation;
|
|
|
|
PUINT pnCardStuff = NULL;
|
|
PCARD MyCardList = NULL;
|
|
PCARD pThisCard = NULL;
|
|
|
|
|
|
#if DBG
|
|
DBGOUT((2, "Entering lineTranslateAddress"));
|
|
DBGOUT((20, " lpszAddressIn: 0x%08lx", lpszAddressIn));
|
|
if (!IsBadStringPtrW(lpszAddressIn, 256))
|
|
DBGOUT((21, " *lpszAddressIn: [%ls]", lpszAddressIn));
|
|
DBGOUT((20, " lpTranslateOutput: 0x%08lx", lpTranslateOutput));
|
|
DBGOUT((21, " lpTranslateOutput->dwTotalSize: 0x%08lx", lpTranslateOutput->dwTotalSize));
|
|
#endif
|
|
|
|
|
|
lResult = IsThisAPIVersionInvalid( dwAPIVersion );
|
|
if ( lResult )
|
|
{
|
|
DBGOUT((1, "Bad dwAPIVersion - 0x%08lx", dwAPIVersion));
|
|
return lResult;
|
|
}
|
|
|
|
|
|
if ( IsBadStringPtrW(lpszAddressIn,256) )
|
|
{
|
|
DBGOUT((1, "Invalid pointer - lpszAddressInW"));
|
|
lResult = LINEERR_INVALPOINTER;
|
|
goto cleanup;
|
|
}
|
|
|
|
|
|
if ( dwTranslateOptions &
|
|
~(LINETRANSLATEOPTION_CARDOVERRIDE |
|
|
LINETRANSLATEOPTION_CANCELCALLWAITING |
|
|
LINETRANSLATEOPTION_FORCELOCAL |
|
|
LINETRANSLATEOPTION_FORCELD) )
|
|
{
|
|
DBGOUT((1, " Invalid dwTranslateOptions (unknown flag set)"));
|
|
lResult = LINEERR_INVALPARAM;
|
|
goto cleanup;
|
|
}
|
|
|
|
|
|
if ( ( dwTranslateOptions & ( LINETRANSLATEOPTION_FORCELOCAL |
|
|
LINETRANSLATEOPTION_FORCELD) )
|
|
==
|
|
( LINETRANSLATEOPTION_FORCELOCAL |
|
|
LINETRANSLATEOPTION_FORCELD)
|
|
)
|
|
{
|
|
DBGOUT((1, " Invalid dwTranslateOptions (both FORCELOCAL & FORCELD set!)"));
|
|
lResult = LINEERR_INVALPARAM;
|
|
goto cleanup;
|
|
}
|
|
|
|
|
|
//
|
|
// Is the caller passing in a bogus version #?
|
|
//
|
|
if (
|
|
(dwAPIVersion != TAPI_VERSION2_0)
|
|
&&
|
|
(dwAPIVersion != TAPI_VERSION1_4)
|
|
&&
|
|
(dwAPIVersion != TAPI_VERSION1_0)
|
|
)
|
|
{
|
|
DBGOUT((1, " Invalid dwAPIVersion"));
|
|
lResult = LINEERR_INCOMPATIBLEAPIVERSION;
|
|
goto cleanup;
|
|
}
|
|
|
|
|
|
//*** *** ***BUGBUG Put in a check for length of lpszAddressIn. Restrict
|
|
// it to < 256 bytes (TCHARs?)
|
|
|
|
|
|
// if (IsValidLineApp (hLineApp) ) //), pParams->ptClient))
|
|
{
|
|
DWORD dwNeededSize;
|
|
|
|
|
|
//
|
|
// Is the structure at least a minimum size?
|
|
//
|
|
if ( IsBadWritePtr(lpTranslateOutput, sizeof(LINETRANSLATEOUTPUT))
|
|
||
|
|
(lpTranslateOutput->dwTotalSize < sizeof(LINETRANSLATEOUTPUT))
|
|
)
|
|
{
|
|
InternalDebugOut((1, " Leaving lineTranslateAddress STRUCTURETOOSMALL"));
|
|
return (LINEERR_STRUCTURETOOSMALL);
|
|
}
|
|
|
|
|
|
lResult = ReadLocations( &MyLocationList,
|
|
&pnStuff,
|
|
hLineApp,
|
|
dwDeviceID,
|
|
dwAPIVersion,
|
|
CHECKPARMS_DWHLINEAPP |
|
|
CHECKPARMS_DWDEVICEID |
|
|
CHECKPARMS_DWAPIVERSION
|
|
);
|
|
if ( 0 != lResult )
|
|
{
|
|
InternalDebugOut((1, " Leaving lineTranslateAddress result=0x%08lx", lResult));
|
|
return lResult;
|
|
}
|
|
|
|
|
|
// pnStuff[0] = nCurrentLocationID;
|
|
// pnStuff[1] = pLocationList;
|
|
// pnStuff[2] = nNumLocations;
|
|
|
|
InternalDebugOut((0, " Calling getlocationindex..."));
|
|
InternalDebugOut((0, " with lookingfor=0x%08lx list@0x%08lx num=0x%08lx",
|
|
pnStuff[0], MyLocationList, pnStuff[2]));
|
|
|
|
pThisLocation = &MyLocationList[GetLocationIndexFromID(pnStuff[0],
|
|
MyLocationList,
|
|
pnStuff[2])
|
|
];
|
|
|
|
InternalDebugOut((0, " back from getlocationindex..."));
|
|
|
|
|
|
ReadCardsEasy( &MyCardList, &pnCardStuff);
|
|
|
|
|
|
|
|
//
|
|
// If there is no override, and this location does not
|
|
// use a calling card, use no card.
|
|
//
|
|
if (
|
|
(
|
|
(LINETRANSLATEOPTION_CARDOVERRIDE & dwTranslateOptions)
|
|
&&
|
|
(dwCard != 0)
|
|
)
|
|
||
|
|
(pThisLocation->dwFlags & LOCATION_USECALLINGCARD)
|
|
)
|
|
{
|
|
//
|
|
// If caller wants to override the default calling card for
|
|
// this location, do it. Otherwise, use the default card for
|
|
// this location.
|
|
//
|
|
n = GetCardIndexFromID( (dwTranslateOptions &
|
|
LINETRANSLATEOPTION_CARDOVERRIDE) ?
|
|
dwCard :
|
|
pThisLocation->dwCallingCard,
|
|
MyCardList,
|
|
pnCardStuff[2]
|
|
);
|
|
|
|
|
|
//
|
|
// n is the zero-offset index into the list
|
|
//
|
|
if ( n >= pnCardStuff[2] )
|
|
{
|
|
lResult = LINEERR_INVALCARD;
|
|
goto cleanup;
|
|
}
|
|
|
|
|
|
pThisCard = &MyCardList[ n ];
|
|
|
|
}
|
|
//
|
|
//else
|
|
// pThisCard is already NULL
|
|
//
|
|
|
|
|
|
lResult = TranslateTheAddress( lpszAddressIn,
|
|
&lpszDialable,
|
|
&lpszDisplayable,
|
|
dwTranslateOptions,
|
|
&dwTranslateResults,
|
|
&dwCountry,
|
|
pThisCard,
|
|
pThisLocation
|
|
);
|
|
if (lResult)
|
|
{
|
|
goto cleanup;
|
|
}
|
|
|
|
|
|
dwDialableSize = sizeof(WCHAR) * (lstrlenW(lpszDialable) + 1);
|
|
dwDisplayableSize = sizeof(WCHAR) * (lstrlenW(lpszDisplayable) + 1);
|
|
|
|
dwNeededSize = dwDialableSize +
|
|
dwDisplayableSize +
|
|
3 + // For potential alignment problem
|
|
sizeof(LINETRANSLATEOUTPUT);
|
|
|
|
|
|
lpTranslateOutput->dwNeededSize = dwNeededSize;
|
|
|
|
|
|
//
|
|
// We checked above if the passed-in buffer is at least as
|
|
// large as the fixed-len size. If we got here, it is.
|
|
//
|
|
|
|
lpTranslateOutput->dwDialableStringSize = dwDialableSize;
|
|
|
|
lpTranslateOutput->dwDialableStringOffset =
|
|
sizeof(LINETRANSLATEOUTPUT);
|
|
|
|
lpTranslateOutput->dwDisplayableStringSize = dwDisplayableSize;
|
|
|
|
lpTranslateOutput->dwDisplayableStringOffset =
|
|
sizeof(LINETRANSLATEOUTPUT) + dwDialableSize;
|
|
// lpTranslateOutput->dwDisplayableStringOffset =
|
|
// (sizeof(LINETRANSLATEOUTPUT) + dwDialableSize
|
|
// + 3) & 0xfffffffc;
|
|
|
|
lpTranslateOutput->dwCurrentCountry =
|
|
pThisLocation->dwCountry;
|
|
|
|
lpTranslateOutput->dwDestCountry = dwCountry;
|
|
|
|
lpTranslateOutput->dwTranslateResults = dwTranslateResults;
|
|
|
|
|
|
//
|
|
// Only copy the strings if there's enough room
|
|
//
|
|
if (lpTranslateOutput->dwTotalSize < dwNeededSize)
|
|
{
|
|
DBGOUT((1, "lpTranslateOutput->dwTotalSize(%ld) < neededsize(%ld)",
|
|
lpTranslateOutput->dwTotalSize, dwNeededSize));
|
|
lpTranslateOutput->dwUsedSize = sizeof(LINETRANSLATEOUTPUT);
|
|
}
|
|
else
|
|
{
|
|
lpTranslateOutput->dwUsedSize = dwNeededSize;
|
|
|
|
lstrcpyW ((WCHAR *)(lpTranslateOutput + 1), lpszDialable);
|
|
|
|
//
|
|
// Be ultra paranoid and make sure the string is DWORD aligned
|
|
//
|
|
lstrcpyW ((LPWSTR)((DWORD)( (LPBYTE)(lpTranslateOutput + 1) +
|
|
dwDialableSize )),
|
|
// + 3 ) & 0xfffffffc)
|
|
lpszDisplayable);
|
|
}
|
|
|
|
}
|
|
|
|
|
|
cleanup:
|
|
|
|
|
|
if ( MyCardList )
|
|
ClientFree( MyCardList );
|
|
if ( pnCardStuff )
|
|
ClientFree( pnCardStuff );
|
|
if ( MyLocationList )
|
|
ClientFree( MyLocationList );
|
|
if ( pnStuff )
|
|
ClientFree( pnStuff );
|
|
if ( lpszDisplayable )
|
|
ClientFree( lpszDisplayable );
|
|
if ( lpszDialable )
|
|
ClientFree( lpszDialable );
|
|
|
|
return (lResult);
|
|
}
|
|
|
|
|
|
|
|
|
|
//***************************************************************************
|
|
//***************************************************************************
|
|
//***************************************************************************
|
|
LONG
|
|
WINAPI
|
|
lineTranslateAddressA(
|
|
HLINEAPP hLineApp,
|
|
DWORD dwDeviceID,
|
|
DWORD dwAPIVersion,
|
|
LPCSTR lpszAddressIn,
|
|
DWORD dwCard,
|
|
DWORD dwTranslateOptions,
|
|
LPLINETRANSLATEOUTPUT lpTranslateOutput
|
|
)
|
|
{
|
|
WCHAR szTempStringW[512];
|
|
LONG lResult;
|
|
|
|
|
|
if ( IsBadStringPtr(lpszAddressIn, 512) )
|
|
{
|
|
DBGOUT((1, "Invalid pszAddressIn pointer passed into lineTranslateAddress"));
|
|
return LINEERR_INVALPOINTER;
|
|
}
|
|
|
|
MultiByteToWideChar(
|
|
GetACP(),
|
|
MB_PRECOMPOSED,
|
|
lpszAddressIn,
|
|
-1,
|
|
szTempStringW,
|
|
512
|
|
);
|
|
|
|
lResult = lineTranslateAddressW(
|
|
hLineApp,
|
|
dwDeviceID,
|
|
dwAPIVersion,
|
|
szTempStringW,
|
|
dwCard,
|
|
dwTranslateOptions,
|
|
lpTranslateOutput
|
|
);
|
|
|
|
if ( 0 == lResult )
|
|
{
|
|
WideStringToNotSoWideString( (LPBYTE)lpTranslateOutput,
|
|
&lpTranslateOutput->dwDialableStringSize );
|
|
WideStringToNotSoWideString( (LPBYTE)lpTranslateOutput,
|
|
&lpTranslateOutput->dwDisplayableStringSize );
|
|
}
|
|
|
|
return lResult;
|
|
}
|
|
|
|
|
|
|
|
//***************************************************************************
|
|
//***************************************************************************
|
|
//***************************************************************************
|
|
LONG
|
|
WINAPI
|
|
lineTranslateAddress(
|
|
HLINEAPP hLineApp,
|
|
DWORD dwDeviceID,
|
|
DWORD dwAPIVersion,
|
|
LPCSTR lpszAddressIn,
|
|
DWORD dwCard,
|
|
DWORD dwTranslateOptions,
|
|
LPLINETRANSLATEOUTPUT lpTranslateOutput
|
|
)
|
|
{
|
|
return lineTranslateAddressA(
|
|
hLineApp,
|
|
dwDeviceID,
|
|
dwAPIVersion,
|
|
lpszAddressIn,
|
|
dwCard,
|
|
dwTranslateOptions,
|
|
lpTranslateOutput
|
|
);
|
|
}
|
|
|
|
|
|
//***************************************************************************
|
|
//***************************************************************************
|
|
//***************************************************************************
|
|
LONG
|
|
WINAPI
|
|
lineSetCurrentLocation(
|
|
HLINEAPP hLineApp,
|
|
DWORD dwLocationID
|
|
)
|
|
{
|
|
|
|
UINT n;
|
|
PUINT pnStuff;
|
|
PLOCATION MyLocationList;
|
|
LONG lResult = 0;
|
|
|
|
|
|
InternalDebugOut((1, "Entering lineSetCurrentLocation"));
|
|
|
|
|
|
lResult = ReadLocations( &MyLocationList,
|
|
&pnStuff,
|
|
hLineApp,
|
|
0,
|
|
0,
|
|
CHECKPARMS_DWHLINEAPP
|
|
);
|
|
if ( 0 != lResult )
|
|
{
|
|
InternalDebugOut((1, "Exiting lineSetCurrentLocation - result=0x%08lx",
|
|
lResult));
|
|
return lResult;
|
|
}
|
|
|
|
// pdwStuff[0] = nCurrentLocationID;
|
|
// pdwStuff[1] = pLocationList;
|
|
// pdwStuff[2] = nNumLocations;
|
|
|
|
|
|
n = GetLocationIndexFromID( dwLocationID, MyLocationList, pnStuff[2]);
|
|
|
|
//
|
|
// Did we find it?
|
|
//
|
|
if ( -1 == n )
|
|
{
|
|
//
|
|
// Nope. The caller's on drugs.
|
|
//
|
|
|
|
DBGOUT((1, "lineSetCurrentLocation: Location ID [%d] not found!", dwLocationID));
|
|
|
|
lResult = LINEERR_INVALLOCATION;
|
|
|
|
goto CLEANUP;
|
|
}
|
|
|
|
|
|
//
|
|
// Update gCurrentLocation and gnCurrentLocationID
|
|
//
|
|
//actually, no, don't do this
|
|
// SetCurrentLocation( dwLocationID );
|
|
|
|
|
|
//
|
|
// Save for all eternity
|
|
//
|
|
|
|
//
|
|
// First, let's make sure we don't shoot ourselves in the foot.
|
|
//
|
|
EnterCriticalSection( &gUICriticalSection );
|
|
|
|
|
|
// WriteLocations( MyLocationList, pnStuff[2],
|
|
// CHANGEDFLAGS_CURLOCATIONCHANGED, gpCurrentLocation );
|
|
|
|
//WRONG! WriteCurrentLocationValue( NULL, pnStuff[0] );
|
|
WriteCurrentLocationValue( NULL, dwLocationID );
|
|
|
|
|
|
LeaveCriticalSection( &gUICriticalSection );
|
|
|
|
|
|
CLEANUP:
|
|
|
|
ClientFree( MyLocationList );
|
|
ClientFree( pnStuff );
|
|
|
|
InternalDebugOut((1, "Leaving lineSetCurrentLocation"));
|
|
return lResult;
|
|
}
|
|
|
|
|
|
|
|
//***************************************************************************
|
|
//***************************************************************************
|
|
//***************************************************************************
|
|
LONG
|
|
WINAPI
|
|
lineSetTollListW(
|
|
HLINEAPP hLineApp,
|
|
DWORD dwDeviceID,
|
|
LPCWSTR lpszAddressInW,
|
|
DWORD dwTollListOption
|
|
)
|
|
{
|
|
LONG lResult = 0;
|
|
PLOCATION pLocationList;
|
|
PUINT pnStuff;
|
|
UINT nThisLocation;
|
|
LPWSTR pTollListW;
|
|
LPWSTR pEntryInListW;
|
|
|
|
LPWSTR pCountry;
|
|
LPWSTR pCity;
|
|
LPWSTR pSubscriber;
|
|
LPWSTR pAddressIn;
|
|
DWORD dwChangeFlags = 0;
|
|
|
|
|
|
InternalDebugOut((1, "Entering lineSetTollListW"));
|
|
|
|
|
|
//*** *** ***BUGBUG More cases!
|
|
// We declare success (NOOP) if:
|
|
// 1. number isn't local call
|
|
// 2. number is in toll list already and this is add
|
|
// 3. number isn't in toll list and this is remove
|
|
//
|
|
|
|
|
|
//
|
|
// Is the caller an idiot?
|
|
//
|
|
if ((dwTollListOption != LINETOLLLISTOPTION_ADD) &&
|
|
(dwTollListOption != LINETOLLLISTOPTION_REMOVE))
|
|
{
|
|
DBGOUT((1, "Bad dwTollListOption in lineSetTollListW"));
|
|
return LINEERR_INVALPARAM;
|
|
}
|
|
|
|
|
|
if ( IsBadStringPtrW(lpszAddressInW, 256) )
|
|
{
|
|
DBGOUT((1, "Bad lpszAddressIn (0x%08lx)in lineSetTollListW", lpszAddressInW));
|
|
return LINEERR_INVALPOINTER;
|
|
}
|
|
|
|
pAddressIn = ClientAlloc( (lstrlenW(lpszAddressInW) + 1) * sizeof(WCHAR));
|
|
if ( !pAddressIn )
|
|
{
|
|
DBGOUT((1, "Memory allocation failed3"));
|
|
return LINEERR_NOMEM;
|
|
}
|
|
|
|
|
|
//
|
|
// Now, do we have a canonical number to deal with, or is it junk?
|
|
//
|
|
if ( *lpszAddressInW != (WCHAR)'+' ) // Check the first char
|
|
{
|
|
//
|
|
// Nope, not canonical
|
|
//
|
|
lResult = LINEERR_INVALADDRESS;
|
|
goto cleanup;
|
|
}
|
|
|
|
|
|
//
|
|
// Copy the string to our local buffer so we can mangle it
|
|
//
|
|
lstrcpyW( pAddressIn, lpszAddressInW + 1 );
|
|
|
|
|
|
//
|
|
// Pick out the juicy bits
|
|
//
|
|
if ( lResult = BreakupCanonicalW( pAddressIn,
|
|
&pCountry,
|
|
&pCity,
|
|
&pSubscriber
|
|
)
|
|
)
|
|
{
|
|
goto cleanup;
|
|
}
|
|
|
|
|
|
//*** *** ***BUGBUG Really(!) need to check return code!
|
|
|
|
DBGOUT((71, "Country:%ls City:%ls Subscriber:%ls",
|
|
pCountry, pCity, pSubscriber));
|
|
|
|
|
|
//
|
|
// Do another check on the phone number to make _really_ sure it's
|
|
// canonical
|
|
//
|
|
//BUGBUG: assumption - that a toll prefix is 3 tchars
|
|
if ( ! ( IsWDigit(pSubscriber[0]) &&
|
|
IsWDigit(pSubscriber[1]) &&
|
|
IsWDigit(pSubscriber[2])
|
|
// &&
|
|
// pSubscriber[3] == '-'
|
|
)
|
|
)
|
|
{
|
|
//
|
|
// AAHA! Caught ya, ya bastard.
|
|
//
|
|
DBGOUT((1, "lineSetTollListW: The prefix is not valid"));
|
|
lResult = LINEERR_INVALADDRESS;
|
|
goto cleanup;
|
|
}
|
|
|
|
|
|
//
|
|
// Build our own location stuff.
|
|
//
|
|
lResult = ReadLocations( &pLocationList,
|
|
&pnStuff,
|
|
hLineApp,
|
|
dwDeviceID,
|
|
0,
|
|
CHECKPARMS_DWHLINEAPP |
|
|
CHECKPARMS_DWDEVICEID
|
|
);
|
|
if ( 0 != lResult )
|
|
{
|
|
goto cleanup;
|
|
}
|
|
|
|
|
|
nThisLocation = GetLocationIndexFromID( pnStuff[0],
|
|
pLocationList,
|
|
pnStuff[2]
|
|
);
|
|
|
|
|
|
//
|
|
// So, is this number in the same country and area code?
|
|
//
|
|
|
|
{
|
|
PWSTR pszTemp;
|
|
|
|
pszTemp = ClientAlloc( 10 * sizeof(WCHAR) );
|
|
|
|
wsprintfW( pszTemp, L"%ld", pLocationList[nThisLocation].dwCountry );
|
|
|
|
if ( lstrcmpiW( pCountry, pszTemp ) )
|
|
{
|
|
DBGOUT((4, "This country ID [%ls] is different from the current country [%ld]",
|
|
pCountry, pLocationList[nThisLocation].dwCountry));
|
|
|
|
ClientFree( pszTemp );
|
|
|
|
return 0;
|
|
}
|
|
|
|
ClientFree( pszTemp );
|
|
}
|
|
|
|
|
|
if ( lstrcmpiW( pCity, pLocationList[nThisLocation].AreaCodeW))
|
|
{
|
|
DBGOUT((4, "This city code [%ls] is different from the current city code [%ls]",
|
|
pCity, pLocationList[nThisLocation].AreaCodeW));
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
//
|
|
// Ok, the data's valid. We won't need to use pSubscriber again,
|
|
// so we'll trash it a bit.
|
|
//
|
|
//BUGBUG: assumption - that a toll prefix is 3 tchars
|
|
pSubscriber[3] = ',';
|
|
pSubscriber[4] = '\0';
|
|
|
|
|
|
pTollListW = &(pLocationList[nThisLocation].TollListW[0]);
|
|
|
|
|
|
//
|
|
// Is the entry in the list?
|
|
//
|
|
pEntryInListW = wcsstr(pTollListW, pSubscriber);
|
|
|
|
|
|
//
|
|
// So, what are we here for?
|
|
//
|
|
if ( dwTollListOption == LINETOLLLISTOPTION_ADD )
|
|
{
|
|
//
|
|
// Ok, the caller wants to add this prefix. Is it already there?
|
|
//
|
|
if ( NULL == pEntryInListW )
|
|
{
|
|
|
|
//
|
|
// If the tolllist is empty, start it off right.
|
|
//
|
|
if ( pTollListW[0] == '\0' )
|
|
{
|
|
pTollListW[0] = ',';
|
|
pTollListW[1] = '\0';
|
|
}
|
|
|
|
|
|
//
|
|
// Now, we hafta do the work
|
|
//
|
|
lstrcatW( pTollListW, pSubscriber );
|
|
|
|
dwChangeFlags |= CHANGEDFLAGS_TOLLLIST;
|
|
}
|
|
// else
|
|
// {
|
|
// //
|
|
// // Yes, it's already there. Do nothing.
|
|
// //
|
|
// }
|
|
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Ok, the caller wants to delete this prefix. Is it even there?
|
|
//
|
|
if ( pEntryInListW )
|
|
{
|
|
//
|
|
// Yes, it's there. Ok, remove it. (copy from the first ',' past the start)
|
|
//
|
|
lstrcpyW( pEntryInListW, wcschr(pEntryInListW, ',')+1 );
|
|
|
|
dwChangeFlags |= CHANGEDFLAGS_TOLLLIST;
|
|
}
|
|
// else
|
|
// {
|
|
// //
|
|
// // Nope, it's not there. Do nothing.
|
|
// //
|
|
// }
|
|
|
|
}
|
|
|
|
|
|
//
|
|
// Ok, now save the new string (if appropriate)
|
|
//
|
|
|
|
EnterCriticalSection( &gUICriticalSection );
|
|
|
|
WriteLocations( pLocationList, pnStuff[2],
|
|
dwChangeFlags, &pLocationList[nThisLocation] );
|
|
|
|
LeaveCriticalSection( &gUICriticalSection );
|
|
|
|
|
|
if (pnStuff)
|
|
ClientFree( pnStuff );
|
|
|
|
if (pLocationList)
|
|
ClientFree( pLocationList );
|
|
|
|
|
|
cleanup:
|
|
|
|
ClientFree( pAddressIn );
|
|
|
|
|
|
InternalDebugOut((1, "Leaving lineSetCurrentLocation result=0x%08lx",
|
|
lResult));
|
|
return lResult;
|
|
}
|
|
|
|
|
|
|
|
//***************************************************************************
|
|
//***************************************************************************
|
|
//***************************************************************************
|
|
LONG
|
|
WINAPI
|
|
lineSetTollListA(
|
|
HLINEAPP hLineApp,
|
|
DWORD dwDeviceID,
|
|
LPCSTR lpszAddressIn,
|
|
DWORD dwTollListOption
|
|
)
|
|
{
|
|
WCHAR szAddressInW[512];
|
|
|
|
if ( IsBadStringPtr(lpszAddressIn, 512) )
|
|
{
|
|
DBGOUT((1, "Bad string pointer passed to lineSetTollList"));
|
|
return LINEERR_INVALPOINTER;
|
|
}
|
|
|
|
MultiByteToWideChar(
|
|
GetACP(),
|
|
MB_PRECOMPOSED,
|
|
lpszAddressIn,
|
|
-1,
|
|
szAddressInW,
|
|
512
|
|
);
|
|
|
|
return lineSetTollListW(
|
|
hLineApp,
|
|
dwDeviceID,
|
|
szAddressInW,
|
|
dwTollListOption
|
|
);
|
|
}
|
|
|
|
|
|
|
|
//***************************************************************************
|
|
//***************************************************************************
|
|
//***************************************************************************
|
|
LONG
|
|
WINAPI
|
|
lineSetTollList(
|
|
HLINEAPP hLineApp,
|
|
DWORD dwDeviceID,
|
|
LPCSTR lpszAddressIn,
|
|
DWORD dwTollListOption
|
|
)
|
|
{
|
|
return lineSetTollListA(
|
|
hLineApp,
|
|
dwDeviceID,
|
|
lpszAddressIn,
|
|
dwTollListOption
|
|
);
|
|
}
|
|
|
|
|
|
//***************************************************************************
|
|
//***************************************************************************
|
|
//***************************************************************************
|
|
LONG
|
|
WINAPI
|
|
tapiGetLocationInfoW(
|
|
LPWSTR lpszCountryCode,
|
|
LPWSTR lpszCityCode
|
|
)
|
|
{
|
|
PLOCATION pLocationList;
|
|
LOCATION Location;
|
|
PUINT pnStuff;
|
|
LONG lResult = 0;
|
|
|
|
if (IsBadWritePtr( lpszCountryCode, 16) )
|
|
{
|
|
DBGOUT((1, "tapiGetLocationInfoW: lpszCountryCode is not a valid, 8-byte pointer"));
|
|
//*** *** ***BUGBUG is this the right error code? - docs say it's the only legal one...
|
|
return TAPIERR_REQUESTFAILED;
|
|
}
|
|
|
|
|
|
if (IsBadWritePtr( lpszCityCode, 16) )
|
|
{
|
|
DBGOUT((1, "tapiGetLocationInfoW: lpszCityCode is not a valid, 8-byte pointer"));
|
|
//*** *** ***BUGBUG is this the right error code? - docs say it's the only legal one...
|
|
return TAPIERR_REQUESTFAILED;
|
|
}
|
|
|
|
|
|
lResult = ReadLocations( &pLocationList,
|
|
&pnStuff,
|
|
0,
|
|
0,
|
|
0,
|
|
0
|
|
);
|
|
if ( 0 != lResult )
|
|
{
|
|
//BUGBUG Should we throw up the mini dialhelper for the caller since
|
|
//the only return code we're "allowed" to return is so generic, the
|
|
//caller won't know what to do (besides, it's called "simple" tapi)
|
|
|
|
return TAPIERR_REQUESTFAILED;
|
|
}
|
|
|
|
|
|
// pnStuff[0] = nCurrentLocationID;
|
|
// pnStuff[1] = (UINT)pLocationList;
|
|
// pnStuff[2] = nNumLocations;
|
|
|
|
GetThisLocation( &Location, pnStuff[0], pLocationList, pnStuff[2] );
|
|
//*** *** ***BUGBUG Need to check return code
|
|
|
|
|
|
wsprintfW( lpszCountryCode, L"%d", Location.dwCountry );
|
|
|
|
wsprintfW(lpszCityCode, L"%ls", Location.AreaCodeW );
|
|
|
|
|
|
ClientFree( pLocationList );
|
|
ClientFree( pnStuff );
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
//***************************************************************************
|
|
//***************************************************************************
|
|
//***************************************************************************
|
|
LONG
|
|
WINAPI
|
|
tapiGetLocationInfoA(
|
|
LPSTR lpszCountryCode,
|
|
LPSTR lpszCityCode
|
|
)
|
|
{
|
|
|
|
WCHAR szCountryCodeW[8];
|
|
WCHAR szCityCodeW[8];
|
|
LONG lResult;
|
|
|
|
|
|
if (IsBadWritePtr( lpszCountryCode, 8) )
|
|
{
|
|
DBGOUT((1, "tapiGetLocationInfo: lpszCountryCode is not a valid, 8-byte pointer"));
|
|
//*** *** ***BUGBUG is this the right error code? - docs say it's the only legal one...
|
|
return TAPIERR_REQUESTFAILED;
|
|
}
|
|
|
|
|
|
if (IsBadWritePtr( lpszCityCode, 8) )
|
|
{
|
|
DBGOUT((1, "tapiGetLocationInfo: lpszCityCode is not a valid, 8-byte pointer"));
|
|
//*** *** ***BUGBUG is this the right error code? - docs say it's the only legal one...
|
|
return TAPIERR_REQUESTFAILED;
|
|
}
|
|
|
|
lResult = tapiGetLocationInfoW(
|
|
szCountryCodeW,
|
|
szCityCodeW
|
|
);
|
|
|
|
if ( 0 == lResult )
|
|
{
|
|
WideCharToMultiByte(
|
|
GetACP(),
|
|
0,
|
|
szCountryCodeW,
|
|
-1,
|
|
lpszCountryCode,
|
|
8,
|
|
NULL,
|
|
NULL
|
|
);
|
|
|
|
WideCharToMultiByte(
|
|
GetACP(),
|
|
0,
|
|
szCityCodeW,
|
|
-1,
|
|
lpszCityCode,
|
|
8,
|
|
NULL,
|
|
NULL
|
|
);
|
|
}
|
|
|
|
return lResult;
|
|
}
|
|
|
|
|
|
//***************************************************************************
|
|
//***************************************************************************
|
|
//***************************************************************************
|
|
LONG
|
|
WINAPI
|
|
tapiGetLocationInfo(
|
|
LPSTR lpszCountryCode,
|
|
LPSTR lpszCityCode
|
|
)
|
|
{
|
|
return tapiGetLocationInfoA(
|
|
lpszCountryCode,
|
|
lpszCityCode
|
|
);
|
|
}
|
|
|
|
|
|
|
|
|
|
#ifndef NORASPRIVATES
|
|
|
|
/*----------------------------------------------------------------------------
|
|
** Private entry points used by RAS
|
|
**----------------------------------------------------------------------------
|
|
**
|
|
** RASDLG.DLL uses these to create, rename, and delete TAPI locations for it's
|
|
** down-level prefix/suffix phone number modifiers. These privates depend on
|
|
** the following TAPI routines:
|
|
**
|
|
** AllocNewID
|
|
** ClientAlloc
|
|
** ClientFree
|
|
** ReadLocations
|
|
** WriteLocations
|
|
**
|
|
** The routines are named internalXxx to make it clear to relocation-table
|
|
** scanners that the APIs were not intended to be published.
|
|
**
|
|
** 03/09/96 Steve Cobb (reviewed by BernieM)
|
|
*/
|
|
|
|
LOCATION*
|
|
LocationFromID(
|
|
IN LOCATION* pLocs,
|
|
IN UINT cLocs,
|
|
IN DWORD dwID )
|
|
|
|
/* Returns address of the location in array 'pLocs' with ID 'dwId' or NULL
|
|
** if not found. 'CLocs' is the number of locations in 'pLocs'.
|
|
*/
|
|
{
|
|
LOCATION* pLoc;
|
|
UINT i;
|
|
|
|
for (i = 0, pLoc = pLocs; i < cLocs; ++i, ++pLoc)
|
|
{
|
|
if (pLoc->dwID == dwID)
|
|
return pLoc;
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
|
|
LOCATION*
|
|
LocationFromName(
|
|
IN LOCATION* pLocs,
|
|
IN UINT cLocs,
|
|
IN WCHAR* pszName )
|
|
|
|
/* Returns address of the location in array 'pLocs' with name 'pszName' or
|
|
** NULL if not found. 'CLocs' is the number of locations in 'pLocs'.
|
|
*/
|
|
{
|
|
LOCATION* pLoc;
|
|
UINT i;
|
|
|
|
for (i = 0, pLoc = pLocs; i < cLocs; ++i, ++pLoc)
|
|
{
|
|
if (lstrcmpW( pLoc->NameW, pszName ) == 0)
|
|
return pLoc;
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
|
|
DWORD APIENTRY
|
|
internalNewLocationW(
|
|
IN WCHAR* pszName )
|
|
|
|
/* Create a new TAPI location that is a clone of the current location but
|
|
** with name 'pszName'. The new location is assigned it's own unique ID
|
|
** by this routine.
|
|
**
|
|
** Returns 0 if succesful, or an error code.
|
|
*/
|
|
{
|
|
DWORD dwErr;
|
|
LOCATION* pLocs;
|
|
LOCATION* pCurLoc;
|
|
LOCATION* pNewLocs;
|
|
LOCATION* pNewLoc;
|
|
UINT* punStuff;
|
|
UINT cLocs;
|
|
DWORD dwCurID;
|
|
|
|
/* Validate argument.
|
|
*/
|
|
if (!pszName || lstrlenW( pszName ) > MAXLEN_NAME)
|
|
return LINEERR_INVALPARAM;
|
|
|
|
pLocs = NULL;
|
|
pNewLocs = NULL;
|
|
punStuff = NULL;
|
|
|
|
/* Retrieve the location array.
|
|
*/
|
|
dwErr = ReadLocations( &pLocs, &punStuff, 0, 0, 0, 0 );
|
|
if (dwErr != 0)
|
|
return dwErr;
|
|
|
|
do
|
|
{
|
|
/* Extract the current location's ID and the location count from the
|
|
** returned "stuff" array.
|
|
*/
|
|
dwCurID = punStuff[ 0 ];
|
|
cLocs = punStuff[ 2 ];
|
|
|
|
/* Allocate a new array one larger.
|
|
*/
|
|
pNewLocs = ClientAlloc( (cLocs + 1) * sizeof(LOCATION) );
|
|
if (!pNewLocs)
|
|
{
|
|
dwErr = ERROR_NOT_ENOUGH_MEMORY;
|
|
break;
|
|
}
|
|
|
|
/* Copy the old array to the new array.
|
|
*/
|
|
CopyMemory( pNewLocs, pLocs, cLocs * sizeof(LOCATION) );
|
|
|
|
/* Copy the current location in the old array over the extra location
|
|
** in the new array.
|
|
*/
|
|
pCurLoc = LocationFromID( pLocs, cLocs, dwCurID );
|
|
if (!pCurLoc)
|
|
{
|
|
dwErr = LINEERR_INVALLOCATION;
|
|
break;
|
|
}
|
|
|
|
pNewLoc = pNewLocs + cLocs;
|
|
CopyMemory( pNewLoc, pCurLoc, sizeof(LOCATION) );
|
|
|
|
/* Give the new location a unique ID and caller's chosen name.
|
|
*/
|
|
AllocNewID( HKEY_LOCAL_MACHINE, &pNewLoc->dwID );
|
|
lstrcpyW( pNewLoc->NameW, pszName );
|
|
|
|
/* Write the new array.
|
|
*/
|
|
WriteLocations(
|
|
pNewLocs, cLocs + 1,
|
|
CHANGEDFLAGS_REALCHANGE | CHANGEDFLAGS_TOLLLIST, pCurLoc );
|
|
}
|
|
while (FALSE);
|
|
|
|
/* Clean up.
|
|
*/
|
|
if (pLocs)
|
|
ClientFree( pLocs );
|
|
if (punStuff)
|
|
ClientFree( punStuff );
|
|
if (pNewLocs)
|
|
ClientFree( pNewLocs );
|
|
|
|
return dwErr;
|
|
}
|
|
|
|
|
|
DWORD APIENTRY
|
|
internalRemoveLocation(
|
|
IN DWORD dwID )
|
|
|
|
/* Removes the TAPI location with ID 'dwID'.
|
|
**
|
|
** Returns 0 if successful, or an error code.
|
|
*/
|
|
{
|
|
DWORD dwErr;
|
|
LOCATION* pLocs;
|
|
LOCATION* pCurLoc;
|
|
LOCATION* pLoc;
|
|
UINT* punStuff;
|
|
UINT cLocs;
|
|
DWORD dwCurID;
|
|
DWORD dwFlags;
|
|
|
|
pLocs = NULL;
|
|
punStuff = NULL;
|
|
|
|
/* Retrieve the location array.
|
|
*/
|
|
dwErr = ReadLocations( &pLocs, &punStuff, 0, 0, 0, 0 );
|
|
if (dwErr != 0)
|
|
return dwErr;
|
|
|
|
do
|
|
{
|
|
/* Extract the current location's ID and the location count from the
|
|
** returned "stuff" array.
|
|
*/
|
|
dwCurID = punStuff[ 0 ];
|
|
cLocs = punStuff[ 2 ];
|
|
|
|
/* Can't delete the last location.
|
|
*/
|
|
if (cLocs < 2)
|
|
{
|
|
dwErr = LINEERR_INVALPARAM;
|
|
break;
|
|
}
|
|
|
|
/* Set the name of the location to "" which causes WriteLocations to
|
|
** delete it.
|
|
*/
|
|
pLoc = LocationFromID( pLocs, cLocs, dwID );
|
|
if (!pLoc)
|
|
{
|
|
dwErr = LINEERR_INVALLOCATION;
|
|
break;
|
|
}
|
|
pLoc->NameW[ 0 ] = L'\0';
|
|
|
|
/* If we're deleting the current location make the first location the
|
|
** current location, or if we're deleting the first the second.
|
|
*/
|
|
dwFlags = CHANGEDFLAGS_REALCHANGE;
|
|
if (dwCurID == dwID)
|
|
{
|
|
if (pLocs->dwID == dwID)
|
|
pCurLoc = pLocs + 1;
|
|
else
|
|
pCurLoc = pLocs;
|
|
dwFlags |= CHANGEDFLAGS_CURLOCATIONCHANGED;
|
|
}
|
|
else
|
|
{
|
|
pCurLoc = LocationFromID( pLocs, cLocs, dwCurID );
|
|
if (!pCurLoc)
|
|
{
|
|
dwErr = LINEERR_INVALLOCATION;
|
|
break;
|
|
}
|
|
}
|
|
|
|
/* Write the changed array.
|
|
*/
|
|
WriteLocations( pLocs, cLocs, dwFlags, pCurLoc );
|
|
}
|
|
while (FALSE);
|
|
|
|
/* Clean up.
|
|
*/
|
|
if (pLocs)
|
|
ClientFree( pLocs );
|
|
if (punStuff)
|
|
ClientFree( punStuff );
|
|
|
|
return dwErr;
|
|
}
|
|
|
|
|
|
DWORD APIENTRY
|
|
internalRenameLocationW(
|
|
IN WCHAR* pszOldName,
|
|
IN WCHAR* pszNewName )
|
|
|
|
/* Renames TAPI location with name 'pszOldName' to 'pszNewName'.
|
|
**
|
|
** Returns 0 if successful, or an error code.
|
|
*/
|
|
{
|
|
DWORD dwErr;
|
|
LOCATION* pLocs;
|
|
LOCATION* pLoc;
|
|
UINT* punStuff;
|
|
UINT cLocs;
|
|
|
|
/* Validate argument.
|
|
*/
|
|
if (!pszOldName || !pszNewName || lstrlenW( pszNewName ) > MAXLEN_NAME)
|
|
return LINEERR_INVALPARAM;
|
|
|
|
pLocs = NULL;
|
|
punStuff = NULL;
|
|
|
|
/* Retrieve the location array.
|
|
*/
|
|
dwErr = ReadLocations( &pLocs, &punStuff, 0, 0, 0, 0 );
|
|
if (dwErr != 0)
|
|
return dwErr;
|
|
|
|
do
|
|
{
|
|
/* Extract the current location count from the returned "stuff" array.
|
|
*/
|
|
cLocs = punStuff[ 2 ];
|
|
|
|
/* Find the old location and change it's name.
|
|
*/
|
|
pLoc = LocationFromName( pLocs, cLocs, pszOldName );
|
|
if (!pLoc)
|
|
{
|
|
dwErr = LINEERR_INVALPARAM;
|
|
break;
|
|
}
|
|
|
|
lstrcpyW( pLoc->NameW, pszNewName );
|
|
|
|
/* Write the changed array.
|
|
*/
|
|
WriteLocations( pLocs, cLocs, CHANGEDFLAGS_REALCHANGE, pLoc );
|
|
}
|
|
while (FALSE);
|
|
|
|
/* Clean up.
|
|
*/
|
|
if (pLocs)
|
|
ClientFree( pLocs );
|
|
if (punStuff)
|
|
ClientFree( punStuff );
|
|
|
|
return dwErr;
|
|
}
|
|
|
|
|
|
#endif // !NORASPRIVATES
|
|
|