// Copyright (c) 1996, Microsoft Corporation, all rights reserved // // phonenum.c // Phone number helper library // Listed alphabetically // // 03/06/96 Steve Cobb #include // Win32 root #include // No-HWND utilities #include // TAPI wrappers #include // Our public header #include // Trace/Assert library TCHAR* LinkPhoneNumberFromParts( IN HINSTANCE hInst, IN OUT HLINEAPP* pHlineapp, IN PBUSER* pUser, IN PBENTRY* pEntry, IN PBLINK* pLink, IN DWORD iPhoneNumber, IN TCHAR* pszOverrideNumber, IN BOOL fDialable ) // Like PhoneNumberFromParts but takes a link and hunt group index as // input instead of a base number, and handles not modifying the number // associated with non-modem/ISDN links. If 'pszOverrideNumber' is // non-NULL and non-"" it is used instead of the derived number. // { DTLNODE* pNode; TCHAR* pszBaseNumber; PBPHONE* pPhone; if (pszOverrideNumber && *pszOverrideNumber) { // So, this is useful? RaoS? // return StrDup( pszOverrideNumber ); } pNode = DtlNodeFromIndex( pLink->pdtllistPhones, iPhoneNumber ); if (!pNode) { ASSERT( FALSE ); return NULL; } pPhone = (PBPHONE *) DtlGetData(pNode); ASSERT( pPhone ); if (pLink->pbport.pbdevicetype == PBDT_Modem || pLink->pbport.pbdevicetype == PBDT_Isdn) { BOOL fDownLevelIsdn; fDownLevelIsdn = (pLink->pbport.pbdevicetype == PBDT_Isdn && pLink->fProprietaryIsdn); return PhoneNumberFromParts( hInst, pHlineapp, pUser, pPhone, fDownLevelIsdn, fDialable ); } else { return StrDup( pPhone->pszPhoneNumber ); } } TCHAR* PhoneNumberFromParts( IN HINSTANCE hInst, IN OUT HLINEAPP* pHlineapp, IN PBUSER* pUser, IN PBPHONE* pPhone, IN BOOL fDownLevelIsdn, IN BOOL fDialable ) // Returns a heap block containing the composite phone number using the // rules of 'pPhone' and 'pUser'. 'HInst' is the module handle. // 'PHlineapp' is the TAPI context. 'FDialable' indicates the dialable // string, instead of the displayable string, should be returned. // // It is caller's responsibility to Free the returned string. // { TCHAR* pszResult; TCHAR* pszBaseNumber; TRACE( "PhoneNumberFromParts" ); pszBaseNumber = pPhone->pszPhoneNumber; if (!pszBaseNumber) { pszBaseNumber = TEXT(""); } if (pPhone->fUseDialingRules) { pszResult = PhoneNumberFromTapiPartsEx( hInst, pszBaseNumber, pPhone->pszAreaCode, pPhone->dwCountryCode, fDownLevelIsdn, pHlineapp, fDialable ); } else { TCHAR* pszPrefix; TCHAR* pszSuffix; PrefixSuffixFromLocationId( pUser, GetCurrentLocation( hInst, pHlineapp ), &pszPrefix, &pszSuffix ); pszResult = PhoneNumberFromPrefixSuffixEx( pszBaseNumber, pszPrefix, pszSuffix, fDownLevelIsdn ); Free0( pszPrefix ); Free0( pszSuffix ); } if (!pszResult) { TRACE( "!Phone#" ); pszResult = StrDup( pszBaseNumber ); } return pszResult; } TCHAR* PhoneNumberFromPrefixSuffix( IN TCHAR* pszBaseNumber, IN TCHAR* pszPrefix, IN TCHAR* pszSuffix ) // Returns a heap block containing the composite phone number comprised of // prefix 'pszPrefix', base phone number 'pszBaseNumber', and suffix // 'pszSuffix', or NULL if the composite number is too long or on a memory // error. // // It is caller's responsibility to Free the returned string. // { TCHAR* pszResult; DWORD cch; TRACE( "PhoneNumberFromPrefixSuffix" ); pszResult = NULL; if (!pszBaseNumber) { pszBaseNumber = TEXT(""); } if (!pszPrefix) { pszPrefix = TEXT(""); } if (!pszSuffix) { pszSuffix = TEXT(""); } cch = lstrlen( pszPrefix ) + lstrlen( pszBaseNumber ) + lstrlen( pszSuffix ); if (cch > RAS_MaxPhoneNumber) { return NULL; } pszResult = Malloc( (cch + 1) * sizeof(TCHAR) ); if (pszResult) { *pszResult = TEXT('\0'); lstrcat( pszResult, pszPrefix ); lstrcat( pszResult, pszBaseNumber ); lstrcat( pszResult, pszSuffix ); } return pszResult; } TCHAR* PhoneNumberFromPrefixSuffixEx( IN TCHAR* pszBaseNumber, IN TCHAR* pszPrefix, IN TCHAR* pszSuffix, IN BOOL fDownLevelIsdn ) // Returns a heap block containing the composite phone number comprised of // prefix 'pszPrefix', base phone number 'pszBaseNumber', and suffix // 'pszSuffix', or NULL if the composite number is too long or on a memory // error. // // If 'fDownLevelIsdn' is set colons are recognized as separaters with // each colon separated token built treated separately. // // It is caller's responsibility to Free the returned string. // { TCHAR* psz; TCHAR* pszResult; INT cchResult; TRACE( "PhoneNumberFromPrefixSuffixEx" ); if (fDownLevelIsdn) { TCHAR* pszNum; TCHAR* pszS; TCHAR* pszE; pszResult = StrDup( TEXT("") ); for (pszS = pszE = pszBaseNumber; *pszE != TEXT('\0'); pszE = CharNext( pszE )) { if (*pszE == TEXT(':')) { *pszE = TEXT('\0'); pszNum = PhoneNumberFromPrefixSuffix( pszS, pszPrefix, pszSuffix ); *pszE = TEXT(':'); if (pszNum) { if (pszResult) cchResult = lstrlen( pszResult ); psz = Realloc( pszResult, (cchResult + lstrlen( pszNum ) + 2) * sizeof(TCHAR) ); if (!psz) { Free0( pszResult ); Free( pszNum ); return NULL; } pszResult = psz; lstrcat( pszResult, pszNum ); lstrcat( pszResult, TEXT(":") ); Free( pszNum ); } pszS = CharNext( pszE ); } } { pszNum = PhoneNumberFromPrefixSuffix( pszS, pszPrefix, pszSuffix ); if (pszNum) { if (pszResult) cchResult = lstrlen( pszResult ); psz = Realloc( pszResult, (cchResult + lstrlen( pszNum ) + 1) * sizeof(TCHAR) ); if (!psz) { Free0( pszResult ); Free( pszNum ); return NULL; } pszResult = psz; lstrcat( pszResult, pszNum ); Free( pszNum ); } } } else { pszResult = PhoneNumberFromPrefixSuffix( pszBaseNumber, pszPrefix, pszSuffix ); } if (pszResult && (lstrlen( pszResult ) > RAS_MaxPhoneNumber )) { Free( pszResult ); return NULL; } return pszResult; } TCHAR* PhoneNumberFromTapiParts( IN HINSTANCE hInst, IN TCHAR* pszBaseNumber, IN TCHAR* pszAreaCode, IN DWORD dwCountryCode, IN OUT HLINEAPP* pHlineapp, IN BOOL fDialable ) // Returns a heap block containing the composite phone number comprised of // base phone number 'pszBaseNumber', area code 'pszAreaCode', and country // code 'dwCountryCode, or NULL if the composite number is too long or on // a memory error. 'HInst' is the module instance handle. '*PHlineapp' // is the address of the TAPI context. 'FDialable' indicates the dialable // string, as opposed to the displayable string, should be returned. // // It is caller's responsibility to Free the returned string. // { TCHAR* pszResult; TRACE( "PhoneNumberFromTapiParts" ); pszResult = NULL; TapiTranslateAddress( hInst, pHlineapp, dwCountryCode, pszAreaCode, pszBaseNumber, 0, fDialable, &pszResult ); return pszResult; } TCHAR* PhoneNumberFromTapiPartsEx( IN HINSTANCE hInst, IN TCHAR* pszBaseNumber, IN TCHAR* pszAreaCode, IN DWORD dwCountryCode, IN BOOL fDownLevelIsdn, IN OUT HLINEAPP* pHlineapp, IN BOOL fDialable ) // Returns heap block containing the composite phone number comprised of // base phone number 'pszBaseNumber', area code 'pszAreaCode', and country // code 'dwCountryCode or NULL if the composite number is too long or on a // memory error. 'HInst' is the module instance handle. '*PHlineapp' is // the address of the TAPI context. 'FDialable' indicates the dialable // string, as opposed to the displayable string, should be returned. // // If 'fDownLevelIsdn' is set colons are recognized as separaters with // each colon separated token built treated separately. // // It is caller's responsibility to Free the returned string. // { TCHAR* psz; TCHAR* pszResult; INT cchResult; TRACE( "PhoneNumberFromTapiPartsEx" ); if (fDownLevelIsdn) { TCHAR* pszNum; TCHAR* pszS; TCHAR* pszE; pszResult = StrDup( TEXT("") ); for (pszS = pszE = pszBaseNumber; *pszE != TEXT('\0'); pszE = CharNext( pszE )) { if (*pszE == TEXT(':')) { *pszE = TEXT('\0'); pszNum = PhoneNumberFromTapiParts( hInst, pszS, pszAreaCode, dwCountryCode, pHlineapp, fDialable ); *pszE = TEXT(':'); if (pszNum) { if (pszResult) { cchResult = lstrlen( pszResult ); } psz = Realloc( pszResult, (cchResult + lstrlen( pszNum ) + 2) * sizeof(TCHAR) ); if (!psz) { Free0( pszResult ); Free( pszNum ); return NULL; } pszResult = psz; lstrcat( pszResult, pszNum ); lstrcat( pszResult, TEXT(":") ); Free( pszNum ); } pszS = CharNext( pszE ); } } { pszNum = PhoneNumberFromTapiParts( hInst, pszS, pszAreaCode, dwCountryCode, pHlineapp, fDialable ); if (pszNum) { if (pszResult) { cchResult = lstrlen( pszResult ); } psz = Realloc( pszResult, (cchResult + lstrlen( pszNum ) + 1) * sizeof(TCHAR) ); if (!psz) { Free0( pszResult ); Free( pszNum ); return NULL; } pszResult = psz; lstrcat( pszResult, pszNum ); Free( pszNum ); } } } else { pszResult = PhoneNumberFromTapiParts( hInst, pszBaseNumber, pszAreaCode, dwCountryCode, pHlineapp, fDialable ); } if (pszResult && (lstrlen( pszResult ) > RAS_MaxPhoneNumber )) { Free( pszResult ); return NULL; } return pszResult; } VOID PrefixSuffixFromLocationId( IN PBUSER* pUser, IN DWORD dwLocationId, OUT TCHAR** ppszPrefix, OUT TCHAR** ppszSuffix ) // Retrieve the prefix and suffix strings, '*ppszPrefix' and '*ppszSuffix' // associated with TAPI location 'dwLocationId'. 'PUser' is the user // preferences from which to retrieve. // // It is caller's responsibility to Free the returned strings. // { #if 0 // NT4-style DTLNODE* pNode; INT iPrefix; INT iSuffix; TRACE( "PrefixSuffixFromLocationId" ); iPrefix = iSuffix = 0; for (pNode = DtlGetFirstNode( pUser->pdtllistLocations ); pNode; pNode = DtlGetNextNode( pNode )) { LOCATIONINFO* p = (LOCATIONINFO* )DtlGetData( pNode ); ASSERT( p ); if (p->dwLocationId == dwLocationId) { iPrefix = p->iPrefix; iSuffix = p->iSuffix; break; } } *ppszPrefix = NULL; if (iPrefix != 0) { pNode = DtlNodeFromIndex( pUser->pdtllistPrefixes, iPrefix - 1 ); if (pNode) { *ppszPrefix = StrDup( (TCHAR* )DtlGetData( pNode ) ); } } *ppszSuffix = NULL; if (iSuffix != 0) { pNode = DtlNodeFromIndex( pUser->pdtllistSuffixes, iSuffix - 1 ); if (pNode) { *ppszSuffix = StrDup( (TCHAR* )DtlGetData( pNode ) ); } } #else // Stubbed in NT5/Connections *ppszPrefix = StrDup( TEXT("") ); *ppszSuffix = StrDup( TEXT("") ); #endif }