/**************************************************************************** Copyright (c) 1998-1999 Microsoft Corporation Module Name: location.cpp Abstract: Location Object implementation Author: noela - 09/11/98 Notes: Rev History: ****************************************************************************/ #include #include #include "tapi.h" #include "tspi.h" #include "client.h" #include "location.h" #include "clntprivate.h" #include "countrygroup.h" #include #define MaxDialStringSize 500 LONG PASCAL ReadCountries( LPLINECOUNTRYLIST *ppLCL, UINT nCountryID, DWORD dwDestCountryID ); HRESULT ReadLocations( PLOCATIONLIST *ppLocationList, HLINEAPP hLineApp, DWORD dwDeviceID, DWORD dwAPIVersion, DWORD dwOptions ); LONG PASCAL WriteLocations( PLOCATIONLIST pLocationList, DWORD dwChangedFlags ); LONG BreakupCanonicalW( PWSTR pAddressIn, PWSTR *pCountry, PWSTR *pCity, PWSTR *pSubscriber ); DWORD TapiPackString(LPBYTE pStructure, DWORD dwOffset, DWORD dwTotalSize, PWSTR pszString, PDWORD pdwOffset, PDWORD pdwSize ); LONG AppendDigits( PWSTR pDest, PWSTR pSrc, PWSTR pValidChars ); HRESULT CreateCountryObject(DWORD dwCountryID, CCountry **ppCountry); int IsCityRule(LPWSTR lpRule); LONG ApplyRule (PWSTR pszDialString, PWSTR pszDisplayString, PWSTR pszRule, PWSTR pszDestLDRule, // used for Area code adjustments PWSTR pszLongDistanceCarrier, PWSTR pszInternationalCarrier, PWSTR pszCountry, PWSTR pszCity, PWSTR pszSubscriber, PWSTR pCardName, PWSTR pCardAccessNumber, PWSTR pCardAccountNumber, PWSTR pCardPINNumber ); BOOL PrefixMatch(PWSTR pszPrefix,PWSTR pszSubscriberString, PDWORD pdwMatched); BOOL AreaCodeMatch(PWSTR pszAreaCode1, PWSTR pszAreaCode2, PWSTR pszRule); PWSTR SkipLDAccessDigits(PWSTR pszAreaCode, PWSTR pszLDRule); #define LOCAL 1 #define LONG_DISTANCE 2 #define INTERNATIONAL 3 const WCHAR csSCANTO[] = L"\r"; const WCHAR csDISPSUPRESS[] = L"TtPp,Ww@?!$"; const WCHAR csBADCO[] = L"AaBbCcDdPpTtWw*#!,@$?;()"; const WCHAR csSCANSUB[] = L"^|/"; /* *************************************************************************** ********************* **************************** ******************** CLocation Class *************************** ******************** Definitions *************************** ********************* **************************** *************************************************************************** */ /**************************************************************************** Class : CLocation Method : Constructer ****************************************************************************/ CLocation::CLocation() { m_pszLocationName = NULL; m_pszLongDistanceAccessCode = NULL; m_pszLocalAccessCode = NULL; m_pszDisableCallWaitingCode = NULL; m_pszAreaCode = NULL; m_bFromRegistry = FALSE; m_bChanged = FALSE; m_dwNumRules = 0; m_hEnumNode = m_AreaCodeRuleList.head(); m_pszTAPIDialingRule = NULL; } /**************************************************************************** Class : CLocation Method : Destructer Clean up memory allocations ****************************************************************************/ CLocation::~CLocation() { if ( m_pszLocationName != NULL ) { ClientFree(m_pszLocationName); } if ( m_pszLongDistanceAccessCode != NULL ) { ClientFree(m_pszLongDistanceAccessCode); } if ( m_pszLocalAccessCode != NULL ) { ClientFree(m_pszLocalAccessCode); } if ( m_pszDisableCallWaitingCode != NULL ) { ClientFree(m_pszDisableCallWaitingCode); } if ( m_pszAreaCode != NULL ) { ClientFree(m_pszAreaCode); } if ( m_pszTAPIDialingRule != NULL ) { ClientFree(m_pszTAPIDialingRule); } if (m_pszLongDistanceCarrierCode != NULL) { ClientFree (m_pszLongDistanceCarrierCode); } if (m_pszInternationalCarrierCode != NULL) { ClientFree (m_pszInternationalCarrierCode); } // clean up Area Code List AreaCodeRulePtrNode *node; node = m_AreaCodeRuleList.head(); while( !node->beyond_tail() ) { delete node->value(); node = node->next(); } m_AreaCodeRuleList.flush(); } /**************************************************************************** Class : CLocation Method : Initialize ****************************************************************************/ STDMETHODIMP CLocation::Initialize ( PWSTR pszLocationName, PWSTR pszAreaCode, PWSTR pszLongDistanceCarrierCode, PWSTR pszInternationalCarrierCode, PWSTR pszLongDistanceAccessCode, PWSTR pszLocalAccessCode, PWSTR pszDisableCallWaitingCode, DWORD dwLocationID, DWORD dwCountryID, DWORD dwPreferredCardID, DWORD dwOptions , BOOL bFromRegistry ) { m_pszLocationName = ClientAllocString( pszLocationName ); if (m_pszLocationName == NULL) { LOG(( TL_ERROR, "Initialize - alloc m_pszLocationName failed" )); return E_OUTOFMEMORY; } m_pszLongDistanceAccessCode = ClientAllocString( pszLongDistanceAccessCode ); if (m_pszLongDistanceAccessCode == NULL) { ClientFree(m_pszLocationName); LOG(( TL_ERROR, "Initialize - alloc m_pszLongDistanceAccessCode failed" )); return E_OUTOFMEMORY; } m_pszLocalAccessCode = ClientAllocString( pszLocalAccessCode ); if (m_pszLocalAccessCode == NULL) { ClientFree(m_pszLocationName); ClientFree(m_pszLongDistanceAccessCode); LOG(( TL_ERROR, "Initialize - alloc m_pszLocalAccessCode failed" )); return E_OUTOFMEMORY; } m_pszDisableCallWaitingCode = ClientAllocString( pszDisableCallWaitingCode ); if (m_pszDisableCallWaitingCode == NULL) { ClientFree(m_pszLocationName); ClientFree(m_pszLongDistanceAccessCode); ClientFree(m_pszLocalAccessCode); LOG(( TL_ERROR, "Initialize - alloc m_pszDisableCallWaitingCode failed" )); return E_OUTOFMEMORY; } m_pszAreaCode = ClientAllocString( pszAreaCode ); if (m_pszAreaCode == NULL) { ClientFree(m_pszLocationName); ClientFree(m_pszLongDistanceAccessCode); ClientFree(m_pszLocalAccessCode); ClientFree(m_pszDisableCallWaitingCode); LOG(( TL_ERROR, "Initialize - alloc m_pszAreaCode failed" )); return E_OUTOFMEMORY; } m_pszLongDistanceCarrierCode = ClientAllocString( pszLongDistanceCarrierCode ); if (m_pszLongDistanceCarrierCode == NULL) { ClientFree(m_pszLocationName); ClientFree(m_pszLongDistanceAccessCode); ClientFree(m_pszLocalAccessCode); ClientFree(m_pszDisableCallWaitingCode); ClientFree(m_pszAreaCode); LOG(( TL_ERROR, "Initialize - alloc m_pszLongDistanceCarrierCode failed" )); return E_OUTOFMEMORY; } m_pszInternationalCarrierCode = ClientAllocString( pszInternationalCarrierCode ); if (m_pszInternationalCarrierCode == NULL) { ClientFree(m_pszLocationName); ClientFree(m_pszLongDistanceAccessCode); ClientFree(m_pszLocalAccessCode); ClientFree(m_pszDisableCallWaitingCode); ClientFree(m_pszAreaCode); ClientFree(m_pszLongDistanceCarrierCode); LOG(( TL_ERROR, "Initialize - alloc m_pszInternationalCarrierCode failed" )); return E_OUTOFMEMORY; } m_dwLocationID = dwLocationID; m_dwCountryID = dwCountryID ? dwCountryID : 1; // workaround for a bogus country ID m_dwPreferredCardID = dwPreferredCardID; m_dwOptions = dwOptions; m_bFromRegistry = bFromRegistry; if (m_bFromRegistry == FALSE) { m_bChanged = TRUE; } return S_OK; } /**************************************************************************** Class : CLocation Method : UseCallWaiting ****************************************************************************/ void CLocation::UseCallWaiting(BOOL bCw) { if(bCw) { m_dwOptions |= LOCATION_HASCALLWAITING; } else { m_dwOptions &= ~LOCATION_HASCALLWAITING; } m_bChanged = TRUE; } /**************************************************************************** Class : CLocation Method : UseCallingCard ****************************************************************************/ void CLocation::UseCallingCard(BOOL bCc) { if(bCc) { m_dwOptions |= LOCATION_USECALLINGCARD; } else { m_dwOptions &= ~LOCATION_USECALLINGCARD; } m_bChanged = TRUE; } /**************************************************************************** Class : CLocation Method : UseToneDialing ****************************************************************************/ void CLocation::UseToneDialing(BOOL bCc) { if(bCc) { m_dwOptions |= LOCATION_USETONEDIALING; } else { m_dwOptions &= ~LOCATION_USETONEDIALING; } m_bChanged = TRUE; } /**************************************************************************** Class : CLocation Method : setName ****************************************************************************/ STDMETHODIMP CLocation::SetName(PWSTR pszLocationName) { HRESULT hr = S_OK; if (m_pszLocationName != NULL) { ClientFree(m_pszLocationName); m_pszLocationName = NULL; } if(pszLocationName != NULL) { m_pszLocationName = ClientAllocString( pszLocationName ); if (m_pszLocationName == NULL) { LOG(( TL_ERROR, "setName - alloc failed" )); hr = E_OUTOFMEMORY; } } m_bChanged = TRUE; return hr; } /**************************************************************************** Class : CLocation Method : setAreaCode ****************************************************************************/ STDMETHODIMP CLocation::SetAreaCode(PWSTR pszAreaCode) { HRESULT hr = S_OK; if (m_pszAreaCode != NULL) { ClientFree(m_pszAreaCode); m_pszAreaCode = NULL; } if(pszAreaCode != NULL) { m_pszAreaCode = ClientAllocString( pszAreaCode ); if (m_pszAreaCode == NULL) { LOG(( TL_ERROR, "setAreaCode - alloc failed" )); hr = E_OUTOFMEMORY; } } m_bChanged = TRUE; return hr; } /**************************************************************************** Class : CLocation Method : SetLongDistanceCarrierCode ****************************************************************************/ STDMETHODIMP CLocation::SetLongDistanceCarrierCode(PWSTR pszLongDistanceCarrierCode) { HRESULT hr = S_OK; if (m_pszLongDistanceCarrierCode != NULL) { ClientFree(m_pszLongDistanceCarrierCode); m_pszLongDistanceCarrierCode = NULL; } if(pszLongDistanceCarrierCode != NULL) { m_pszLongDistanceCarrierCode = ClientAllocString( pszLongDistanceCarrierCode ); if (m_pszLongDistanceCarrierCode == NULL) { LOG(( TL_ERROR, "setLongDistanceCarrierCode - alloc failed" )); hr = E_OUTOFMEMORY; } } m_bChanged = TRUE; return hr; } /**************************************************************************** Class : CLocation Method : SetInternationalCarrierCode ****************************************************************************/ STDMETHODIMP CLocation::SetInternationalCarrierCode(PWSTR pszInternationalCarrierCode) { HRESULT hr = S_OK; if (m_pszInternationalCarrierCode != NULL) { ClientFree(m_pszInternationalCarrierCode); m_pszInternationalCarrierCode = NULL; } if(pszInternationalCarrierCode != NULL) { m_pszInternationalCarrierCode = ClientAllocString( pszInternationalCarrierCode ); if (m_pszInternationalCarrierCode == NULL) { LOG(( TL_ERROR, "setInternationalCarrierCode - alloc failed" )); hr = E_OUTOFMEMORY; } } m_bChanged = TRUE; return hr; } /**************************************************************************** Class : CLocation Method : setLongDistanceAccessCode ****************************************************************************/ STDMETHODIMP CLocation::SetLongDistanceAccessCode(PWSTR pszLongDistanceAccessCode) { HRESULT hr = S_OK; if (m_pszLongDistanceAccessCode != NULL) { ClientFree(m_pszLongDistanceAccessCode); m_pszLongDistanceAccessCode = NULL; } if(pszLongDistanceAccessCode != NULL) { m_pszLongDistanceAccessCode = ClientAllocString( pszLongDistanceAccessCode ); if (m_pszLongDistanceAccessCode == NULL) { LOG(( TL_ERROR, "setLongDistanceAccessCode - alloc failed" )); hr = E_OUTOFMEMORY; } } m_bChanged = TRUE; return hr; } /**************************************************************************** Class : CLocation Method : setLocalAccessCode ****************************************************************************/ STDMETHODIMP CLocation::SetLocalAccessCode(PWSTR pszLocalAccessCode) { HRESULT hr = S_OK; if (m_pszLocalAccessCode != NULL) { ClientFree(m_pszLocalAccessCode); m_pszLocalAccessCode = NULL; } if(pszLocalAccessCode != NULL) { m_pszLocalAccessCode = ClientAllocString( pszLocalAccessCode ); if (m_pszLocalAccessCode == NULL) { LOG(( TL_ERROR, "setLocalAccessCode - alloc failed" )); hr = E_OUTOFMEMORY; } } m_bChanged = TRUE; return hr; } /**************************************************************************** Class : CLocation Method : SetDisableCallWaitingCode ****************************************************************************/ STDMETHODIMP CLocation::SetDisableCallWaitingCode(PWSTR pszDisableCallWaitingCode) { HRESULT hr = S_OK; if (m_pszDisableCallWaitingCode != NULL) { ClientFree(m_pszDisableCallWaitingCode); m_pszDisableCallWaitingCode = NULL; } if(pszDisableCallWaitingCode != NULL) { m_pszDisableCallWaitingCode = ClientAllocString( pszDisableCallWaitingCode ); if (m_pszDisableCallWaitingCode == NULL) { LOG(( TL_ERROR, "SetDisableCallWaitingCodee - alloc failed" )); hr = E_OUTOFMEMORY; } } m_bChanged = TRUE; return hr; } /**************************************************************************** Class : CLocation Method : WriteToRegistry ****************************************************************************/ STDMETHODIMP CLocation::WriteToRegistry() { HRESULT hr = S_OK; DWORD dwTotalSizeNeeded = 0 ; DWORD dwSize=0, dwOffset = 0; PLOCATIONLIST pLocationList = NULL; PLOCATION pEntry = NULL; // static size dwTotalSizeNeeded = sizeof(LOCATIONLIST); dwSize = TapiSize(); dwTotalSizeNeeded += dwSize; // Allocate the memory buffer; pLocationList = (PLOCATIONLIST) ClientAlloc( dwTotalSizeNeeded ); if (pLocationList != NULL) { // buffer size pLocationList->dwTotalSize = dwTotalSizeNeeded; pLocationList->dwNeededSize = dwTotalSizeNeeded; pLocationList->dwUsedSize = dwTotalSizeNeeded; pLocationList->dwCurrentLocationID = 0; pLocationList->dwNumLocationsAvailable = 1; //list size & offset dwOffset = sizeof(LOCATIONLIST); pLocationList->dwNumLocationsInList = 1; pLocationList->dwLocationListSize = dwSize; pLocationList->dwLocationListOffset = dwOffset; // point to the location entry in list pEntry = (PLOCATION)(((LPBYTE)pLocationList) + dwOffset); // fill out structure TapiPack(pEntry, dwSize); WriteLocations( pLocationList, 0); // finished with TAPI memory block so release if ( pLocationList != NULL ) { ClientFree( pLocationList ); } } else { hr = E_OUTOFMEMORY; } return hr; } /**************************************************************************** Class : CLocation Method : RemoveRule ****************************************************************************/ void CLocation::RemoveRule(CAreaCodeRule *pRule) { AreaCodeRulePtrNode * node = m_AreaCodeRuleList.head(); while( !node->beyond_tail() ) { if ( pRule == node->value() ) { node->remove(); delete pRule; m_dwNumRules--; break; } node = node->next(); } m_bChanged = TRUE; } /**************************************************************************** Class : CLocation Method : ResetRules ****************************************************************************/ HRESULT CLocation::ResetRules(void) { m_hEnumNode = m_AreaCodeRuleList.head(); return S_OK; } /**************************************************************************** Class : CLocation Method : NextRule ****************************************************************************/ HRESULT CLocation::NextRule(DWORD NrElem, CAreaCodeRule **ppRule, DWORD *pNrElemFetched) { DWORD dwIndex = 0; if(pNrElemFetched == NULL && NrElem != 1) return E_INVALIDARG; if(ppRule==NULL) return E_INVALIDARG; while( !m_hEnumNode->beyond_tail() && dwIndexvalue(); m_hEnumNode = m_hEnumNode->next(); dwIndex++; } if(pNrElemFetched!=NULL) *pNrElemFetched = dwIndex; return dwIndexbeyond_tail() && dwIndexnext(); dwIndex++; } return dwIndexbeyond_tail() ) { // Add in size of each Area Code Rule pRule = node->value(); if (pRule != NULL) { dwSize += pRule->TapiSize(); } node = node->next(); } } else // no change so don't save this { dwSize = 0; } return dwSize; } /**************************************************************************** Class : CLocation Method : TapiPack Pack this object into a TAPI structure. Return number of bytes used. If the object has not changed while in memory, we won't save it so do mothing except return a zero size. ****************************************************************************/ DWORD CLocation::TapiPack(PLOCATION pLocation, DWORD dwTotalSize) { AreaCodeRulePtrNode * node; CAreaCodeRule * pRule = NULL; DWORD dwSize =0, dwOffSet =0; PAREACODERULE pEntry = NULL; if(m_bChanged) { m_bFromRegistry = TRUE; ///////////////////////////////////////////////////////////////////// // Process fized part of Location info dwOffSet = sizeof(LOCATION); pLocation->dwPermanentLocationID= m_dwLocationID; pLocation->dwCountryCode = m_dwCountryCode; pLocation->dwCountryID = m_dwCountryID; pLocation->dwPreferredCardID = m_dwPreferredCardID; pLocation->dwOptions = m_dwOptions; ///////////////////////////////////////////////////////////////////// // Process strings // name dwOffSet += TapiPackString((LPBYTE)pLocation, dwOffSet, dwTotalSize, m_pszLocationName, &pLocation->dwLocationNameOffset, &pLocation->dwLocationNameSize ); //area code dwOffSet += TapiPackString((LPBYTE)pLocation, dwOffSet, dwTotalSize, m_pszAreaCode, &pLocation->dwAreaCodeOffset, &pLocation->dwAreaCodeSize ); //LD carrier code dwOffSet += TapiPackString((LPBYTE)pLocation, dwOffSet, dwTotalSize, m_pszLongDistanceCarrierCode, &pLocation->dwLongDistanceCarrierCodeOffset, &pLocation->dwLongDistanceCarrierCodeSize ); //International carrier code dwOffSet += TapiPackString((LPBYTE)pLocation, dwOffSet, dwTotalSize, m_pszInternationalCarrierCode, &pLocation->dwInternationalCarrierCodeOffset, &pLocation->dwInternationalCarrierCodeSize ); //LD access dwOffSet += TapiPackString((LPBYTE)pLocation, dwOffSet, dwTotalSize, m_pszLongDistanceAccessCode, &pLocation->dwLongDistanceAccessCodeOffset, &pLocation->dwLongDistanceAccessCodeSize ); // Local access dwOffSet += TapiPackString((LPBYTE)pLocation, dwOffSet, dwTotalSize, m_pszLocalAccessCode, &pLocation->dwLocalAccessCodeOffset, &pLocation->dwLocalAccessCodeSize ); // CallWaiting dwOffSet += TapiPackString((LPBYTE)pLocation, dwOffSet, dwTotalSize, m_pszDisableCallWaitingCode, &pLocation->dwCancelCallWaitingOffset, &pLocation->dwCancelCallWaitingSize ); ///////////////////////////////////////////////////////////////////// // Process Area Code Rules pLocation->dwNumAreaCodeRules = m_dwNumRules; pLocation->dwAreaCodeRulesListOffset = dwOffSet; //pLocation->dwAreaCodeRulesListSize; // point to the 1st rule pEntry = (PAREACODERULE)(((LPBYTE)pLocation) + dwOffSet); //point strings past rule area dwOffSet += ALIGN(( sizeof(AREACODERULE) * m_dwNumRules )); // run through list node = m_AreaCodeRuleList.head(); while( !node->beyond_tail() ) { // Add in size of each Area Code Rule pRule = node->value(); if (pRule != NULL) { pEntry->dwOptions = pRule->GetOptions(); // Area code dwOffSet += TapiPackString((LPBYTE)pLocation, dwOffSet, dwTotalSize, pRule->GetAreaCode(), &pEntry->dwAreaCodeOffset, &pEntry->dwAreaCodeSize ); // num to Call dwOffSet += TapiPackString((LPBYTE)pLocation, dwOffSet, dwTotalSize, pRule->GetNumberToDial(), &pEntry->dwNumberToDialOffset, &pEntry->dwNumberToDialSize ); // prefix list dwSize = pRule->GetPrefixListSize(); pEntry->dwPrefixesListSize = dwSize; pEntry->dwPrefixesListOffset = dwOffSet; CopyMemory((PVOID)(((LPBYTE)pLocation) + dwOffSet), pRule->GetPrefixList() , dwSize); dwOffSet += ALIGN(dwSize); } node = node->next(); pEntry++; } // offset gives how many bytes we used pLocation->dwUsedSize = dwOffSet; } else // no change so don't save this { dwOffSet = 0; } return dwOffSet; } /**************************************************************************** Class : CLocation Method : NewID gets new ID from server ****************************************************************************/ HRESULT CLocation::NewID() { LONG lResult; DWORD dwId = 0; FUNC_ARGS funcArgs = { MAKELONG (LINE_FUNC | SYNC | 1, tAllocNewID), { (DWORD_PTR)&dwId }, { lpDword } }; // // Yes, let TAPISRV do it without danger of AV interruption from // another thread // lResult = DOFUNC (&funcArgs, "TAllocNewID"); if(lResult == 0) { m_dwLocationID = dwId; } return (HRESULT)lResult; } /**************************************************************************** Class : CLocation Method : GetCountryCode gets GetCountryCode from server ****************************************************************************/ DWORD CLocation::GetCountryCode() { CCountry * pCountry = NULL; if(SUCCEEDED( CreateCountryObject(m_dwCountryID, &pCountry)) ) { m_dwCountryCode = pCountry->GetCountryCode(); delete pCountry; } return m_dwCountryCode; } /**************************************************************************** Class : CLocation Method : TranslateAddress This is what its all there for, take a input number & figure out the dialable & display strings ****************************************************************************/ LONG CLocation::TranslateAddress(PCWSTR pszAddressIn, CCallingCard *pCallingCard, DWORD dwTranslateOptions, PDWORD pdwTranslateResults, PDWORD pdwDestCountryCode, PWSTR * pszDialableString, PWSTR * pszDisplayableString ) { PWSTR pszDialString = NULL; PWSTR pszDisplayString = NULL; PWSTR pszInputString = NULL; PWSTR pszRule = NULL; PWSTR pszDestLDRule = NULL; PWSTR pszCountry = NULL; PWSTR pszCity = NULL; PWSTR pszSubscriber = NULL; PWSTR pCardName = NULL; PWSTR pCardAccessNumber = NULL; PWSTR pCardAccountNumber = NULL; PWSTR pCardPINNumber = NULL; LONG lResult = 0; HRESULT hr= S_OK; CCountry * pCountry = NULL; CCountry * pDestCountry = NULL; DWORD dwAccess; DWORD dwDestCountryCode; BOOL bSpaceExists, bOutOfMem = FALSE; *pdwTranslateResults = 0; if(pdwDestCountryCode) *pdwDestCountryCode = 0; ////////////////////////////////////////////////////////////// // Allocate space for our strings // pszDialString = (PWSTR)ClientAlloc( MaxDialStringSize * sizeof(WCHAR) ); if (pszDialString == NULL) { LOG((TL_TRACE, "TranslateAddress DialString alloc failed")); return LINEERR_NOMEM; } pszDisplayString = (PWSTR)ClientAlloc( MaxDialStringSize * sizeof(WCHAR) ); if (pszDisplayString == NULL) { LOG((TL_TRACE, "TranslateAddress DisplayString alloc failed")); ClientFree(pszDialString); return LINEERR_NOMEM; } *pszDialableString = pszDialString; *pszDisplayableString = pszDisplayString; bSpaceExists = TRUE; // for suppressing a first space ////////////////////////////////////////////////////////////// // Copy the string to our local buffer so we can mangle it // pszInputString = ClientAllocString(pszAddressIn); if (pszInputString == NULL) { LOG((TL_TRACE, "TranslateAddress InputString alloc failed")); ClientFree(pszDialString); ClientFree(pszDisplayString); return LINEERR_NOMEM; } ////////////////////////////////////////////////////////////// // Mark off the end // // Isolate the piece of pszInputString that we will operate upon in // This piece stops at first CR or \0. // pszInputString[wcscspn(pszInputString,csSCANTO)] = L'\0'; //////////////////////////////// // Set T or P, if not set in input ////////////////////////////////////////////////////////////// // Easy case: first put the T or P in the beginning of the // dialable string // if ( HasToneDialing() ) { *pszDialString = L'T'; } else { *pszDialString = L'P'; } pszDialString++; ////////////////////////////////////////////////////////////// // Set Call Waiting //if location supports call Waiting AND (TranslateOptions | LINETRANSLATIONOPTION_CANCELCALLWAIT) if((dwTranslateOptions & LINETRANSLATEOPTION_CANCELCALLWAITING) && HasCallWaiting() ) { hr = StringCchCatExW(pszDialString, MaxDialStringSize, m_pszDisableCallWaitingCode, NULL, NULL, STRSAFE_NO_TRUNCATION); bOutOfMem = bOutOfMem && FAILED(hr); hr = StringCchCatExW(pszDisplayString, MaxDialStringSize, m_pszDisableCallWaitingCode, NULL, NULL, STRSAFE_NO_TRUNCATION); bOutOfMem = bOutOfMem && FAILED(hr); bSpaceExists = FALSE; } ////////////////////////////////////////////////////////////// // Now, do we have a canonical number to deal with, or is it junk? // if ( *pszInputString == L'+' ) // Check the real _first_ char { // // Ok, it's canonical // // // Skip the plus // lResult = BreakupCanonicalW( pszInputString + 1, &pszCountry, &pszCity, &pszSubscriber ); if (lResult == 0) { // It's canonical *pdwTranslateResults |= LINETRANSLATERESULT_CANONICAL; hr = CreateCountryObject(m_dwCountryID, &pCountry); if(SUCCEEDED( hr) ) { ////////////////////////////////////////////////////////////// // set LINETRANSLATERESULT result codes dwDestCountryCode = (DWORD)_wtol((const wchar_t*) pszCountry); if (dwDestCountryCode == pCountry->GetCountryCode() ) { // In country Call pszDestLDRule = pCountry->GetLongDistanceRule(); //if ( ( // CurrentCountry.LongDistanceRule.AreaCodes == Optional // OR CurrentCountry.LongDistanceRule.AreaCodes == Manditory && cityCode != NULL // ) // AND AreaCodeString != CurrentLocation.AreaCodeString ) if ( ( (IsCityRule(pszDestLDRule) == CITY_OPTIONAL) || ( (IsCityRule(pszDestLDRule) == CITY_MANDATORY) && (pszCity != NULL) ) ) && (!AreaCodeMatch(pszCity, m_pszAreaCode, pszDestLDRule)) ) { // Long Distance Call *pdwTranslateResults |= LINETRANSLATERESULT_LONGDISTANCE; } else // Local Call { *pdwTranslateResults |= LINETRANSLATERESULT_LOCAL; } } else // International Call { // find the LD rule of the destination country using the country code (we don't have the country ID) hr = CreateCountryObject(dwDestCountryCode, &pDestCountry); if(SUCCEEDED(hr)) { if ( pCountry->GetCountryGroup() != 0 && pCountry->GetCountryGroup() == pDestCountry->GetCountryGroup() ) { // if countries are in the same group, we need to // apply long distance rule instead of international *pdwTranslateResults |= LINETRANSLATERESULT_LONGDISTANCE; } else { *pdwTranslateResults |= LINETRANSLATERESULT_INTERNATIONAL; } pszDestLDRule = pDestCountry->GetLongDistanceRule(); } else { *pdwTranslateResults |= LINETRANSLATERESULT_INTERNATIONAL; // FALL THROUGH if error } } } if(SUCCEEDED( hr) ) { // If the caller needs the destination country code if(pdwDestCountryCode) *pdwDestCountryCode = dwDestCountryCode; ////////////////////////////////////////////////////////////// // Now we no what type of call, find the correct rule // Take in to account LINETRANSLATIONOPTION over-rides FindRule( *pdwTranslateResults, dwTranslateOptions, pCallingCard, pCountry, pszCity, pszSubscriber, &pszRule, &dwAccess ); ////////////////////////////////////////////////////////////// // Add access String to output string if (dwAccess == LOCAL) { hr = StringCchCatExW(pszDialString, MaxDialStringSize, m_pszLocalAccessCode, NULL, NULL, STRSAFE_NO_TRUNCATION); bOutOfMem = bOutOfMem && FAILED(hr); if(*m_pszLocalAccessCode) { if(!bSpaceExists) { hr = StringCchCatExW(pszDisplayString, MaxDialStringSize, L" ", NULL, NULL, STRSAFE_NO_TRUNCATION); bOutOfMem = bOutOfMem && FAILED(hr); } hr = StringCchCatExW(pszDisplayString, MaxDialStringSize, m_pszLocalAccessCode, NULL, NULL, STRSAFE_NO_TRUNCATION); bOutOfMem = bOutOfMem && FAILED(hr); bSpaceExists = FALSE; } } else // LONG_DISTANCE or INTERNATIONAL { hr = StringCchCatExW(pszDialString, MaxDialStringSize, m_pszLongDistanceAccessCode, NULL, NULL, STRSAFE_NO_TRUNCATION); bOutOfMem = bOutOfMem && FAILED(hr); if(*m_pszLongDistanceAccessCode) { if(!bSpaceExists) { hr = StringCchCatExW(pszDisplayString, MaxDialStringSize, L" ", NULL, NULL, STRSAFE_NO_TRUNCATION); bOutOfMem = bOutOfMem && FAILED(hr); } hr = StringCchCatExW(pszDisplayString, MaxDialStringSize, m_pszLongDistanceAccessCode, NULL, NULL, STRSAFE_NO_TRUNCATION); bOutOfMem = bOutOfMem && FAILED(hr); bSpaceExists = FALSE; } } ////////////////////////////////////////////////////////////// // If there's a card get its values if(pCallingCard != NULL) { switch(dwAccess) { case INTERNATIONAL: pCardAccessNumber = pCallingCard->GetInternationalAccessNumber(); break; case LONG_DISTANCE: LOG((TL_TRACE, "TranslateAddress: About to do pCallingCard->GetLongDistanceAccessNumber")); pCardAccessNumber = pCallingCard->GetLongDistanceAccessNumber(); LOG((TL_TRACE, "TranslateAddress: Did pCallingCard->GetLongDistanceAccessNumber")); break; default: pCardAccessNumber = pCallingCard->GetLocalAccessNumber(); break; } pCardName = pCallingCard->GetCardName(); pCardAccountNumber = pCallingCard->GetAccountNumber(); pCardPINNumber = pCallingCard->GetPIN(); } if(!bSpaceExists) { hr = StringCchCatExW(pszDisplayString, MaxDialStringSize, L" ", NULL, NULL, STRSAFE_NO_TRUNCATION); bOutOfMem = bOutOfMem && FAILED(hr); } ////////////////////////////////////////////////////////////// // Got the rule , now apply it if (ApplyRule (pszDialString, pszDisplayString, pszRule, pszDestLDRule, m_pszLongDistanceCarrierCode, m_pszInternationalCarrierCode, pszCountry, pszCity, pszSubscriber, pCardName, pCardAccessNumber, pCardAccountNumber, pCardPINNumber )) { bOutOfMem = TRUE; } else { // // Set LINETRANSLATERESULT_consts based on translation // results // if (wcschr (pszDialString, L'$')) { *pdwTranslateResults |= LINETRANSLATERESULT_DIALBILLING; } if (wcschr (pszDialString, L'W')) { *pdwTranslateResults |= LINETRANSLATERESULT_DIALDIALTONE; } if (wcschr (pszDialString, L'?')) { *pdwTranslateResults |= LINETRANSLATERESULT_DIALPROMPT; } if (wcschr (pszDialString, L'@')) { *pdwTranslateResults |= LINETRANSLATERESULT_DIALQUIET; } if (wcschr (pszDialString, L':')) { *pdwTranslateResults |= LINETRANSLATERESULT_VOICEDETECT; } } } else // bad country code { lResult = LINEERR_INVALCOUNTRYCODE; ClientFree(*pszDialableString); ClientFree(*pszDisplayableString); *pszDialableString = *pszDisplayableString = NULL; } if(pCountry) delete pCountry; if(pDestCountry) delete pDestCountry; } else // bad canonical address { lResult = LINEERR_INVALADDRESS; ClientFree(*pszDialableString); ClientFree(*pszDisplayableString); *pszDialableString = *pszDisplayableString = NULL; } } else // non-canonical string { PWSTR pszInputStringLocal = pszInputString; // if the string starts with T,P,t or p, skip the // first character. if (*pszInputString == L'T' || *pszInputString == L'P' || *pszInputString == L't' || *pszInputString == L'p') { pszInputStringLocal++; } hr = StringCchCatExW(pszDialString, MaxDialStringSize, pszInputStringLocal, NULL, NULL, STRSAFE_NO_TRUNCATION); bOutOfMem = bOutOfMem && FAILED(hr); hr = StringCchCatExW(pszDisplayString, MaxDialStringSize, pszInputString, NULL, NULL, STRSAFE_NO_TRUNCATION); bOutOfMem = bOutOfMem && FAILED(hr); } ///////////////////////////////////////////////////////////////////// // Clean up // if (bOutOfMem) { lResult = LINEERR_NOMEM; ClientFree(pszDialString); ClientFree(pszDisplayString); } if(pszInputString != NULL) { ClientFree(pszInputString); } return lResult; } /**************************************************************************** Class : CLocation Method : FindRule Decide which TAPI dial string rule to apply in dwTranslateResults dwTranslateOptions pCard pCountry AreaCodeString SubscriberString out ppRule dwAccess ****************************************************************************/ void CLocation::FindRule( DWORD dwTranslateResults, DWORD dwTranslateOptions, CCallingCard * pCard, CCountry * pCountry, PWSTR pszAreaCodeString, PWSTR pszSubscriberString, PWSTR * ppszRule, PDWORD dwAccess ) { CRuleSet * pCardRuleSet; CRuleSet * pCountryRuleSet; //if using Card if(pCard != NULL) { // Apply card rules pCardRuleSet = pCard->GetRuleSet(); LOG((TL_INFO, "FindRule - using (eventually) card %ls", pCard->GetCardName() )); } else { pCardRuleSet = NULL; } pCountryRuleSet = pCountry->GetRuleSet(); // use card rule if card is specified. If a specific rule is empty, fallback to country rule #define SUITABLE_RULE(x) \ ( (pCard && pCardRuleSet->x && *(pCardRuleSet->x) ) ? \ pCardRuleSet->x : pCountryRuleSet->x ) // Forced Long Distance Call if (dwTranslateOptions & LINETRANSLATEOPTION_FORCELD) { *dwAccess = LONG_DISTANCE; *ppszRule = SUITABLE_RULE(m_pszLongDistanceRule); LOG((TL_INFO, "FindRule - force long distance")); } // Force Local Call else if (dwTranslateOptions & LINETRANSLATEOPTION_FORCELOCAL) { *dwAccess = LOCAL; *ppszRule = SUITABLE_RULE(m_pszLocalRule); LOG((TL_INFO, "FindRule - force local")); } // International Call else if (dwTranslateResults & LINETRANSLATERESULT_INTERNATIONAL) { *dwAccess = INTERNATIONAL; *ppszRule = SUITABLE_RULE(m_pszInternationalRule); LOG((TL_INFO, "FindRule - international")); } // In Country, Long Distance Call or Local else { CAreaCodeRule * pCrtRule = NULL; AreaCodeRulePtrNode * pNode = NULL; PWSTR pszPrefix = NULL; DWORD dwNumMatchedDigits = 0; DWORD dwBestMatchedDigits = 0; DWORD dwBestThisRule = 0; BOOL bFoundApplicableRule = FALSE; BOOL bMatchThisRule = FALSE; BOOL bThisPrefixMatchThisRule = FALSE; // Enumerate the area code rules pNode = m_AreaCodeRuleList.head(); while( !pNode->beyond_tail() ) { pCrtRule = pNode->value(); if(pCrtRule!=NULL) { // does this rule match the area code we're calling ? if(AreaCodeMatch(pszAreaCodeString, pCrtRule->GetAreaCode(), pCountry->GetLongDistanceRule())) { LOG((TL_INFO, "FindRule - ACRule applies")); bMatchThisRule = FALSE; dwBestThisRule = 0; if( pCrtRule->HasAppliesToAllPrefixes() ) { bMatchThisRule = TRUE; dwNumMatchedDigits = 0; LOG((TL_INFO, "FindRule - there's a all prefix rule")); } else // is there a specific prefix rule ? { pszPrefix = pCrtRule->GetPrefixList(); while(*pszPrefix != '\0') { bThisPrefixMatchThisRule= PrefixMatch(pszPrefix, pszSubscriberString, &dwNumMatchedDigits); if(bThisPrefixMatchThisRule) { LOG((TL_INFO, "FindRule: there's a specific prefix rule %d digit match" ,dwNumMatchedDigits)); bMatchThisRule = TRUE; if(dwNumMatchedDigits > dwBestThisRule ) { dwBestThisRule= dwNumMatchedDigits; } } pszPrefix = wcschr( pszPrefix, '\0'); pszPrefix++; } } // have we got a better match than we've had before ? if(bMatchThisRule && (dwBestThisRule >= dwBestMatchedDigits) ) { // We have the best prefix match so far so use this rule dwBestMatchedDigits = dwBestThisRule; bFoundApplicableRule = TRUE; LOG((TL_INFO, "FindRule: going with the %d digit match" ,dwBestMatchedDigits)); *ppszRule = NULL; // Card overides, so if using Card if(pCard != NULL) { LOG((TL_INFO, "FindRule: card override (eventually)")); if ( pCrtRule->HasDialNumber() ) { *ppszRule = pCardRuleSet->m_pszLongDistanceRule; } else { *ppszRule = pCardRuleSet->m_pszLocalRule; } } if(!(*ppszRule && **ppszRule)) // build a tapirulestring for this rule entry // this might be necessary if the calling card has no suitable rule { if(m_pszTAPIDialingRule != NULL) { ClientFree(m_pszTAPIDialingRule); } if (S_OK == CreateDialingRule(&m_pszTAPIDialingRule, pCrtRule->HasDialNumber()?pCrtRule->GetNumberToDial():NULL, pCrtRule->HasDialAreaCode() )) { *ppszRule = m_pszTAPIDialingRule; LOG((TL_INFO, "FindRule: built a rule string - %ls",m_pszTAPIDialingRule)); } } // Set the correct access, based on the selected rule if ( pCrtRule->HasDialNumber() ) { *dwAccess = LONG_DISTANCE; } else { *dwAccess = LOCAL; } } // no better match } // no not calling this area code } pNode = pNode->next(); } // Did we have a match at all ? if(bFoundApplicableRule == FALSE) { // No area code rule matched, so go with country default rule if (dwTranslateResults & LINETRANSLATERESULT_LONGDISTANCE) { // long Distance *dwAccess = LONG_DISTANCE; *ppszRule = SUITABLE_RULE(m_pszLongDistanceRule); LOG((TL_TRACE, "FindRule - long distance default")); } else // Local { *dwAccess = LOCAL; *ppszRule = SUITABLE_RULE(m_pszLocalRule); LOG((TL_TRACE, "FindRule - local default")); } } } } #undef SUITABLE_RULE /* *************************************************************************** ********************* **************************** ******************** CLocations Class *************************** ******************** Definitions *************************** ********************* **************************** *************************************************************************** */ /**************************************************************************** Class : CLocations Method : Constructer ****************************************************************************/ CLocations::CLocations() { m_dwNumEntries = 0; m_hEnumNode = m_LocationList.head(); } /**************************************************************************** Class : CLocations Method : Destructer ****************************************************************************/ CLocations::~CLocations() { CLocationNode *node; node = m_LocationList.head(); while( !node->beyond_tail() ) { delete node->value(); node = node->next(); } m_LocationList.flush(); node = m_DeletedLocationList.head(); while( !node->beyond_tail() ) { delete node->value(); node = node->next(); } m_DeletedLocationList.flush(); } /**************************************************************************** Class : CLocations Method : Initialize Read the location list from registry via TAPISRV & build our object list. ****************************************************************************/ HRESULT CLocations::Initialize(void) { PLOCATIONLIST pLocationList = NULL; PLOCATION pEntry = NULL; PWSTR pszLocationName = NULL; PWSTR pszAreaCode = NULL; PWSTR pszLongDistanceCarrierCode = NULL; PWSTR pszInternationalCarrierCode = NULL; PWSTR pszLocalAccessCode = NULL; PWSTR pszLongDistanceAccessCode = NULL; PWSTR pszCancelCallWaitingCode = NULL; DWORD dwPermanentLocationID = 0; CLocation * pNewLocation = NULL; PAREACODERULE pAreaCodeRuleEntry = NULL; PWSTR pszNumberToDial = NULL; PWSTR pszzPrefixesList = NULL; DWORD dwNumRules = 0; CAreaCodeRule * pAreaCodeRule = NULL; DWORD dwNumEntries = 0; DWORD dwCount,dwCount2 = 0; HRESULT hr; hr = ReadLocations(&pLocationList, 0, 0, 0, 0 ); if SUCCEEDED( hr) { // current location m_dwCurrentLocationID = pLocationList->dwCurrentLocationID; // Find position of 1st LOCATION structure in the LOCATIONLIST structure pEntry = (PLOCATION) ((BYTE*)(pLocationList) + pLocationList->dwLocationListOffset ); // Number of locations ? dwNumEntries = pLocationList->dwNumLocationsInList; for (dwCount = 0; dwCount < dwNumEntries ; dwCount++) { // Pull Location Info out of LOCATION structure pszLocationName = (PWSTR) ((BYTE*)(pEntry) + pEntry->dwLocationNameOffset); pszAreaCode = (PWSTR) ((BYTE*)(pEntry) + pEntry->dwAreaCodeOffset); pszLongDistanceCarrierCode = (PWSTR) ((BYTE*)(pEntry) + pEntry->dwLongDistanceCarrierCodeOffset); pszInternationalCarrierCode = (PWSTR) ((BYTE*)(pEntry) + pEntry->dwInternationalCarrierCodeOffset); pszLocalAccessCode = (PWSTR) ((BYTE*)(pEntry) + pEntry->dwLocalAccessCodeOffset); pszLongDistanceAccessCode = (PWSTR) ((BYTE*)(pEntry) + pEntry->dwLongDistanceAccessCodeOffset); pszCancelCallWaitingCode = (PWSTR) ((BYTE*)(pEntry) + pEntry->dwCancelCallWaitingOffset); // create our new Location Object pNewLocation = new CLocation; if (pNewLocation) { // initialize the new Location Object hr = pNewLocation->Initialize( pszLocationName, pszAreaCode, pszLongDistanceCarrierCode, pszInternationalCarrierCode, pszLongDistanceAccessCode, pszLocalAccessCode, pszCancelCallWaitingCode , pEntry->dwPermanentLocationID, pEntry->dwCountryID, pEntry->dwPreferredCardID, pEntry->dwOptions, TRUE ); if( SUCCEEDED(hr) ) { // Find position of 1st AREACODERULE structure in the LOCATIONLIST structure pAreaCodeRuleEntry = (PAREACODERULE) ((BYTE*)(pEntry) + pEntry->dwAreaCodeRulesListOffset ); dwNumRules = pEntry->dwNumAreaCodeRules; for (dwCount2 = 0; dwCount2 != dwNumRules; dwCount2++) { // Pull Rule Info out of AREACODERULE structure pszAreaCode = (PWSTR) ((BYTE*)(pEntry) + pAreaCodeRuleEntry->dwAreaCodeOffset); pszNumberToDial = (PWSTR) ((BYTE*)(pEntry) + pAreaCodeRuleEntry->dwNumberToDialOffset); pszzPrefixesList = (PWSTR) ((BYTE*)(pEntry) + pAreaCodeRuleEntry->dwPrefixesListOffset); // create our new AreaCodeRule Object pAreaCodeRule = new CAreaCodeRule; if (pAreaCodeRule) { // initialize the new AreaCodeRule Object hr = pAreaCodeRule->Initialize ( pszAreaCode, pszNumberToDial, pAreaCodeRuleEntry->dwOptions, pszzPrefixesList, pAreaCodeRuleEntry->dwPrefixesListSize ); if( SUCCEEDED(hr) ) { pNewLocation->AddRule(pAreaCodeRule); } else // rule initialization failed { delete pAreaCodeRule; LOG((TL_ERROR, "Initialize: CreateCurrentLoctionObject - rule create failed")); } } else // new CAreaCodeRule failed { LOG((TL_ERROR, "CreateCurrentLoctionObject - rule create failed")); } // Try next rule in list pAreaCodeRuleEntry++; } Add(pNewLocation); } else // location initialize failed { delete pNewLocation; pNewLocation = NULL; LOG((TL_ERROR, "CreateCurrentLoctionObject - location create failed")); } } else // new CLocation failed { LOG((TL_ERROR, "CreateCurrentLoctionObject - location create failed")); } // Try next location in list //pEntry++; pEntry = (PLOCATION) ((BYTE*)(pEntry) + pEntry->dwUsedSize); } } else // ReadLocations failed { LOG((TL_ERROR, "CreateCurrentLoctionObject - ReadLocation create failed")); } // finished with TAPI memory block so release if ( pLocationList != NULL ) ClientFree( pLocationList ); return hr; } /**************************************************************************** Class : CLocations Method : SaveToRegistry Save object list back to registry via TAPISRV again ****************************************************************************/ HRESULT CLocations::SaveToRegistry(void) { HRESULT hr = S_OK; DWORD dwTotalSizeNeeded = 0, dwNumEntries= 0 ; DWORD dwSize=0, dwOffset = 0; CLocationNode * node = NULL; CLocation * pLocation = NULL; PLOCATIONLIST pLocationList = NULL; PLOCATION pEntry = NULL; // static size dwTotalSizeNeeded = sizeof(LOCATIONLIST); dwNumEntries = 0; // Now add in size of each Location (includes rules) node = m_LocationList.head(); while( !node->beyond_tail() ) { pLocation = node->value(); if (pLocation != NULL) { dwSize= pLocation->TapiSize(); dwTotalSizeNeeded += dwSize; if(dwSize) { // only save if dwSize >0, i.e. object has changed dwNumEntries++; } } node = node->next(); } // Now add in size of each deleted Location node = m_DeletedLocationList.head(); while( !node->beyond_tail() ) { pLocation = node->value(); if (pLocation != NULL) { dwSize= pLocation->TapiSize(); dwTotalSizeNeeded += dwSize; if(dwSize) { // only save if dwSize > 0, i.e. object has changed dwNumEntries++; } } node = node->next(); } // Allocate the memory buffer; pLocationList = (PLOCATIONLIST) ClientAlloc( dwTotalSizeNeeded ); if (pLocationList != NULL) { // buffer size pLocationList->dwTotalSize = dwTotalSizeNeeded; pLocationList->dwNeededSize = dwTotalSizeNeeded; pLocationList->dwUsedSize = dwTotalSizeNeeded; pLocationList->dwCurrentLocationID = m_dwCurrentLocationID; pLocationList->dwNumLocationsAvailable = dwNumEntries; //list size & offset dwOffset = sizeof(LOCATIONLIST); pLocationList->dwNumLocationsInList = dwNumEntries; pLocationList->dwLocationListSize = dwTotalSizeNeeded - sizeof(LOCATIONLIST); pLocationList->dwLocationListOffset = dwOffset; // Now add in each Location (includes rules) node = m_LocationList.head(); while( !node->beyond_tail() ) { // point to the location entry in list pEntry = (PLOCATION)(((LPBYTE)pLocationList) + dwOffset); pLocation = node->value(); if (pLocation != NULL) { // fill out structure dwOffset += pLocation->TapiPack(pEntry, dwTotalSizeNeeded - dwOffset); } node = node->next(); } // Now add in each deleted Location node = m_DeletedLocationList.head(); while( !node->beyond_tail() ) { // point to the location entry in list pEntry = (PLOCATION)(((LPBYTE)pLocationList) + dwOffset); pLocation = node->value(); if (pLocation != NULL) { // fill out structure dwOffset += pLocation->TapiPack(pEntry, dwTotalSizeNeeded - dwOffset); } node = node->next(); } WriteLocations( pLocationList,CHANGEDFLAGS_CURLOCATIONCHANGED); // finished with TAPI memory block so release if ( pLocationList != NULL ) { ClientFree( pLocationList ); } } else { hr = E_OUTOFMEMORY; } return hr; } /**************************************************************************** Class : CLocations Method : Remove (with CLocation *) If location object was read from the registry we must keep it around so we can remove its entry when writing back to the registry. If it only existed in memory we can just delete it. ****************************************************************************/ void CLocations::Remove(CLocation * pLocation) { CLocationNode *node = m_LocationList.head(); while( !node->beyond_tail() ) { if ( pLocation == node->value() ) { node->remove(); m_dwNumEntries--; pLocation->Changed(); if( pLocation->FromRegistry() ) { // set name to null so server knows to delete it pLocation->SetName(NULL); m_DeletedLocationList.tail()->insert_after(pLocation); } else { delete pLocation; } break; } node = node->next(); } } /**************************************************************************** Class : CLocations Method : Remove (with DWORD) If location object was read from the registry we must keep it around so we can remove its entry when writing back to the registry. If it only existed in memory we can just delete it. ****************************************************************************/ void CLocations::Remove(DWORD dwID) { CLocationNode *node = m_LocationList.head(); CLocation *pLocation; while( !node->beyond_tail() ) { if ( dwID == node->value()->GetLocationID() ) { pLocation = node->value(); node->remove(); m_dwNumEntries--; pLocation->Changed(); if( pLocation->FromRegistry() ) { // set name to null so server knows to delete it pLocation->SetName(NULL); m_DeletedLocationList.tail()->insert_after(pLocation); } else { delete pLocation; } break; } node = node->next(); } } /**************************************************************************** Class : CLocations Method : Replace Replace pLocOld with pLocNew. These locations must have the same location ID. ****************************************************************************/ void CLocations::Replace(CLocation * pLocOld, CLocation * pLocNew) { if ( pLocOld->GetLocationID() != pLocNew->GetLocationID() ) { LOG((TL_ERROR, "Replace: Illegal")); return; } CLocationNode *node = m_LocationList.head(); while( !node->beyond_tail() ) { if ( pLocOld == node->value() ) { // node->remove(); // m_LocationList.tail()->insert_after(pLocNew); node->value() = pLocNew; delete pLocOld; break; } node = node->next(); } } /**************************************************************************** Class : CLocations Method : Add Put it in the list ****************************************************************************/ void CLocations::Add(CLocation * pLocation) { m_LocationList.tail()->insert_after(pLocation); m_dwNumEntries++; } /**************************************************************************** Class : CLocations Method : Reset Set enumerator to start ****************************************************************************/ HRESULT CLocations::Reset(void) { m_hEnumNode = m_LocationList.head(); return S_OK; } /**************************************************************************** Class : CLocations Method : Next get next location in list ****************************************************************************/ HRESULT CLocations::Next(DWORD NrElem, CLocation **ppLocation, DWORD *pNrElemFetched) { DWORD dwIndex = 0; if(pNrElemFetched == NULL && NrElem != 1) return E_INVALIDARG; if(ppLocation==NULL) return E_INVALIDARG; while( !m_hEnumNode->beyond_tail() && dwIndexvalue(); m_hEnumNode = m_hEnumNode->next(); dwIndex++; } if(pNrElemFetched!=NULL) *pNrElemFetched = dwIndex; return dwIndexbeyond_tail() && dwIndexnext(); dwIndex++; } return dwIndexbeyond_tail() ) { delete node->value(); node = node->next(); } m_CountryList.flush(); } /**************************************************************************** Class : CCountries Method : Initialize Read the countries list from registry via TAPISRV & build our object list. ****************************************************************************/ HRESULT CCountries::Initialize(void) { LPLINECOUNTRYLIST_INTERNAL pCountryList = NULL; LPLINECOUNTRYENTRY_INTERNAL pEntry = NULL; PWSTR pszCountryName = NULL; PWSTR pszInternationalRule = NULL; PWSTR pszLongDistanceRule = NULL; PWSTR pszLocalRule = NULL; CCountry * pCountry = NULL; DWORD dwCount = 0; DWORD dwNumEntries = 0; LONG lResult; HRESULT hr; lResult = ReadCountriesAndGroups( &pCountryList, 0, 0); if (lResult == 0) { // Find position of 1st LINECOUNTRYENTRY structure in the LINECOUNTRYLIST structure pEntry = (LPLINECOUNTRYENTRY_INTERNAL) ((BYTE*)(pCountryList) + pCountryList->dwCountryListOffset ); dwNumEntries = pCountryList->dwNumCountries; for (dwCount = 0; dwCount < dwNumEntries ; dwCount++) { // Pull Country Info out of LINECOUNTRYENTRY structure pszCountryName = (PWSTR) ((BYTE*)(pCountryList) + pEntry->dwCountryNameOffset); pszInternationalRule = (PWSTR) ((BYTE*)(pCountryList) + pEntry->dwInternationalRuleOffset); pszLongDistanceRule = (PWSTR) ((BYTE*)(pCountryList) + pEntry->dwLongDistanceRuleOffset); pszLocalRule = (PWSTR) ((BYTE*)(pCountryList) + pEntry->dwSameAreaRuleOffset); // create our new CCountry Object pCountry = new CCountry; if (pCountry) { // initialize the new CCountry Object hr = pCountry->Initialize(pEntry->dwCountryID, pEntry->dwCountryCode, pEntry->dwCountryGroup, pszCountryName, pszInternationalRule, pszLongDistanceRule, pszLocalRule ); if( SUCCEEDED(hr) ) { m_CountryList.tail()->insert_after(pCountry); m_dwNumEntries++; } else // country initialization failed { delete pCountry; LOG((TL_ERROR, "Initialize - country create failed")); } } else // new CCountry failed { LOG((TL_ERROR, "Initialize - country create failed")); } // Try next country in list pEntry++; } } else // ReadLocations failed { LOG((TL_ERROR, "Initialize - ReadCountries failed")); hr = (HRESULT)lResult; } // finished with TAPI memory block so release if ( pCountryList != NULL ) { ClientFree( pCountryList ); } return hr; } /**************************************************************************** Class : CCountries Method : Reset ****************************************************************************/ HRESULT CCountries::Reset(void) { m_hEnumNode = m_CountryList.head(); return S_OK; } /**************************************************************************** Class : CCountries Method : Next ****************************************************************************/ HRESULT CCountries::Next(DWORD NrElem, CCountry **ppCcountry, DWORD *pNrElemFetched) { DWORD dwIndex = 0; if(pNrElemFetched == NULL && NrElem != 1) return E_INVALIDARG; if(ppCcountry==NULL) return E_INVALIDARG; while( !m_hEnumNode->beyond_tail() && dwIndexvalue(); m_hEnumNode = m_hEnumNode->next(); dwIndex++; } if(pNrElemFetched!=NULL) *pNrElemFetched = dwIndex; return dwIndexbeyond_tail() && dwIndexnext(); dwIndex++; } return dwIndex