//+---------------------------------------------------------------------------- // // File: tapi.cpp // // Module: CMDIAL32.DLL // // Synopsis: The module contains the code related to TAPI. // // Copyright (c) 1996-1999 Microsoft Corporation // // Author: byao created 04/29/97 // quintinb created Header 08/16/99 // //+---------------------------------------------------------------------------- #include "cmmaster.h" #include "unimodem.h" // // Local prototype // DWORD GetModemSpeakerMode(TapiLinkageStruct *ptlsTapiLink); //+---------------------------------------------------------------------------- // // Function: TapiCallback // // Synopsis: NULL callback required param when intializing line // // Arguments: DWORD hDevice - // DWORD dwMsg - // DWORD dwCallbackInstance - // DWORD dwParam1 - // DWORD dwParam2 - // DWORD dwParam3 - // // Returns: Nothing // // History: nickball Created Header 7/7/99 // //+---------------------------------------------------------------------------- VOID FAR PASCAL TapiCallback(DWORD hDevice, DWORD dwMsg, DWORD dwCallbackInstance, DWORD dwParam1, DWORD dwParam2, DWORD dwParam3) { // nothing } //+---------------------------------------------------------------------------- // // Function: OpenTapi // // Synopsis: // // Arguments: HINSTANCE hInst - // TapiLinkageStruct *ptlsTapiLink - // // Returns: BOOL - // // History: quintinb Created Header 5/1/99 // //+---------------------------------------------------------------------------- BOOL OpenTapi(HINSTANCE hInst, TapiLinkageStruct *ptlsTapiLink) { LONG lRes; if (ptlsTapiLink->bOpen) { return (TRUE); } if (!ptlsTapiLink->pfnlineInitialize || !ptlsTapiLink->pfnlineShutdown) { SetLastError(ERROR_PROC_NOT_FOUND); return (FALSE); } lRes = ptlsTapiLink->pfnlineInitialize(&ptlsTapiLink->hlaLine, hInst, TapiCallback, NULL, &ptlsTapiLink->dwDevCnt); CMTRACE3(TEXT("OpenTapi() lineInitialize() returns %u, hlaLine=0x%x, dwDevCnt=%u."), lRes, ptlsTapiLink->hlaLine, ptlsTapiLink->dwDevCnt); if (lRes != 0) { DWORD dwErr = ERROR_INVALID_PARAMETER; switch (lRes) { case LINEERR_REINIT: dwErr = ERROR_BUSY; break; case LINEERR_RESOURCEUNAVAIL: case LINEERR_NOMEM: dwErr = ERROR_NOT_ENOUGH_MEMORY; break; } SetLastError(dwErr); return (FALSE); } ptlsTapiLink->bOpen = TRUE; ptlsTapiLink->bDevicePicked = FALSE; ptlsTapiLink->bModemSpeakerOff = FALSE; return (TRUE); } //+---------------------------------------------------------------------------- // // Function: CloseTapi // // Synopsis: Helper function to clean up TAPI line. // // Arguments: TapiLinkageStruct *ptlsTapiLink - Our TAPI linkage struct // // Returns: Nothing // // History: nickball Created Header 7/7/99 // //+---------------------------------------------------------------------------- void CloseTapi(TapiLinkageStruct *ptlsTapiLink) { if (ptlsTapiLink->bOpen) { ptlsTapiLink->bOpen = FALSE; ptlsTapiLink->pfnlineShutdown(ptlsTapiLink->hlaLine); } } //+---------------------------------------------------------------------------- // // Function: LinkToTapi // // Synopsis: Encapsulates the calling of LinkToDll with the correct table of // function names to be used therein with GetProcAddress // // Arguments: TapiLinkageStruct *ptlsTapiLink - The Tapi linkage struct to receive the function addresses // LPCTSTR pszTapi - The explicit name of the DLL // // Returns: BOOL - TRUE if fully linked // // History: nickball Created Header 12/31/97 // //+---------------------------------------------------------------------------- BOOL LinkToTapi(TapiLinkageStruct *ptlsTapiLink, LPCSTR pszTapi) { BOOL bRet = FALSE; if (OS_NT) { static LPCSTR apszTapi[] = { // // Several of the Tapi Functions don't have W versions. Use all the Unicode functions // that we can however. // "lineInitialize", // no W version "lineNegotiateAPIVersion", // no W version "lineGetDevCapsW", "lineGetDevConfig", "lineShutdown", // no W version "lineTranslateAddressW", "lineTranslateDialogW", "lineGetTranslateCaps", "lineSetCurrentLocation", NULL }; MYDBGASSERT(sizeof(ptlsTapiLink->apvPfnTapi)/sizeof(ptlsTapiLink->apvPfnTapi[0])==sizeof(apszTapi)/sizeof(apszTapi[0])); bRet = LinkToDll(&ptlsTapiLink->hInstTapi,pszTapi,apszTapi,ptlsTapiLink->apvPfnTapi); } else { static LPCSTR apszTapi[] = { "lineInitialize", "lineNegotiateAPIVersion", "lineGetDevCaps", "lineGetDevConfig", "lineShutdown", "lineTranslateAddress", "lineTranslateDialog", "lineGetTranslateCaps", "lineSetCurrentLocation", NULL }; MYDBGASSERT(sizeof(ptlsTapiLink->apvPfnTapi)/sizeof(ptlsTapiLink->apvPfnTapi[0])==sizeof(apszTapi)/sizeof(apszTapi[0])); bRet = LinkToDll(&ptlsTapiLink->hInstTapi,pszTapi,apszTapi,ptlsTapiLink->apvPfnTapi); } return bRet; } //+---------------------------------------------------------------------------- // // Function: UnlinkFromTapi // // Synopsis: Helper function to release link to TAPI and clear linkage struct // // Arguments: TapiLinkageStruct *ptlsTapiLink - Ptr to our TAPI linkage struct // // Returns: Nothing // // History: nickball Created Header 7/7/99 // // t-urama Modified 08/04/00 Access Points: Restore Tapi // location when CM was started //+---------------------------------------------------------------------------- void UnlinkFromTapi(TapiLinkageStruct *ptlsTapiLink) { if (ptlsTapiLink->hInstTapi) { // // If we changed the original Tapi location, restore it // if (-1 != ptlsTapiLink->dwOldTapiLocation) { RestoreOldTapiLocation(ptlsTapiLink); } CloseTapi(ptlsTapiLink); FreeLibrary(ptlsTapiLink->hInstTapi); memset(ptlsTapiLink,0,sizeof(*ptlsTapiLink)); } } LPTSTR GetModemFromLineDevCapsWithAlloc(LPLINEDEVCAPS pldcLineDevCaps) { LPTSTR pszTmp = NULL; if (OS_NT) { pszTmp = (LPTSTR) CmMalloc((pldcLineDevCaps->dwLineNameSize + 1)*sizeof(TCHAR)); if (pszTmp) { LPTSTR pszPointerIntoTapiBuffer = LPTSTR((DWORD_PTR)pldcLineDevCaps + pldcLineDevCaps->dwLineNameOffset); lstrcpynU (pszTmp, pszPointerIntoTapiBuffer, pldcLineDevCaps->dwLineNameSize + 1); } } else { // // If this is Win9x, then we have an Ansi buffer that we need to convert to Unicode // LPSTR pszAnsiTmp = (LPSTR) CmMalloc((pldcLineDevCaps->dwLineNameSize + 1)*sizeof(CHAR)); if (pszAnsiTmp) { LPSTR pszPointerIntoTapiBuffer = LPSTR((DWORD_PTR)pldcLineDevCaps + pldcLineDevCaps->dwLineNameOffset); lstrcpynA (pszAnsiTmp, pszPointerIntoTapiBuffer, pldcLineDevCaps->dwLineNameSize + 1); pszTmp = SzToWzWithAlloc(pszAnsiTmp); CmFree(pszAnsiTmp); } } return pszTmp; } BOOL SetTapiDevice(HINSTANCE hInst, TapiLinkageStruct *ptlsTapiLink, LPCTSTR pszModem) { BOOL bRet = TRUE; LONG lRes; DWORD dwTmp; LPLINEDEVCAPS pldcLineDevCaps; if (!OpenTapi(hInst,ptlsTapiLink)) { return (FALSE); } if (ptlsTapiLink->bDevicePicked && (lstrcmpU(ptlsTapiLink->szDeviceName, pszModem) == 0)) { return (TRUE); } CMTRACE1(TEXT("SetTapiDevice() looking for device name match with (%s)."), pszModem); ptlsTapiLink->bDevicePicked = FALSE; // // LineGetDevCaps has both an Ansi version (win9x) and a Unicode version. Thus we must use // the correct char size as needed. // dwTmp = sizeof(LINEDEVCAPS) + (2048 * (OS_NT ? sizeof(WCHAR) : sizeof(CHAR))); pldcLineDevCaps = (LPLINEDEVCAPS) CmMalloc(dwTmp); if (NULL == pldcLineDevCaps) { return FALSE; } pldcLineDevCaps->dwTotalSize = dwTmp; for (ptlsTapiLink->dwDeviceId=0; ptlsTapiLink->dwDeviceId < ptlsTapiLink->dwDevCnt; ptlsTapiLink->dwDeviceId++) { LINEEXTENSIONID leiLineExtensionId; lRes = ptlsTapiLink->pfnlineNegotiateAPIVersion(ptlsTapiLink->hlaLine, ptlsTapiLink->dwDeviceId, MIN_TAPI_VERSION, MAX_TAPI_VERSION, &ptlsTapiLink->dwApiVersion, &leiLineExtensionId); CMTRACE3(TEXT("******* SetTapiDevice() lineNegotiateAPIVersion(dwDeviceId=%u) returns %u, dwApiVersion=0x%x."), ptlsTapiLink->dwDeviceId, lRes, ptlsTapiLink->dwApiVersion); if (lRes == ERROR_SUCCESS) { lRes = ptlsTapiLink->pfnlineGetDevCaps(ptlsTapiLink->hlaLine, ptlsTapiLink->dwDeviceId, ptlsTapiLink->dwApiVersion, 0, pldcLineDevCaps); CMTRACE2(TEXT("SetTapiDevice() lineGetDevCaps(dwDeviceId=%u) returns %u."), ptlsTapiLink->dwDeviceId, lRes); if (lRes == ERROR_SUCCESS) { // // Copy out the device name according to reported offset and // length. Don't assume that its a NULL terminated string. // LPTSTR pszTmp = GetModemFromLineDevCapsWithAlloc(pldcLineDevCaps); if (pszTmp) { // // Okay, we have a device name from TAPI, first try to do a straight // comparision with the one we are looking for // CMTRACE1(TEXT("SetTapiDevice() - examining LineName of (%s)."), pszTmp); if (0 == lstrcmpU(pszModem, pszTmp)) { ptlsTapiLink->bDevicePicked = TRUE; } else { // // We didn't find a straight match but that doesn't mean that // this isn't our device. On NT, RAS keeps its device names in ANSI // internally. Thus we can try roundtripping the string to MBCS and // back and see if they match now. Another possibility is that this // is an ISDN device, because on NT4 the RAS name and TAPI name are // different for ISDN devices. So, instead of checking the LineName // we should check the ProviderInfo (it is concatenation of two NULL terminated strings // and the second string is the used by RAS as device name) // if (OS_NT) { DWORD dwSize = WzToSz(pszTmp, NULL, 0); // cannot use WzToSzWithAlloc or we would get asserts // that the string didn't roundtrip on debug builds. // The point here is not to have it round trip so // that is what we want but we don't want to assert. if (0 != dwSize) { LPSTR pszAnsiTmp = (LPSTR)CmMalloc(dwSize*sizeof(CHAR)); if (pszAnsiTmp) { if (WzToSz(pszTmp, pszAnsiTmp, dwSize)) { LPWSTR pszRoundTripped = SzToWzWithAlloc(pszAnsiTmp); if (pszRoundTripped) { if (0 == lstrcmpU(pszModem, pszRoundTripped)) { ptlsTapiLink->bDevicePicked = TRUE; } } CmFree(pszRoundTripped); } CmFree(pszAnsiTmp); } } // // Okay, check for an ISDN device name if it is one // if (!ptlsTapiLink->bDevicePicked) { // // Copy out the provider info according to reported offset // and length. Don't assume that its NULL terminated. // CmFree(pszTmp); pszTmp = (LPTSTR) CmMalloc((pldcLineDevCaps->dwProviderInfoSize + 1)*sizeof(TCHAR)); if (pszTmp) { lstrcpynU(pszTmp, (LPTSTR)((LPBYTE)pldcLineDevCaps + pldcLineDevCaps->dwProviderInfoOffset), (pldcLineDevCaps->dwProviderInfoSize + 1)); // // We should do this only if the device type is ISDN // The device type is the first string in the ProviderInfo // CMTRACE1(TEXT("SetTapiDevice() - examining ProviderInfo of (%s) for match with (RASDT_Isdn)."), pszTmp); if (0 == lstrcmpiU(pszTmp, RASDT_Isdn)) { ptlsTapiLink->bDevicePicked = TRUE; } } } } } } // // If we found a device, then we need to copy the name over // if (ptlsTapiLink->bDevicePicked) { lstrcpynU(ptlsTapiLink->szDeviceName, pszModem, CELEMS(ptlsTapiLink->szDeviceName)); if (OS_NT) { dwTmp = GetModemSpeakerMode(ptlsTapiLink); if (-1 != dwTmp && MDMSPKR_OFF == dwTmp) { ptlsTapiLink->bModemSpeakerOff = TRUE; } } // // We found a device, stop looking... // CmFree(pszTmp); break; } CmFree(pszTmp); } } } CmFree(pldcLineDevCaps); bRet = ptlsTapiLink->bDevicePicked; return bRet; } //+---------------------------------------------------------------------------- // // Function: GetModemSpeakerMode // // Synopsis: Queries Modem settings for Speaker modeof a modem device. // // Arguments: TapiLinkageStruct *ptlsTapiLink - Ptr to TAPI linkage // // Returns: DWORD - The speaker mode for a valid modem device or 0xFFFFFFFF // // History: nickball Created 7/7/99 // //+---------------------------------------------------------------------------- DWORD GetModemSpeakerMode(TapiLinkageStruct *ptlsTapiLink) { DWORD dwRet = -1; LPVARSTRING lpVar = (LPVARSTRING) CmMalloc(sizeof(VARSTRING)); // // Get the required buffer size by querying the config. // if (lpVar) { lpVar->dwTotalSize = sizeof(VARSTRING); lpVar->dwUsedSize = lpVar->dwTotalSize; DWORD dwTmpRet = ptlsTapiLink->pfnlineGetDevConfig(ptlsTapiLink->dwDeviceId, lpVar, "comm/datamodem/dialout"); if (LINEERR_STRUCTURETOOSMALL == dwTmpRet || lpVar->dwNeededSize > lpVar->dwTotalSize) { // // We need a bigger buffer, re-allocate // DWORD dwTmp = lpVar->dwNeededSize; CmFree(lpVar); lpVar = (LPVARSTRING) CmMalloc(dwTmp); if (lpVar) { lpVar->dwTotalSize = dwTmp; lpVar->dwUsedSize = lpVar->dwTotalSize; // // Now get the actual config // dwTmpRet = ptlsTapiLink->pfnlineGetDevConfig(ptlsTapiLink->dwDeviceId, lpVar, "comm/datamodem/dialout"); if (ERROR_SUCCESS != dwTmpRet) { CmFree(lpVar); lpVar = NULL; } } } } // // If we don't have a valid VARSTRING something failed, error out. // if (NULL == lpVar) { return -1; } // // We have a VARSTRING for the "dialout" config, // get the MODEMSETTINGS info. and see how the // modem speaker is configured. // PUMDEVCFG lpDevConfig = NULL; LPCOMMCONFIG lpCommConfig = NULL; LPMODEMSETTINGS lpModemSettings = NULL; if (lpVar->dwStringFormat == STRINGFORMAT_BINARY && lpVar->dwStringSize >= sizeof(UMDEVCFG)) { lpDevConfig = (PUMDEVCFG) ((LPBYTE) lpVar + lpVar->dwStringOffset); lpCommConfig = &lpDevConfig->commconfig; // // Check modems only // if (lpCommConfig->dwProviderSubType == PST_MODEM) { lpModemSettings = (LPMODEMSETTINGS)((LPBYTE) lpCommConfig + lpCommConfig->dwProviderOffset); dwRet = lpModemSettings->dwSpeakerMode; } } CmFree(lpVar); return dwRet; } //+---------------------------------------------------------------------------- // // Func: MungePhone // // Desc: call TAPI to do phone dial info translation // // Args: [pszModem] - IN, modem string // [ppszPhone] - INOUT, phone number for display // [ptlsTapiLink] - IN, argument string for connect action // [hInst] - IN, instance handle (needed to call TAPI) // [fDialingRules] - are dialing rules enabled // [ppszDial] - OUT, dialable phone number // [fAccessPointsEnabled] - IN, are access points enabled // Return: LRESULT // // Notes: // // History: 01-Mar-2000 SumitC Added header block // 04-Mar-2000 SumitC fixed case for dialing rules not enabled // 04-Aug-2000 t-urama Added changing the TAPI location based on access point // //----------------------------------------------------------------------------- LRESULT MungePhone(LPCTSTR pszModem, LPTSTR *ppszPhone, TapiLinkageStruct *ptlsTapiLink, HINSTANCE hInst, BOOL fDialingRules, LPTSTR *ppszDial, BOOL fAccessPointsEnabled) { LPLINETRANSLATEOUTPUT pltoOutput = NULL; DWORD dwLen; LPWSTR pszDisplayable = NULL; LPWSTR pszDialable = NULL; LPSTR pszAnsiDisplayable = NULL; LPSTR pszAnsiDialable = NULL; LPTSTR pszOriginalPhoneNumber = NULL; LRESULT lRes; // // Check the input params. Note that ppszDial could be NULL. // if ((NULL == pszModem) || (NULL == ppszPhone) || (NULL == *ppszPhone) || (NULL == ptlsTapiLink) || (NULL == hInst)) { lRes = ERROR_INVALID_PARAMETER; CMASSERTMSG(FALSE, TEXT("MungePhone - invalid param.")); goto done; } if (!SetTapiDevice(hInst, ptlsTapiLink, pszModem)) { lRes = ERROR_NOT_FOUND; goto done; } if (FALSE == fDialingRules) { pszOriginalPhoneNumber = CmStrCpyAlloc(*ppszPhone); } if (TRUE == fDialingRules) { if (fAccessPointsEnabled) { // // Access Points are enabled. we now have to change the TAPI location // to that of the current access point. First get the current TAPI // location from TAPI // DWORD dwRet = GetCurrentTapiLocation(ptlsTapiLink); if (-1 == dwRet) { lRes = ERROR_NOT_FOUND; goto done; } if ((0 != ptlsTapiLink->dwTapiLocationForAccessPoint) && (dwRet != ptlsTapiLink->dwTapiLocationForAccessPoint)) { // // The current TAPI location is different from the access point TAPI location // Change it. Note that if the current TAPI location is 0, this just means we haven't written // one for the favorite yet. Don't try to change it as SetCurrentTapiLocation will error out. // lRes = SetCurrentTapiLocation(ptlsTapiLink, ptlsTapiLink->dwTapiLocationForAccessPoint); if (lRes != ERROR_SUCCESS) { CMASSERTMSG(FALSE, TEXT("MungePhone -- unable to set the current TAPI location.")); goto done; } CMTRACE1(TEXT("MungePhone() - Changed TAPI location to %u."), ptlsTapiLink->dwTapiLocationForAccessPoint); // // Save the TAPI location that was being used when CM started. // This will be restored when CM exits // if (-1 == ptlsTapiLink->dwOldTapiLocation) { ptlsTapiLink->dwOldTapiLocation = dwRet; CMTRACE1(TEXT("Saved TAPI location used when CM started, location is %d"), ptlsTapiLink->dwOldTapiLocation); } } } } // // Setup buffer for output, make sure to size the CHARs properly // dwLen = sizeof(*pltoOutput) + (1024 * (OS_NT ? sizeof(WCHAR) : sizeof(CHAR))); pltoOutput = (LPLINETRANSLATEOUTPUT) CmMalloc(dwLen); if (NULL == pltoOutput) { lRes = ERROR_NOT_ENOUGH_MEMORY; goto done; } pltoOutput->dwTotalSize = dwLen; // // Do the translation // if (OS_NT) { lRes = ptlsTapiLink->pfnlineTranslateAddress(ptlsTapiLink->hlaLine, ptlsTapiLink->dwDeviceId, ptlsTapiLink->dwApiVersion, *ppszPhone, 0, LINETRANSLATEOPTION_CANCELCALLWAITING, pltoOutput); } else { LPSTR pszAnsiPhone = WzToSzWithAlloc(*ppszPhone); if (pszAnsiPhone) { // // Note that the Cast on parameter 4 is to fake out the compiler, // rather than building a full set of "U" infrastructure for // the tapi linkage when only a couple of TAPI calls take strings. // lRes = ptlsTapiLink->pfnlineTranslateAddress(ptlsTapiLink->hlaLine, ptlsTapiLink->dwDeviceId, ptlsTapiLink->dwApiVersion, (LPWSTR)pszAnsiPhone, 0, LINETRANSLATEOPTION_CANCELCALLWAITING, pltoOutput); } CmFree(pszAnsiPhone); } CMTRACE3(TEXT("MungePhone(Modem=%s,Phone=%s) lineTranslateAddress(DeviceId=%u)"), MYDBGSTR(pszModem), MYDBGSTR(*ppszPhone), ptlsTapiLink->dwDeviceId); CMTRACE1(TEXT("\treturns %u."), lRes); if (lRes == ERROR_SUCCESS) { // // Get ptrs to displayable and dialable variations // LPBYTE pBase = (LPBYTE) pltoOutput; if (OS_NT) { pszDisplayable = (LPTSTR) (pBase + pltoOutput->dwDisplayableStringOffset); pszDialable = (LPTSTR) (pBase + pltoOutput->dwDialableStringOffset); } else { pszAnsiDisplayable = (LPSTR)(pBase + pltoOutput->dwDisplayableStringOffset); pszAnsiDialable = (LPSTR)(pBase + pltoOutput->dwDialableStringOffset); } } done: CmFree(*ppszPhone); *ppszPhone = NULL; if (ppszDial) { CmFree(*ppszDial); *ppszDial = NULL; } // Allocate buffers using the ptr ptrs specified by the caller // and fill them with the displayable and dialable versions if (ERROR_SUCCESS == lRes) { if (OS_NT) { if (fDialingRules) { *ppszPhone = CmStrCpyAlloc(pszDisplayable); } else { *ppszPhone = CmStrCpyAlloc(pszOriginalPhoneNumber); } } else { if (fDialingRules) { *ppszPhone = SzToWzWithAlloc(pszAnsiDisplayable); } else { *ppszPhone = CmStrCpyAlloc(pszOriginalPhoneNumber); } } MYDBGASSERT(*ppszPhone); if (*ppszPhone) { // // TAPI prepends a space, so trim the displayable number. // CmStrTrim(*ppszPhone); SingleSpace(*ppszPhone); } else { // // If we failed to alloc *ppszPhone, continue because we don't // depend on it below but we want the return code to be a failure. // lRes = ERROR_NOT_ENOUGH_MEMORY; } if (ppszDial) { if (OS_NT) { if (fDialingRules) { *ppszDial = CmStrCpyAlloc(pszDialable); } else { *ppszDial = (LPTSTR) CmMalloc(sizeof(TCHAR)*(2 + lstrlenU(pszOriginalPhoneNumber))); // 2 == one for NULL term and one for first char of pszDialable if (*ppszDial) { (*ppszDial)[0] = pszDialable[0]; (*ppszDial)[1] = 0; lstrcatU(*ppszDial, pszOriginalPhoneNumber); } } } else { if (fDialingRules) { *ppszDial = SzToWzWithAlloc(pszAnsiDialable); } else { *ppszDial = (LPTSTR) CmMalloc(sizeof(TCHAR)*(2 + lstrlenU(pszOriginalPhoneNumber))); // 2 == one for NULL term and one for first char of pszDialable if (*ppszDial) { int lRet = MultiByteToWideChar(CP_ACP, 0, pszAnsiDialable, 1, *ppszDial, 1); (*ppszDial)[lRet] = 0; lstrcatU(*ppszDial, pszOriginalPhoneNumber); } } } } } if (FALSE == fDialingRules) { CmFree(pszOriginalPhoneNumber); } CmFree(pltoOutput); return (lRes); } //+---------------------------------------------------------------------------- // // Func: GetCurrentTapiLocation // // Desc: get the current Tapi location // // Args: [ptlsTapiLink] - IN, Ptr to TAPI linkage // // Return: DWORD dwCurrentLoc - Current Tapi Location // // Notes: // // History: t-urama 07/21/2000 Created //----------------------------------------------------------------------------- DWORD GetCurrentTapiLocation(TapiLinkageStruct *ptlsTapiLink) { MYDBGASSERT(ptlsTapiLink->pfnlineGetTranslateCaps); if (!ptlsTapiLink->pfnlineGetTranslateCaps) { SetLastError(ERROR_PROC_NOT_FOUND); return (-1); } LPLINETRANSLATECAPS lpTranslateCaps = NULL; DWORD dwLen; LRESULT lRes; DWORD dwRes = -1; BOOL bLoopAgain = FALSE; dwLen = sizeof(*lpTranslateCaps) + (1024 * (OS_NT ? sizeof(WCHAR) : sizeof(CHAR))); do { CmFree(lpTranslateCaps); lpTranslateCaps = (LPLINETRANSLATECAPS) CmMalloc(dwLen); MYDBGASSERT(lpTranslateCaps); if (NULL == lpTranslateCaps) { lRes = ERROR_NOT_ENOUGH_MEMORY; break; } lpTranslateCaps->dwTotalSize = dwLen; lRes = ptlsTapiLink->pfnlineGetTranslateCaps(ptlsTapiLink->hlaLine, ptlsTapiLink->dwApiVersion, lpTranslateCaps); bLoopAgain = (LINEERR_STRUCTURETOOSMALL == lRes) || ((ERROR_SUCCESS == lRes) && (lpTranslateCaps->dwNeededSize > lpTranslateCaps->dwTotalSize)); if (bLoopAgain) { dwLen = lpTranslateCaps->dwNeededSize; } } while(bLoopAgain); if (ERROR_SUCCESS != lRes) { CMTRACE1(TEXT("lineGetTranslateCaps returns error code %u."), lRes); } else { dwRes = lpTranslateCaps->dwCurrentLocationID; } CmFree(lpTranslateCaps); return dwRes; } //+---------------------------------------------------------------------------- // // Func: SetCurrentTapiLocation // // Desc: Set the current Tapi location // // Args: TapiLinkageStruct *ptlsTapiLink - Ptr to TAPI linkage // DWORD dwLocation - New location // // Return: DWORD - Error code // // Notes: // // History: t-urama 07/21/2000 Created //----------------------------------------------------------------------------- DWORD SetCurrentTapiLocation(TapiLinkageStruct *ptlsTapiLink, DWORD dwLocation) { MYDBGASSERT(ptlsTapiLink->pfnlineSetCurrentLocation); if (!ptlsTapiLink->pfnlineSetCurrentLocation) { SetLastError(ERROR_PROC_NOT_FOUND); return (-1); } DWORD dwRes = 0; dwRes = ptlsTapiLink->pfnlineSetCurrentLocation(ptlsTapiLink->hlaLine, dwLocation); CMTRACE1(TEXT("SetCurrentTapiLocation -- setting TAPI location to %d"), dwLocation); return dwRes; } //+---------------------------------------------------------------------------- // // Func: RestoreOldTapiLocation // // Desc: Restore the Tapi location to the one when CM was started // // Args: TapiLinkageStruct *ptlsTapiLink - IN, Ptr to TAPI linkage // // Return: Nothing // // Notes: // // History: t-urama 07/21/2000 Created //----------------------------------------------------------------------------- void RestoreOldTapiLocation(TapiLinkageStruct *ptlsTapiLink) { if (ptlsTapiLink->dwOldTapiLocation != ptlsTapiLink->dwTapiLocationForAccessPoint) { CMTRACE1(TEXT("RestoreOldTapiLocation -- setting TAPI location to %d"), ptlsTapiLink->dwOldTapiLocation); MYVERIFY (0 == SetCurrentTapiLocation(ptlsTapiLink, ptlsTapiLink->dwOldTapiLocation)); } }