|
|
/*
- util.c - * Microsoft At Work Fax Messaging Address Book * * Revision History: * * When Who What * -------- ------------------ --------------------------------------- * 7.24.96 Rick Turner ported from old code in fax tree * */ /* ***************************************************************************/
/* inculde files */
#include "faxab.h"
/*******************************
**** Utility Functions **** *******************************/
// ***************************************************************************
// GetCurrentLocationAreaCode *
// Get the area code for the current location *
// returns: the area code of the current location or "" if error *
//
TCHAR g_szAreaCode[ AREA_CODE_SIZE ]; DWORD g_dwTlsIndex; // index for private thread storage
LPTSTR GetCurrentLocationAreaCode() { LPLINETRANSLATECAPS lpLineTransCaps; DWORD lResult, dwNumLocs; LPLINELOCATIONENTRY lplle, lplleCur;
g_szAreaCode[0] = 0;
/* allocate buffer */ lpLineTransCaps = (LPLINETRANSLATECAPS)LocalAlloc(LPTR, 1024 ); if (!lpLineTransCaps) { goto err; }
lpLineTransCaps->dwTotalSize = 1024;
/* try to get TranslateCaps */ lResult = lineGetTranslateCaps( NULL, TAPI_CURRENT_VERSION, lpLineTransCaps); if (lResult != NO_ERROR) { goto err; }
/* reallocate buffer if not big enough */ while (lpLineTransCaps->dwNeededSize > lpLineTransCaps->dwTotalSize) { DWORD lcbNeeded = lpLineTransCaps->dwNeededSize;
LocalFree(lpLineTransCaps); lpLineTransCaps = (LPLINETRANSLATECAPS)LocalAlloc(LPTR, lcbNeeded); if (!lpLineTransCaps) { goto err; }
lpLineTransCaps->dwTotalSize = lcbNeeded;
/* try one more time */ lResult = lineGetTranslateCaps( NULL, TAPI_CURRENT_VERSION, lpLineTransCaps); if (lResult != NO_ERROR) { goto err; } } /* while */
dwNumLocs = lpLineTransCaps->dwNumLocations;
// get the name and area code of the current location
lplle = (LPLINELOCATIONENTRY)((LPBYTE)(lpLineTransCaps) + lpLineTransCaps->dwLocationListOffset); lplleCur = lplle; while (dwNumLocs-- && lplleCur->dwPermanentLocationID != lpLineTransCaps->dwCurrentLocationID) ++lplleCur;
// Save the current location information
lstrcpyn( g_szAreaCode, (LPTSTR)((LPBYTE)(lpLineTransCaps) + lplleCur->dwCityCodeOffset), min(ARRAYSIZE(g_szAreaCode),lplleCur->dwCityCodeSize) );
LocalFree( lpLineTransCaps ); return g_szAreaCode;
err: if (lpLineTransCaps != NULL) LocalFree(lpLineTransCaps);
return NULL;
} /* GetCurrentLocationAreaCode */
// ***************************************************************************
// GetCurrentLocationCountryID *
// Get the area code for the current location *
// returns: the country ID for the current location or 0 if error
//
DWORD GetCurrentLocationCountryID() { LPLINETRANSLATECAPS lpLineTransCaps; DWORD lResult, dwNumLocs, dwCountryID; LPLINELOCATIONENTRY lplle, lplleCur;
/* allocate buffer */ lpLineTransCaps = (LPLINETRANSLATECAPS)LocalAlloc(LPTR, 1024 ); if (!lpLineTransCaps) { goto err; }
lpLineTransCaps->dwTotalSize = 1024;
/* try to get TranslateCaps */ lResult = lineGetTranslateCaps( NULL, TAPI_CURRENT_VERSION, lpLineTransCaps); if (lResult != NO_ERROR) { goto err; }
/* reallocate buffer if not big enough */ while (lpLineTransCaps->dwNeededSize > lpLineTransCaps->dwTotalSize) { DWORD lcbNeeded = lpLineTransCaps->dwNeededSize;
LocalFree(lpLineTransCaps); lpLineTransCaps = (LPLINETRANSLATECAPS)LocalAlloc(LPTR, lcbNeeded); if (!lpLineTransCaps) { goto err; }
lpLineTransCaps->dwTotalSize = lcbNeeded;
/* try one more time */ lResult = lineGetTranslateCaps( NULL, TAPI_CURRENT_VERSION, lpLineTransCaps); if (lResult != NO_ERROR) { goto err; } } /* while */
dwNumLocs = lpLineTransCaps->dwNumLocations;
// get the name and area code of the current location
lplle = (LPLINELOCATIONENTRY)((LPBYTE)(lpLineTransCaps) + lpLineTransCaps->dwLocationListOffset); lplleCur = lplle; while (dwNumLocs-- && lplleCur->dwPermanentLocationID != lpLineTransCaps->dwCurrentLocationID) ++lplleCur;
dwCountryID = lplleCur->dwCountryID;
LocalFree( lpLineTransCaps ); return dwCountryID;
err: if (lpLineTransCaps != NULL) LocalFree(lpLineTransCaps);
return 0;
} /* GetCurrentLocationCountryID */
/* ***************************************************************************
* GetCountry * * - gets the a country or a country list from TAPI * * Parameters: dwReqCountryID - a TAPI country ID. 0 for all countries * * Returns: TRUE on success, FALSE on failure. */
#define SIZE_OF_ONE_COUNTRY_BUFFER 150 // current number is 110
#define SIZE_OF_ALL_COUNTRIES_BUFFER 17000 // current number is 15694
BOOL GetCountry(DWORD dwReqCountryID, LPLINECOUNTRYLIST *lppLineCountryList) { ULONG ulMemNeeded; WORD i; LONG lError = NO_ERROR; LPLINECOUNTRYLIST lpLineCountryList = NULL; BOOL bResult = TRUE;
// See what size of a buffer I need to allocate
ulMemNeeded = (dwReqCountryID ? SIZE_OF_ONE_COUNTRY_BUFFER : SIZE_OF_ALL_COUNTRIES_BUFFER);
// Try to allocate buffer and call lineGetCountry twice
// If this does not work, allocate a buffer of the size
// requested by TAPI and try again
for (i=0; i < 2; i++) { // Allocate memory for the LINECOUNTRYLIST structure
lpLineCountryList = (LPLINECOUNTRYLIST)LocalAlloc( LPTR, ulMemNeeded ); if (!lpLineCountryList) { DEBUG_TRACE("GetCountry: could not alloc buffer(%d) for LPLINECOUNTRYLIST\n", i); goto err; }
// Set the size of the provided buffer for TAPI
lpLineCountryList->dwTotalSize = ulMemNeeded;
// Get the country inofmration for the requested country
lError = lineGetCountry(dwReqCountryID, TAPI_CURRENT_VERSION, lpLineCountryList);
// I give up if error and it's not because the structure passed in was too small
if ( (lError != NO_ERROR) && (lError != LINEERR_STRUCTURETOOSMALL) && // Remove next line after TAPI fixes bug
(lError != LINEERR_NOMEM) ) { DEBUG_TRACE("GetCountry: lineGetCountry returned error %lx\n", lError); goto err; }
// If I didn't get it all, free the buffer and try again with bigger size buffer
if (lpLineCountryList->dwNeededSize > lpLineCountryList->dwTotalSize) { // +1 is due to TAPI bug. Exactly won't work
ulMemNeeded = lpLineCountryList->dwNeededSize+1; LocalFree(lpLineCountryList); } else // got it
break; }
// should have valid lpLineCountryList here
if (lError != NO_ERROR) goto err;
DEBUG_TRACE("GetCountry: %lx of the buffer used\n", lpLineCountryList->dwUsedSize);
out: *lppLineCountryList = lpLineCountryList; return bResult;
err: // Free the buffer
if (lpLineCountryList) LocalFree( lpLineCountryList ); lpLineCountryList = NULL; bResult = FALSE; goto out;
} /* GetCountry */
/* ***************************************************************************
* GetCountryCode * * - gets a country code when given a country ID * * Parameters: dwReqCountryID - a TAPI country ID * lpdwCountryCode - an address of a DWORD in which to store the country code * * Returns: TRUE on success, FALSE on failure. */
BOOL GetCountryCode(DWORD dwReqCountryID, DWORD *lpdwCountryCode) { ULONG country; LPLINECOUNTRYLIST lpLineCountryList = NULL; LPLINECOUNTRYENTRY lprgLineCountryEntry = NULL; BOOL bResult = FALSE;
// Get the country info structure from TAPI
if (!GetCountry(dwReqCountryID, &lpLineCountryList)) goto out;
// Point to the first country in the structure
lprgLineCountryEntry = (LPLINECOUNTRYENTRY)((LPBYTE)(lpLineCountryList) + lpLineCountryList->dwCountryListOffset);
// Loop through LINECOUNTRYENTRY structures and look for the country ID.
for (country=0; country < lpLineCountryList->dwNumCountries; country++) if ( (lprgLineCountryEntry[country].dwCountryNameSize != 0) && (lprgLineCountryEntry[country].dwCountryNameOffset != 0) ) { DWORD dwCountryCode = lprgLineCountryEntry[country].dwCountryCode; DWORD dwCountryID = lprgLineCountryEntry[country].dwCountryID;
// If this is the requested country, get its country code
if (dwCountryID == dwReqCountryID) { *lpdwCountryCode = dwCountryCode; bResult = TRUE; break; }
}
out: // Free the buffer
if (lpLineCountryList) LocalFree( lpLineCountryList );
if (!bResult) *lpdwCountryCode = 1; // U.S.
return bResult;
} /* GetCountryCode */
/****************************************************************************
FUNCTION: MakeMessageBox
PURPOSE: Gets resource string and displays an error message box.
PARAMETERS: hInst - Instnace of the caller (for getting strings) hWnd - Handle to parent window ulResult - Result/Status code 0: information message 100-499: warning message 500 and up: error message idString - Resource ID of message in StringTable fStyle - style of the message box
RETURNS: the return value from MessageBox() function
****************************************************************************/ int MakeMessageBox(HINSTANCE hInst, HWND hWnd, DWORD ulResult, UINT idString, UINT fStyle, ...) { va_list va; TCHAR szMessage[512]=TEXT(""); TCHAR szTempBuf[400]; TCHAR szTitle[128]; TCHAR szAppName[MAX_PATH];
// Get the application name from the resource file
LoadString (hInst, IDS_APP_NAME, szAppName, MAX_PATH);
// Do the title: 0: information message, 100-499: warning, 500 and up: critical (real error)
// Also, if an error msg, load the standard MAWF error message
if (ulResult == 0) { lstrcpy(szMessage, TEXT("")); LoadString (hInst, IDS_INFORMATION_MESSAGE, szTempBuf, 128); }
else // Error or warning
{ if ((ulResult >= 100) && (ulResult < 500)) { // Warning
lstrcpy(szMessage, TEXT("")); LoadString (hInst, IDS_WARNING_MESSAGE, szTempBuf, 128); }
else // Error
{ // If an error msg, load the standard MAWF error message
LoadString (hInst, MAWF_E_GENERIC, szMessage, 64); LoadString (hInst, IDS_CRITICAL_MESSAGE, szTempBuf, 128); } }
// Add a 'Microsoft At Work Fax' to the title
lstrcpy(szTitle, szAppName); lstrcat(szTitle, TEXT(": ")); lstrcat(szTitle, szTempBuf);
// If there is a string ID, load the string from the resource file
if (idString) { TCHAR szFormat[400];
// Point to the first optional parameter. fStyle is the last required parameter
va_start(va, fStyle); LoadString (hInst, idString, szFormat, 255); wvsprintf(szTempBuf, szFormat, va); va_end(va); lstrcat (szMessage, szTempBuf); }
return(MessageBox (hWnd, szMessage, szTitle, fStyle)); }
/* ***************************************************************************
* EncodeFaxAddress * * - encodes fax address components into the format name@+country-code (area-code) fax-number * * Parameters: lpszFaxAddr - address of a buffer in which to fill the encoded fax number * lpParsedFaxAddr - an address of a PARSEDTELNUMBER structure which contains * the components of the address that need to be encoded * * Returns: TRUE on success, FALSE on failure. * * CHECK: will need localization */
BOOL EncodeFaxAddress(LPTSTR lpszFaxAddr, LPPARSEDTELNUMBER lpParsedFaxAddr) {
// somewhat validate parameters
if (!lpszFaxAddr) return FALSE; if (!lpParsedFaxAddr) return FALSE;
// initialize the encoded string to an empty string
lstrcpy(lpszFaxAddr, TEXT(""));
// start with routing name and @, if any
if ((lpParsedFaxAddr->szRoutingName) && (lstrlen(lpParsedFaxAddr->szRoutingName) != 0)) { lstrcat(lpszFaxAddr, lpParsedFaxAddr->szRoutingName); lstrcat(lpszFaxAddr, TEXT("@")); }
// must have a country code
if (lpParsedFaxAddr->szCountryCode) { // if the country code is not 0, start an canonical address
// a 0 country code is a special case, and address generated won't be canonincal
if ( (lstrlen(lpParsedFaxAddr->szCountryCode) != 0) && (lstrcmp(lpParsedFaxAddr->szCountryCode, TEXT("0"))) ) { lstrcat(lpszFaxAddr, TEXT("+")); lstrcat(lpszFaxAddr, lpParsedFaxAddr->szCountryCode); lstrcat(lpszFaxAddr, TEXT(" ")); } } else { goto err; }
// area code is optional
if ((lpParsedFaxAddr->szAreaCode) && (lstrlen(lpParsedFaxAddr->szAreaCode) != 0)) { lstrcat(lpszFaxAddr, TEXT("(")); lstrcat(lpszFaxAddr, lpParsedFaxAddr->szAreaCode); lstrcat(lpszFaxAddr, TEXT(")")); lstrcat(lpszFaxAddr, TEXT(" ")); }
// must have a telephone number
if ((lpParsedFaxAddr->szTelNumber) && (lstrlen(lpParsedFaxAddr->szTelNumber) != 0)) { lstrcat(lpszFaxAddr, lpParsedFaxAddr->szTelNumber); } else { goto err; } #ifdef UNICODE
{ CHAR szDebug[ MAX_PATH ];
szDebug[0] = 0; WideCharToMultiByte( CP_ACP, 0, lpszFaxAddr, -1, szDebug, ARRAYSIZE(szDebug), NULL, NULL ); DEBUG_TRACE("EncodeFaxAddress: Canonical number: %s\n", szDebug); } #else
DEBUG_TRACE("EncodeFaxAddress: Canonical number: %s\n", lpszFaxAddr); #endif
return TRUE;
err: lstrcpy(lpszFaxAddr, TEXT("")); return FALSE;
} /* EncodeFaxAddress */
/* ***************************************************************************
* DecodeFaxAddress * * - parses a fax address of the format name@+country-code (area-code) fax-number * * Parameters: lpszFaxAddr - a Fax address in the above format * lpParsedFaxAddr - an address of a PARSEDTELNUMBER structure in which to * fill the parsed information * * Returns: TRUE on success, FALSE on failure. * success: full address * no routing name * no area code * failure: no '+country-code ' * no telephone number * * CHECK: will need localization */
enum tAddrComp {error, country_code, area_code, tel_number};
BOOL DecodeFaxAddress(LPTSTR lpszFaxAddr, LPPARSEDTELNUMBER lpParsedFaxAddr) { TCHAR szTempBuf[sizeof(PARSEDTELNUMBER)] = {TEXT("")}; BOOL fRoutingNameAllowed = TRUE; BOOL fAreaCodeAllowed = TRUE; BOOL bResult = FALSE; LPTSTR lpszTempBuf = szTempBuf; enum tAddrComp nWhatStarted = tel_number; WORD i;
// somewhat validate parameters
if (!lpszFaxAddr) return FALSE; if (!lpParsedFaxAddr) return FALSE;
// Initialize to empty string values
lstrcpy(lpParsedFaxAddr->szCountryCode, TEXT("")); lstrcpy(lpParsedFaxAddr->szAreaCode, TEXT("")); lstrcpy(lpParsedFaxAddr->szTelNumber, TEXT("")); lstrcpy(lpParsedFaxAddr->szRoutingName, TEXT(""));
// if the string empty, nothing to do
// (else, even if I don't find any "special" charachters in the string,
// I'll stash whatever is in there into the telephone number)
if (!lstrlen(lpszFaxAddr)) return TRUE;
// Scan once through the address. disallow fields as you progress
for (i=0; lpszFaxAddr[i] != 0; i++) { switch (lpszFaxAddr[i]) { case TEXT('@'): // maybe the end of a mailbox name string, or just a @ in the name
if (fRoutingNameAllowed) { LPTSTR lpszTemp;
// is this the last @ in the number string ?
#ifdef UNICODE
lpszTemp = wcschr(lpszFaxAddr, TEXT('@')); #else
lpszTemp = _mbsrchr(lpszFaxAddr, TEXT('@')); #endif
if (lpszTemp == &(lpszFaxAddr[i])) { // end of mailbox name. beginning of "real" canonical number
lstrcpy(lpParsedFaxAddr->szRoutingName, szTempBuf); lpszTempBuf = szTempBuf; } else { // not the end of the mailbox name yet. just continue.
*(lpszTempBuf++) = lpszFaxAddr[i]; *(lpszTempBuf) = 0; } }
break;
case TEXT('+'): // next thing in the string should be the country code
// if there is a '+', I do not allow @ sign to be interpreted as a special character
fRoutingNameAllowed = FALSE; lpszTempBuf = szTempBuf; nWhatStarted = country_code; break;
case TEXT('-'): switch (nWhatStarted) { case country_code: lstrcpy(lpParsedFaxAddr->szCountryCode, szTempBuf); lpszTempBuf = szTempBuf; nWhatStarted = area_code; lstrcpy(szTempBuf, TEXT("")); break;
case area_code: lstrcpy (lpParsedFaxAddr->szAreaCode, szTempBuf); lpszTempBuf = szTempBuf; nWhatStarted = tel_number; break;
default: // for any other character, store in a temp buffer
*(lpszTempBuf++) = lpszFaxAddr[i]; *(lpszTempBuf) = 0; break; } break;
case TEXT('('): // next thing in the string should be the area code
if (fAreaCodeAllowed) { lpszTempBuf = szTempBuf; nWhatStarted = area_code; } break;
case TEXT(')'): // copy without the ()
if ((fAreaCodeAllowed) && (nWhatStarted == area_code)) { lstrcpy(lpParsedFaxAddr->szAreaCode, szTempBuf); // advance beyond the space that follows the ')'
i++; lpszTempBuf = szTempBuf; nWhatStarted = tel_number; fAreaCodeAllowed = FALSE; } break;
case TEXT(' '): // this ends something
if (nWhatStarted == country_code) { lstrcpy(lpParsedFaxAddr->szCountryCode, szTempBuf); lpszTempBuf = szTempBuf; nWhatStarted = tel_number; // may be overriden be area code, if any
// if next character is not '(', I disallow area code
if (lpszFaxAddr[i+1] != '(') fAreaCodeAllowed = FALSE; break; } else if (nWhatStarted == area_code) { // should not happen
DEBUG_TRACE("DecodeFaxAddress: bad address. space in area code\n"); return FALSE; } else; // Spaces are allowed in the mailbox or the phone number,
// so I fall through to the default case
default: // for any other character, store in a temp buffer
*(lpszTempBuf++) = lpszFaxAddr[i]; *(lpszTempBuf) = 0; break; } // switch (lpszFaxAddr[i])
} // for
// End of address string. Last component must be the telephone number
if (nWhatStarted == tel_number) { lstrcpy(lpParsedFaxAddr->szTelNumber, szTempBuf); bResult = TRUE; } else { // we also get here on empty input string
bResult = FALSE; }
return bResult;
} /* DecodeFaxAddress */
#ifdef DO_WE_REALLY_NEED_TAPI
/****************************************************************************
FUNCTION: DoThreadAttach()
PURPOSE: does the thread attach (DLL_THREAD_ATTACH) actions
PARAMETERS: [in/out] lppPTGData - address where to put the thread's private storage pointer
RETURNS: TRUE on success, FALSE on failure
****************************************************************************/ BOOL DoThreadAttach(LPPTGDATA *lppPTGData) { LPPTGDATA lpPTGData=NULL;
// initialize the TLS index for this thread
lpPTGData = (LPPTGDATA) LocalAlloc(LPTR, sizeof(PTGDATA)); if (lpPTGData) { TlsSetValue(dwTlsIndex, lpPTGData); } else { DEBUG_TRACE("DoThreadAttach: LocalAlloc() failed for thread %x\n", GetCurrentThreadId()); goto error; }
/*
* initilialize the per-thread data */
RtlZeroMemory((PVOID) lpPTGData, sizeof(PTGDATA));
// initialize the critical section that is used to control access to hInst
// to make sure this thread does not call us again
InitializeCriticalSection(&(pt_csInstance));
// initialize allocations array
if (!InitAllocations()) { DEBUG_TRACE("DoThreadAttach: InitAllocations failed\n"); goto error; }
// allocate and initialize the TAPI state structure
if (MAWFAllocBuff(SIZEOF(DTS), &pt_lpVdts)) { DEBUG_TRACE("DoThreadAttach: allocation of vdts failed\n"); goto error; }
RtlZeroMemory((PVOID) pt_lpVdts, SIZEOF(DTS)); pt_lpVdts->dwCurrentLocationID = (DWORD)-1;
lpPTGData->iLastDeviceAdded=LINEID_NONE; // what kind of device was last added
*lppPTGData = lpPTGData; return TRUE;
error: *lppPTGData = NULL; return FALSE; }
/****************************************************************************
FUNCTION: GetThreadStoragePointer()
PURPOSE: gets the private storage pointer for a thread, allocating one if it does not exist (i.e. the thread didn't go through LibMain THREAD_ATTACH)
PARAMETERS: none
RETURNS: a pointer to the thread's private storage NULL, if there was a failure (usually memory allocation failure)
****************************************************************************/ LPPTGDATA GetThreadStoragePointer() { LPPTGDATA lpPTGData=TlsGetValue(dwTlsIndex);
// if the thread does not have a private storage, it did not go through
// THREAD_ATTACH and we need to do this here.
if (!lpPTGData) { DEBUG_TRACE("GetThreadStoragePointer: no private storage for this thread %x\n", GetCurrentThreadId()); if (!DoThreadAttach(&lpPTGData)) lpPTGData = NULL; }
return lpPTGData;
}
/* ***************************************************************************
* InitTAPI * * initializes TAPI by calling lineInitialize. enumerates all the available * lines to set up pt_lpVdts->lprgLineInfo. also opens up each available line for * monitoring. sets up pt_lpVdts->iLineCur and pt_lpVdts->iAddrCur by checking the * preferred line/address name stored in the ini file against the available * line/address names. * * Parameters: hInst - the instance of the calling module * hWnd - window handle for UI * lpszAppName - the name of the calling module * * returns NO_ERROR if success and the corresponding error code otherwise. */
DWORD InitTAPI( HINSTANCE hInst, HWND hWnd, LPTSTR lpszAppName ) { LONG lResult; LONG lResultLine = NO_ERROR; DWORD iLine, iLineVoiceFirst = (DWORD)-1;
#ifdef LINE_ADDRESSES
DWORD iAddr, cAddr; LPLINEADDRESSCAPS lpAddrCaps = NULL; CHAR szPreferedAddress[cchAddrNameMac]; #endif
LPPTGDATA lpPTGData = GetThreadStoragePointer(); CHECK_THREAD_STORAGE_POINTER(lpPTGData, "InitTAPI", LINEERR_NOMEM);
/***************************************
********* initialize tapi ************* ***************************************/
DEBUG_TRACE("InitTAPI: thread %x is initializing\n", GetCurrentThreadId()); DEBUG_TRACE("InitTAPI: cRefCount is %d\n", pt_lpVdts->cRefCount);
// see if this thread already initialized TAPI
if (pt_lpVdts->cRefCount) { lResult = NO_ERROR; goto LDone; }
if ((lResult = TAPIBasicInit(hInst, hWnd, lpszAppName)) != NO_ERROR) goto LDone;
/***************************************
********* initialize lines ************ ***************************************/
// initialize pt_lpVdts->lpgrLineInfo and open each available line for
// monitoring
// allocate buffer for storing LINEINFO for all the available lines
pt_lpVdts->lprgLineInfo = (LPLINEINFO)_fmalloc(SIZEOF(LINEINFO)*(int)pt_lpVdts->cLines); if (pt_lpVdts->lprgLineInfo == NULL) { lResult = LINEERR_NOMEM; goto LDone; } _fmemset(pt_lpVdts->lprgLineInfo,0,SIZEOF(LINEINFO)*(int)pt_lpVdts->cLines);
// init pt_lpVdts->lprgLineInfo and open each line to get its caps
// also count the fax lines
pt_lpVdts->cFaxLines = 0; for (iLine = 0; iLine < pt_lpVdts->cLines; ++iLine) { // Open the line and get its capabilities, including its name
lResult = GetCachedLineInfo(iLine); if (lResult != NO_ERROR) { // something went wrong with initializing a line that TAPI told me
// should be OK
// I save the lResult (but doing nothing with it for now)
// and continue with other lines. This line does not get enumerated.
lResultLine = lResult; // this does not mean InitTAPI failed
lResult = NO_ERROR; continue; // goto LDone;
}
if ( (iLineVoiceFirst == (DWORD)-1) && pt_lpVdts->lprgLineInfo[iLine].fIsVoiceLine ) { iLineVoiceFirst = iLine; }
// if it's a fax line, count it in
if (pt_lpVdts->lprgLineInfo[iLine].fIsVoiceLine) // CHECK: && fIsFaxDevice))
{ pt_lpVdts->cFaxLines++; }
} // for
// No reason to proceed if no Fax lines
if (pt_lpVdts->cFaxLines == 0) { /* no voice line, too bad */ lResult = ERROR_NO_LINES; pt_lpVdts->iLineCur = NO_MODEM; goto LDone; } // If no current line and there is a voice line, set the current line to be this voice line
// This code is probably not needed, as I later (InitLineDeviceLB()) set the current line
// from the profile
else if (pt_lpVdts->iLineCur == NO_MODEM) { pt_lpVdts->iLineCur = iLineVoiceFirst; }
#ifdef LINE_ADDRESSES
/* **************************************************/ /* init pt_lpVdts->iAddrCur */
// Set the line address to a default value of 0 (the only one currently supported)
pt_lpVdts->iAddrCur = 0;
// allocate buffer for the lineGetAddressCaps calls
if ((lpAddrCaps = (LPLINEADDRESSCAPS)_fmalloc(lcbAddrDevCapsInitial)) == NULL) { lResult = LINEERR_NOMEM; goto LDone; } lpAddrCaps->dwTotalSize = lcbAddrDevCapsInitial;
// enumerate all the available addresses to match szPreferedAddress with
// an address name
cAddr = pt_lpVdts->lprgLineInfo[pt_lpVdts->iLineCur].cAddr; for (iAddr = 0; iAddr < cAddr; ++iAddr) { char szAddrName[cchAddrNameMac]; LPTSTR lpszAddrName;
// get address capability info
lResult = lineGetAddressCaps( pt_lpVdts->hApp, pt_lpVdts->iLineCur, iAddr, tapiVersionCur, 0, lpAddrCaps ); if (lResult != NO_ERROR) goto LDone;
// reallocate buffer if not big enough
while (lpAddrCaps->dwNeededSize > lpAddrCaps->dwTotalSize) { DWORD lcbNeeded = lpAddrCaps->dwNeededSize;
_ffree(lpAddrCaps); if ((lpAddrCaps = (LPLINEADDRESSCAPS)_fmalloc((size_t)lcbNeeded)) == NULL) { lResult = LINEERR_NOMEM; goto LDone; } lpAddrCaps->dwTotalSize = lcbNeeded;
/* try it one more time */ lResult = lineGetAddressCaps( pt_lpVdts->hApp, pt_lpVdts->iLineCur, iAddr, tapiVersionCur, 0, lpAddrCaps ); if (lResult != NO_ERROR) goto LDone; } /* while */
/* get the address's name */ if (lpAddrCaps->dwAddressSize > 0) lpszAddrName = (LPTSTR)((LPBYTE)(lpAddrCaps)+lpAddrCaps->dwAddressOffset); else { /* use default name */ TCHAR szAddrFormat[32];
LoadString( hInst, IDS_TAPI_LINE_NAME, szAddrFormat, ARRAYSIZEf(szAddrFormat) ); wsprintf(szAddrName,szAddrFormat,iAddr); lpszAddrName = (LPTSTR)szAddrName; } /* else */
if (lstrcmpi(lpszAddrName,szPreferedAddress) == 0) { pt_lpVdts->iAddrCur = iAddr; break; } /* if */ } /* for */ #endif // #ifdef LINE_ADDRESSES
lResult = NO_ERROR;
LDone: // free up memory allocated
#ifdef LINE_ADDRESSES
if (lpAddrCaps) _ffree(lpAddrCaps); #endif
// if InitTAPI succeeded, bump up the ref count
if ( (lResult == NO_ERROR) || (lResult == ERROR_NO_LINES) ) { pt_lpVdts->cRefCount++; } // else, free unneeded memory
else if (pt_lpVdts->lprgLineInfo) { _ffree(pt_lpVdts->lprgLineInfo); pt_lpVdts->lprgLineInfo = NULL; }
return lResult;
} /* InitTAPI */
/****************************************************************************
* DeinitTAPI * * frees up the memory allocated, closes all the lines we have opened for * monitoring and calls lineShutDown to disconnect from TAPI. */
BOOL DeinitTAPI() { LPPTGDATA lpPTGData = GetThreadStoragePointer(); CHECK_THREAD_STORAGE_POINTER(lpPTGData, "DeinitTAPI", 0xffffffff);
DEBUG_TRACE("DeinitTAPI: thread %x is deinitializing\n", GetCurrentThreadId());
// if ref count is already 0, unbalanced calls, do nothing
if (!(pt_lpVdts->cRefCount)) return TRUE;
// don't want to deinit if ref count is still > 0
if (--pt_lpVdts->cRefCount) return TRUE;
/* never mind if lineInitialize failed in the first place */ if (!pt_lpVdts->fLineInited) return TRUE;
/* unregister STAPI */ FRegisterSimpleTapi(FALSE);
/* closes all the open lines and free pt_lpVdts->lprgLineInfo */ if (pt_lpVdts->lprgLineInfo) { DWORD iLine;
for (iLine = 0; iLine < pt_lpVdts->cLines; ++iLine) { DEBUG_TRACE( "Thread %x,DeinitTAPI: looking to close line %x...\n", GetCurrentThreadId(), iLine ); if (pt_lpVdts->lprgLineInfo[iLine].dwAPIVersion == 0) continue; lineClose(pt_lpVdts->lprgLineInfo[iLine].hLine); DEBUG_TRACE( "Thread %x,DeinitTAPI: line %x is closed\n", GetCurrentThreadId(), iLine ); } /* for */
_ffree(pt_lpVdts->lprgLineInfo); } /* if */
/* disconnect from TAPI */ lineShutdown(pt_lpVdts->hApp);
pt_lpVdts->hInst = NULL;
return TRUE;
} /* DeinitTAPI */ #endif // DO_WE_REALLY_NEED_TAPI
|