diff options
Diffstat (limited to 'private/unimodem/tapisp/unimdm.c')
-rw-r--r-- | private/unimodem/tapisp/unimdm.c | 3399 |
1 files changed, 3399 insertions, 0 deletions
diff --git a/private/unimodem/tapisp/unimdm.c b/private/unimodem/tapisp/unimdm.c new file mode 100644 index 000000000..64a22fa08 --- /dev/null +++ b/private/unimodem/tapisp/unimdm.c @@ -0,0 +1,3399 @@ +//**************************************************************************** +// +// Module: Unimdm.tsp +// File: unimdm.c +// Content: This file contains the moudle initialization. +// +// Copyright (c) 1992-1993, Microsoft Corporation, all rights reserved +// +// History: +// Tue 23-Feb-1993 14:08:25 -by- Viroon Touranachun [viroont] +// Ported from TAPI's atsp +// +//**************************************************************************** + +#include "unimdm.h" +#include "umdmspi.h" +#include "rcids.h" + +//**************************************************************************** +// Global Variables +//**************************************************************************** + +HINSTANCE ghInstance = NULL; // The global module handle +DWORD gdwProviderID; +HPROVIDER ghProvider; + +// Asynchronous operation completion callback +// +ASYNC_COMPLETION gfnCompletionCallback = NULL; +LINEEVENT gfnLineCreateProc = NULL; + + +void SetPendingRequest( + PLINEDEV pLineDev, + DWORD dwRequestID, + DWORD dwRequestOp + ); +void ClearPendingRequest( + PLINEDEV pLineDev + ); + +//**************************************************************************** +// Constant Parameters +//**************************************************************************** + +GETIDINFO aGetID[] = {{TEXT("tapi/line"), STRINGFORMAT_BINARY}, + {TEXT("comm"), STRINGFORMAT_ASCII}, + {TEXT("comm/datamodem"), STRINGFORMAT_BINARY}, + {TEXT("comm/datamodem/portname"), STRINGFORMAT_ASCII}, + {TEXT("ndis"), STRINGFORMAT_BINARY}}; +TCHAR g_szzClassList[] = {TEXT("tapi/line")TEXT("\0") + TEXT("comm")TEXT("\0") + TEXT("comm/datamodem")TEXT("\0") + TEXT("comm/datamodem/portname")TEXT("\0") + TEXT("ndis")TEXT("\0\0")}; +TCHAR g_szDeviceClass[] = TEXT("com"); + +// Generic string +// +TCHAR szNull[] = TEXT(""); +CHAR szSemicolon[] = ";"; +CHAR szAttachedTo[] = "AttachedTo"; + +//**************************************************************************** +//*********************** The Device ID Specific Calls************************ +//**************************************************************************** + +//**************************************************************************** +// LONG TSPIAPI TSPI_lineGetDevConfig(DWORD dwDeviceID, +// LPVARSTRING lpDeviceConfig, +// LPCSTR lpszDeviceClass) +// +// Functions: Get the modem configuration +// +// Return: ERROR_SUCCESS if successful +// LINEERR_INVALDEVICECLASS if the device class in invalid +// LINEERR_INVALPOINTER if the output buffer address is invalid +// LINEERR_STRUCTURETOOSMALL if the buffer is too small +// LINEERR_NODEVICE if the line ID is invalid +//**************************************************************************** + +LONG TSPIAPI TSPI_lineGetDevConfig(DWORD dwDeviceID, + LPVARSTRING lpDeviceConfig, + LPCTSTR lpszDeviceClass) +{ + PLINEDEV pLineDev=NULL; + LPBYTE lpCC; + DWORD cbSize; + DWORD dwRet; + LONG lRet = LINEERR_OPERATIONFAILED; // assume failure + + DBG_DDI_ENTER("TSPI_lineGetDevConfig"); + + TRACE3(IDEVENT_TSPFN_ENTER, IDFROM_TSPI_lineGetDevConfig, &dwDeviceID); + + // Validate the requested device class + // + if (!ValidateDevCfgClass(lpszDeviceClass)) + { + lRet = LINEERR_INVALDEVICECLASS; + goto end; + } + + // Validate the buffer + // + if (lpDeviceConfig == NULL) + { + lRet = LINEERR_INVALPOINTER; + goto end; + } + + if (lpDeviceConfig->dwTotalSize < sizeof(VARSTRING)) + { + lRet = LINEERR_STRUCTURETOOSMALL; + goto end; + } + + // Validate the device ID + // + if ((pLineDev = GetCBfromID(dwDeviceID)) == NULL) + { + lRet = LINEERR_NODEVICE; + goto end; + } + + ASSERT(pLineDev->pDevCfg != NULL); + +#ifdef DYNA_ADDREMOVE + // Fail if out-of-service + // + if (pLineDev->fdwResources&LINEDEVFLAGS_OUTOFSERVICE) + { + lRet = LINEERR_RESOURCEUNAVAIL; + goto end; + } +#endif // DYNA_ADDREMOVE + + // Validate the buffer size + // + cbSize = pLineDev->pDevCfg->dfgHdr.dwSize; + lpDeviceConfig->dwUsedSize = sizeof(VARSTRING); + lpDeviceConfig->dwNeededSize = sizeof(VARSTRING) + cbSize; + + if (lpDeviceConfig->dwTotalSize >= lpDeviceConfig->dwNeededSize) + { + // If the line is active, we need to get the current modem setting. + // + if (pLineDev->hDevice != INVALID_DEVICE) + { + DWORD cb = pLineDev->pDevCfg->commconfig.dwSize; + + // Set the modem configuration + // + UnimodemGetCommConfig(pLineDev, + &(pLineDev->pDevCfg->commconfig), + &cb); + }; + + // Fill with the default value + // + lpCC = (LPBYTE)(((LPBYTE)lpDeviceConfig) + sizeof(VARSTRING)); + CopyMemory(lpCC, (LPBYTE)pLineDev->pDevCfg, cbSize); + + lpDeviceConfig->dwStringFormat = STRINGFORMAT_BINARY; + lpDeviceConfig->dwStringSize = cbSize; + lpDeviceConfig->dwStringOffset = sizeof(VARSTRING); + lpDeviceConfig->dwUsedSize += cbSize; + }; + + + lRet = ERROR_SUCCESS; + + +end: + + if (pLineDev) RELEASE_LINEDEV(pLineDev); + + + TRACE4( + IDEVENT_TSPFN_EXIT, + IDFROM_TSPI_lineGetDevConfig, + &dwDeviceID, + lRet + ); + DBG_DDI_EXIT("TSPI_lineGetDevConfig", lRet); + + return lRet; +} + +//**************************************************************************** +// LONG TSPIAPI TSPI_lineSetDevConfig(DWORD dwDeviceID, +// LPVOID const lpDeviceConfig, +// DWORD dwSize, +// LPCSTR lpszDeviceClass) +// +// Functions: Set the modem configuration +// +// Return: ERROR_SUCCESS if successful +// LINEERR_INVALDEVICECLASS if the device class in invalid +// LINEERR_INVALPOINTER if the output buffer address is invalid +// LINEERR_NODEVICE if the line ID is invalid +// LINEERR_INVALPARAM if the buffer is invalid configuration +//**************************************************************************** + +LONG TSPIAPI TSPI_lineSetDevConfig(DWORD dwDeviceID, + LPVOID const lpDeviceConfig, + DWORD dwSize, + LPCTSTR lpszDeviceClass) +{ + PLINEDEV pLineDev; + PDEVCFG pDevCfg; + LONG lRet = LINEERR_OPERATIONFAILED; // assume failure + + DBG_DDI_ENTER("TSPI_lineSetDevConfig"); + + TRACE3( + IDEVENT_TSPFN_ENTER, + IDFROM_TSPI_lineSetDevConfig, + &dwDeviceID + ); + + // Validate the requested device class + // + if (!ValidateDevCfgClass(lpszDeviceClass)) + { + lRet = LINEERR_INVALDEVICECLASS; + goto end; + } + + // Validate the buffer, make sure it's dword aligned + // + if (lpDeviceConfig == NULL || ((DWORD)lpDeviceConfig & 3)) + { + ASSERT(FALSE); + lRet = LINEERR_INVALPOINTER; + goto end; + } + + if (dwSize < sizeof(DWORD)) { + lRet = LINEERR_INVALPARAM; + goto end; + } + + // Validate the device ID + // + if ((pLineDev = GetCBfromID(dwDeviceID)) == NULL) + { + lRet = LINEERR_NODEVICE; + goto end; + } + + ASSERT(pLineDev->pDevCfg != NULL); + + // Check the copied size + // + pDevCfg = pLineDev->pDevCfg; + if ((dwSize < pDevCfg->dfgHdr.dwSize) || + (pDevCfg->dfgHdr.dwVersion != ((LPDEVCFG)lpDeviceConfig)->dfgHdr.dwVersion)) + { + RELEASE_LINEDEV(pLineDev); + lRet = LINEERR_INVALPARAM; + goto end; + } + + // Get the new settings + // + SETWAITBONG(pDevCfg, GETWAITBONG(((LPDEVCFG)lpDeviceConfig))); + SETOPTIONS(pDevCfg, GETOPTIONS(((LPDEVCFG)lpDeviceConfig))); + + ASSERT(pDevCfg->commconfig.wVersion == ((LPDEVCFG)lpDeviceConfig)->commconfig.wVersion); + ASSERT(pDevCfg->commconfig.dwProviderSubType == + ((LPDEVCFG)lpDeviceConfig)->commconfig.dwProviderSubType); + ASSERT(pDevCfg->commconfig.dwProviderSize == + ((LPDEVCFG)lpDeviceConfig)->commconfig.dwProviderSize); + + pDevCfg->commconfig.dcb = ((LPDEVCFG)lpDeviceConfig)->commconfig.dcb; + CopyMemory(((LPBYTE)&pDevCfg->commconfig)+pDevCfg->commconfig.dwProviderOffset, + ((LPBYTE)&((LPDEVCFG)lpDeviceConfig)->commconfig)+((LPDEVCFG)lpDeviceConfig)->commconfig.dwProviderOffset, + ((LPDEVCFG)lpDeviceConfig)->commconfig.dwProviderSize); + + pLineDev->InitStringsAreValid=FALSE; + +#if 0 // ifdef'ed off because of bug win95b:21204. Don't pass down comm config when connected. + // If the line is active, we need to propagate the new setting to modem. + // + if (pLineDev->hDevice != INVALID_DEVICE) + { + // Set the modem configuration + // + UnimodemSetCommConfig(pLineDev, + &(pDevCfg->commconfig), + pDevCfg->commconfig.dwSize); + }; +#endif // 0 + + RELEASE_LINEDEV(pLineDev); + + lRet = ERROR_SUCCESS; + +end: + + TRACE4( + IDEVENT_TSPFN_EXIT, + IDFROM_TSPI_lineSetDevConfig, + &dwDeviceID, + lRet + ); + DBG_DDI_EXIT("TSPI_lineSetDevConfig", lRet); + + return lRet; +} + +//**************************************************************************** +// LONG TSPIAPI TSPI_lineGetDevCaps(DWORD dwDeviceID, +// DWORD dwTSPIVersion, +// DWORD dwExtVersion, +// LPLINEDEVCAPS lpLineDevCaps) +// +// Functions: Get the line capibilities +// +// Return: ERROR_SUCCESS if successful +// LINEERR_NODEVICE if the device ID is invalid +//**************************************************************************** + +LONG TSPIAPI TSPI_lineGetDevCaps(DWORD dwDeviceID, + DWORD dwTSPIVersion, + DWORD dwExtVersion, + LPLINEDEVCAPS lpLineDevCaps) +{ + PLINEDEV pLineDev=NULL; + TCHAR lpszProviderInfo[80]; + int cbProviderInfoLen, + cbLineNameLen, + cbDevSpecificLen, + cbDevClassLen, + cbAvailMem, +#ifdef UNICODE + cbDeviceKeyLen, +#endif // UNICODE + cbDWORDPad; + LONG lRet = LINEERR_OPERATIONFAILED; // assume failure + + DBG_DDI_ENTER("TSPI_lineGetDevCaps"); + + TRACE3( + IDEVENT_TSPFN_ENTER, + IDFROM_TSPI_lineGetDevCaps, + &dwDeviceID + ); + + + // Check the version + // + VALIDATE_VERSION(dwTSPIVersion); + + // Validate the device ID + // + if ((pLineDev = GetCBfromID(dwDeviceID)) == NULL) + { + lRet = LINEERR_NODEVICE; + goto end; + } + +#ifdef DYNA_ADDREMOVE + // Fail if out-of-service + // + if (pLineDev->fdwResources&LINEDEVFLAGS_OUTOFSERVICE) + { + lRet = LINEERR_RESOURCEUNAVAIL; + goto end; + } +#endif // DYNA_ADDREMOVE + + + // Check to see how much memory we'll need. + // + cbProviderInfoLen = sizeof(TCHAR) * (LoadString(ghInstance, + ID_PROVIDER_INFO, + lpszProviderInfo, + sizeof(lpszProviderInfo)/sizeof(TCHAR)) + + 1); + cbLineNameLen = sizeof(TCHAR) * (lstrlen(pLineDev->szDeviceName) + 1); + + lpLineDevCaps->dwUsedSize = sizeof(LINEDEVCAPS); + + cbAvailMem = (int) (lpLineDevCaps->dwTotalSize - lpLineDevCaps->dwUsedSize); + + // Enter the size we ideally need. + lpLineDevCaps->dwNeededSize = cbProviderInfoLen + cbLineNameLen + + lpLineDevCaps->dwUsedSize; + + // Copy in the provider info if it fits + if (cbAvailMem >= cbProviderInfoLen) + { + lstrcpy((LPTSTR)((LPBYTE)lpLineDevCaps + lpLineDevCaps->dwUsedSize), + lpszProviderInfo); + lpLineDevCaps->dwProviderInfoSize = cbProviderInfoLen; + lpLineDevCaps->dwProviderInfoOffset = lpLineDevCaps->dwUsedSize; + lpLineDevCaps->dwUsedSize += cbProviderInfoLen; + cbAvailMem -= cbProviderInfoLen; + } + + // Copy the name if it fits + if (cbAvailMem >= cbLineNameLen) + { + lstrcpy((LPTSTR)((LPBYTE)lpLineDevCaps + lpLineDevCaps->dwUsedSize), + pLineDev->szDeviceName); + lpLineDevCaps->dwLineNameSize = cbLineNameLen; + lpLineDevCaps->dwLineNameOffset = lpLineDevCaps->dwUsedSize; + lpLineDevCaps->dwUsedSize += cbLineNameLen; + cbAvailMem -= cbLineNameLen; + } + + lpLineDevCaps->dwPermanentLineID = MAKELONG(LOWORD(pLineDev->dwPermanentLineID), + LOWORD(gdwProviderID)); + lpLineDevCaps->dwStringFormat = STRINGFORMAT_ASCII; + + // Line address information + // + lpLineDevCaps->dwAddressModes = LINEADDRESSMODE_ADDRESSID; + lpLineDevCaps->dwNumAddresses = 1; + + // Bearer mode & information + // + lpLineDevCaps->dwMaxRate = pLineDev->dwMaxDCERate; + // + lpLineDevCaps->dwBearerModes = pLineDev->dwBearerModes; + + // Media mode + // + lpLineDevCaps->dwMediaModes = pLineDev->dwMediaModes; + + // Tones & Digits + // + //lpLineDevCaps->dwGenerateToneModes = 0; + //lpLineDevCaps->dwGenerateToneMaxNumFreq = 0; + //lpLineDevCaps->dwGenerateDigitModes = 0; + //lpLineDevCaps->dwMonitorToneMaxNumFreq = 0; + //lpLineDevCaps->dwMonitorToneMaxNumEntries = 0; + //lpLineDevCaps->dwMonitorDigitModes = 0; + //lpLineDevCaps->dwGatherDigitsMinTimeout = 0; + //lpLineDevCaps->dwGatherDigitsMaxTimeout = 0; + //lpLineDevCaps->dwMedCtlDigitMaxListSize = 0; + //lpLineDevCaps->dwMedCtlMediaMaxListSize = 0; + //lpLineDevCaps->dwMedCtlToneMaxListSize = 0; + //lpLineDevCaps->dwMedCtlCallStateMaxListSize = 0; + + // Line capabilities + // + // We can simulate wait-for-bong. + lpLineDevCaps->dwDevCapFlags = pLineDev->dwDevCapFlags | + LINEDEVCAPFLAGS_DIALBILLING | + LINEDEVCAPFLAGS_CLOSEDROP; + //lpLineDevCaps->dwAnswerMode = 0; + lpLineDevCaps->dwRingModes = 1; + // + lpLineDevCaps->dwMaxNumActiveCalls = 1; + + // Line device state to be notified + // + lpLineDevCaps->dwLineStates = LINEDEVSTATE_CONNECTED | + LINEDEVSTATE_DISCONNECTED | + LINEDEVSTATE_OPEN | + LINEDEVSTATE_CLOSE | + LINEDEVSTATE_INSERVICE | + LINEDEVSTATE_OUTOFSERVICE | + LINEDEVSTATE_REMOVED | + LINEDEVSTATE_RINGING | + LINEDEVSTATE_REINIT; + + // We do not support user-to-user information + // + //lpLineDevCaps->dwUUIAcceptSize = 0; + //lpLineDevCaps->dwUUIAnswerSize = 0; + //lpLineDevCaps->dwUUIMakeCallSize = 0; + //lpLineDevCaps->dwUUIDropSize = 0; + //lpLineDevCaps->dwUUISendUserUserInfoSize = 0; + //lpLineDevCaps->dwUUICallInfoSize = 0; + + // We do not support dial parameters setting + // + //lpLineDevCaps->MinDialParams.dwDialPause = 0; + //lpLineDevCaps->MinDialParams.dwDialSpeed = 0; + //lpLineDevCaps->MinDialParams.dwDigitDuration = 0; + //lpLineDevCaps->MinDialParams.dwWaitForDialtone = 0; + //lpLineDevCaps->MaxDialParams.dwDialPause = 0; + //lpLineDevCaps->MaxDialParams.dwDialSpeed = 0; + //lpLineDevCaps->MaxDialParams.dwDigitDuration = 0; + //lpLineDevCaps->MaxDialParams.dwWaitForDialtone = 0; + //lpLineDevCaps->DefaultDialParams.dwDialPause = 0; + //lpLineDevCaps->DefaultDialParams.dwDialSpeed = 0; + //lpLineDevCaps->DefaultDialParams.dwDigitDuration = 0; + //lpLineDevCaps->DefaultDialParams.dwWaitForDialtone = 0; + + // We do not support terminal settings + // + //lpLineDevCaps->dwNumTerminals = 0; + //lpLineDevCaps->dwTerminalCapsSize = 0; + //lpLineDevCaps->dwTerminalCapsOffset = 0; + //lpLineDevCaps->dwTerminalTextEntrySize = 0; + //lpLineDevCaps->dwTerminalTextSize = 0; + //lpLineDevCaps->dwTerminalTextOffset = 0; + + lpLineDevCaps->dwLineFeatures = LINEFEATURE_MAKECALL; + + // We will return this in the dev specific section: + // struct { + // DWORD dwContents; Set to 1 (indicates containing key) + // DWORD dwKeyOffset; Offset to key from start of this structure (8) + // BYTE rgby[...]; place containing null-terminated registry key. + // } + + // Since we need to store a DWORD, we need to calculate how much padding we need + // to add so that we are DWORD aligned. Only add padding if necessary. + cbDWORDPad = lpLineDevCaps->dwUsedSize % sizeof(DWORD); + if (cbDWORDPad >= 0) + { + cbDWORDPad = sizeof(DWORD) - cbDWORDPad; + } + +#ifdef UNICODE + cbDeviceKeyLen = WideCharToMultiByte(CP_ACP, + 0, + pLineDev->szDriverKey, + -1, + NULL, + 0, + NULL, + NULL); + + if (cbDeviceKeyLen == 0) + { + TSPPRINTF1("TSPI_lineGetDevCaps: WideCharToMultiByte() returned %d", + GetLastError()); + } + else + { + cbDeviceKeyLen++; + + cbDevSpecificLen = sizeof(DWORD) + + sizeof(DWORD) + + cbDeviceKeyLen; +#else // UNICODE + cbDevSpecificLen = sizeof(DWORD) + + sizeof(DWORD) + + lstrlen(pLineDev->szDriverKey) + 1; +#endif // UNICODE + + lpLineDevCaps->dwNeededSize += cbDevSpecificLen + cbDWORDPad; + + // Copy path if it fits + if (cbAvailMem >= cbDevSpecificLen + cbDWORDPad) + { + lpLineDevCaps->dwUsedSize += cbDWORDPad; + *(LPDWORD)((LPBYTE)lpLineDevCaps + lpLineDevCaps->dwUsedSize) = 1; + *(LPDWORD)((LPBYTE)lpLineDevCaps + lpLineDevCaps->dwUsedSize + sizeof(DWORD)) = 8; + +#ifdef UNICODE + WideCharToMultiByte(CP_ACP, + 0, + pLineDev->szDriverKey, + -1, + (LPSTR)((LPBYTE)lpLineDevCaps + + lpLineDevCaps->dwUsedSize + + sizeof(DWORD) + + sizeof(DWORD)), + cbDeviceKeyLen, + NULL, + NULL); +#else // UNICODE + lstrcpy((LPSTR)lpLineDevCaps + + lpLineDevCaps->dwUsedSize + + sizeof(DWORD) + + sizeof(DWORD), + pLineDev->szDriverKey); +#endif // UNICODE + + lpLineDevCaps->dwDevSpecificSize = cbDevSpecificLen; + lpLineDevCaps->dwDevSpecificOffset = lpLineDevCaps->dwUsedSize; + lpLineDevCaps->dwUsedSize += cbDevSpecificLen; + cbAvailMem -= cbDevSpecificLen + cbDWORDPad; + } +#ifdef UNICODE + } +#endif // UNICODE + + cbDevClassLen = sizeof(g_szzClassList); + lpLineDevCaps->dwNeededSize += cbDevClassLen; + + // Copy device classes if it fits + if (cbAvailMem >= cbDevClassLen) + { + hmemcpy((LPBYTE)lpLineDevCaps + lpLineDevCaps->dwUsedSize, + g_szzClassList, cbDevClassLen); + lpLineDevCaps->dwDeviceClassesSize = cbDevClassLen; + lpLineDevCaps->dwDeviceClassesOffset= lpLineDevCaps->dwUsedSize; + lpLineDevCaps->dwUsedSize += cbDevClassLen; + cbAvailMem -= cbDevClassLen; + } + + lRet = ERROR_SUCCESS; + +end: + + if (pLineDev) RELEASE_LINEDEV(pLineDev); + + + TRACE4( + IDEVENT_TSPFN_EXIT, + IDFROM_TSPI_lineGetDevCaps, + &dwDeviceID, + lRet + ); + DBG_DDI_EXIT("TSPI_lineGetDevCaps", lRet); + + return lRet; +} + +//**************************************************************************** +// LONG TSPIAPI TSPI_lineGetIcon(DWORD dwDeviceID, +// LPCSTR lpszDeviceClass, +// LPHICON lphIcon) +// +// Functions: Get the icon handle for the specific line +// +// Return: ERROR_SUCCESS if successful +// LINEERR_NODEVICE if the line ID is invalid +// LINEERR_OPERATIONFAILED if the parameter is invalid +//**************************************************************************** + +LONG TSPIAPI TSPI_lineGetIcon(DWORD dwDeviceID, + LPCTSTR lpszDeviceClass, + LPHICON lphIcon) +{ + PLINEDEV pLineDev; + LONG lRet = LINEERR_OPERATIONFAILED; // assume failure + + DBG_DDI_ENTER("TSPI_lineGetIcon"); + + TRACE3( + IDEVENT_TSPFN_ENTER, + IDFROM_TSPI_lineGetIcon, + &dwDeviceID + ); + + // Validate the buffer pointer + // + if (lphIcon == NULL) + { + goto end; + } + + // Validate the device ID + // + if ((pLineDev = GetCBfromID(dwDeviceID)) == NULL) + { + lRet = LINEERR_NODEVICE; + goto end; + } + + // Have we loaded this icon? + // + if (pLineDev->hIcon == NULL) + { + int iIcon; + + switch (pLineDev->bDeviceType) + { + case DT_NULL_MODEM: iIcon = IDI_NULL; break; + case DT_EXTERNAL_MODEM: iIcon = IDI_EXT_MDM; break; + case DT_INTERNAL_MODEM: iIcon = IDI_INT_MDM; break; + case DT_PCMCIA_MODEM: iIcon = IDI_PCM_MDM; break; + default: iIcon = -1; break; + }; + + // Nope! load one and save it + // + if (iIcon != -1) + { + pLineDev->hIcon = LoadIcon(ghInstance, MAKEINTRESOURCE(iIcon)); + }; + }; + + // Return this icon (even if NULL, return SUCCESS. tapi will provide + // a default icon if necessary) + // + *lphIcon = pLineDev->hIcon; + + // Release the modem CB + // + RELEASE_LINEDEV(pLineDev); + + lRet = ERROR_SUCCESS; + +end: + + TRACE4( + IDEVENT_TSPFN_EXIT, + IDFROM_TSPI_lineGetIcon, + &dwDeviceID, + lRet + ); + DBG_DDI_EXIT("TSPI_lineGetIcon", lRet); + + return lRet; +} + + + +//**************************************************************************** +//************************** The Line Specific Calls************************** +//**************************************************************************** + +//**************************************************************************** +// LONG TSPIAPI TSPI_lineOpen(DWORD dwDeviceID, +// HTAPILINE htLine, +// LPHDRVLINE lphdLine, +// DWORD dwTSPIVersion, +// LINEEVENT lineEventProc) +// +// Functions: Associates the modem CB with the TAPI handle. +// +// Returns: ERROR_SUCCESS if a modem CB can be associated +// LINEERR_NODEVICE if the device ID cannot be found +// +// History: +// Mon 17-Apr-1995 14:45:00 -by- Viroon Touranachun [viroont] +// Created. +// +//**************************************************************************** + +LONG TSPIAPI TSPI_lineOpen(DWORD dwDeviceID, + HTAPILINE htLine, + LPHDRVLINE lphdLine, + DWORD dwTSPIVersion, + LINEEVENT lineEventProc) +{ + PLINEDEV pLineDev=NULL; + LONG lRet = LINEERR_OPERATIONFAILED; // assume failure + + + DBG_DDI_ENTER("TSPI_lineOpen"); + + TRACE3( + IDEVENT_TSPFN_ENTER, + IDFROM_TSPI_lineOpen, + &dwDeviceID + ); + + + // Check the version + // + VALIDATE_VERSION(dwTSPIVersion); + + // Validate the device ID + // + if ((pLineDev = GetCBfromID(dwDeviceID)) == NULL) + { + lRet = LINEERR_NODEVICE; + goto end; + } + + +#ifdef DYNA_ADDREMOVE + // Fail if out-of-service + // + if (pLineDev->fdwResources&LINEDEVFLAGS_OUTOFSERVICE) + { + lRet = LINEERR_RESOURCEUNAVAIL; + goto end; + } +#endif // DYNA_ADDREMOVE + + + // Update the line device + // + *lphdLine = (HDRVLINE)pLineDev; + + if (TRACINGENABLED()) + { + lineEventProc = traceSetEventProc(lineEventProc); + } + +#ifdef DEBUG + DebugSetEventProc(lineEventProc); + pLineDev->lpfnEvent = DebugEventProc; +#else // DEBUG + pLineDev->lpfnEvent = lineEventProc; +#endif // DEBUG + + pLineDev->htLine = htLine; + + // If we need to re-read the default comm config, we do this here. + if (pLineDev->fUpdateDefaultCommConfig) + { + + DPRINTF("Updating DefaultCommConfig"); + RefreshDefaultCommConfig(pLineDev); + pLineDev->fUpdateDefaultCommConfig = FALSE; // We set it to false + // regardless of whether + // the refresh succeeded + // or not. + } + + lRet = ERROR_SUCCESS; + +end: + + if (pLineDev) {RELEASE_LINEDEV(pLineDev);} + + TRACE4( + IDEVENT_TSPFN_EXIT, + IDFROM_TSPI_lineOpen, + &dwDeviceID, + lRet + ); + DBG_DDI_EXIT("TSPI_lineOpen", lRet); + + return lRet; +} + +//**************************************************************************** +// LONG TSPIAPI TSPI_lineSetDefaultMediaDetection(HDRVLINE hdLine, +// DWORD dwMediaModes) +// +// Functions: Enables the opened line to detect an inbound call. +// +// Returns: ERROR_SUCCESS if a modem CB can be associated +// LINEERR_INVALIDHANDLE if the line handle is invalid +// LINEERR_INVALMEDIAMODE if requested media modes not supported +// +// History: +// Mon 17-Apr-1995 14:45:00 -by- Viroon Touranachun [viroont] +// Created. +//**************************************************************************** + +LONG TSPIAPI TSPI_lineSetDefaultMediaDetection(HDRVLINE hdLine, + DWORD dwMediaModes) +{ + PLINEDEV pLineDev; + DWORD dwRet = LINEERR_OPERATIONFAILED; // assume failure + + DBG_HDL_ENTER("TSPI_lineSetDefaultMediaDetection"); + + TRACE3( + IDEVENT_TSPFN_ENTER, + IDFROM_TSPI_lineSetDefaultMediaDetection, + &hdLine + ); + + + if ((pLineDev = GetCBfromHandle ((DWORD)hdLine)) == NULL) + { + dwRet = LINEERR_INVALLINEHANDLE; + goto end; + } + + // Check the requested modes. There must be only our media modes. + // In addition, don't allow INTERACTIVEVOICE to be used for listening. + // + if (dwMediaModes & ~(pLineDev->dwMediaModes & ~LINEMEDIAMODE_INTERACTIVEVOICE)) + { + dwRet = LINEERR_INVALMEDIAMODE; + } + else + { + // If no detection and a detection is requested + // + if ((pLineDev->dwDetMediaModes == 0) && (dwMediaModes)) + { + // Open the modem + // + if ((dwRet = DevlineOpen(pLineDev)) == ERROR_SUCCESS) + { + // Start listening to the port + // + if ((dwRet = DevlineDetectCall(pLineDev)) == ERROR_SUCCESS) + { + // The modem is now monitoring the call. + // Remember the media mode we are monitoring + // + pLineDev->dwDetMediaModes = dwMediaModes; + } + else + { + // We cannot monitor the call, close the modem + // + DevlineClose(pLineDev); + } + } + else + { + // Handle the case of LINEERR_ALLOCATED being returned from DevlineOpen, + // indicating there is an already open port. + // + if (LINEERR_ALLOCATED == dwRet) + { + // Just remember the detection media modes. + // return ERROR_SUCCESS because we will comeback to monitor the call + // when this call is deallocated. + // + pLineDev->dwDetMediaModes = dwMediaModes; + dwRet = ERROR_SUCCESS; + } + } + } + else + { + // we are stopping detection OR adjusting the detection media modes + // + pLineDev->dwDetMediaModes = dwMediaModes; + + // If we are detecting and requested not to, + // just close the line if it isn't in use + // + if (pLineDev->dwDetMediaModes && + dwMediaModes == 0 && + (DEVST_PORTLISTENING == pLineDev->DevState || + DEVST_PORTLISTENINIT == pLineDev->DevState)) + { + // Close the modem + // + DevlineClose(pLineDev); + +#ifdef UNDER_CONSTRUCTION + // If we are out of service + // + if (pLineDev->fdwResources & LINEDEVFLAGS_OUTOFSERVICE) + { + // Clean up the control block + // + DevlineDisabled (pLineDev); + }; +#endif // UNDER_CONSTRUCTION + }; + + dwRet = ERROR_SUCCESS; + }; + }; + + // Release the modem CB + // + RELEASE_LINEDEV(pLineDev); + +end: + + TRACE4( + IDEVENT_TSPFN_EXIT, + IDFROM_TSPI_lineSetDefaultMediaDetection, + &hdLine, + dwRet + ); + DBG_HDL_EXIT("TSPI_lineSetDefaultMediaDetection", dwRet); + + return dwRet; +} + +//**************************************************************************** +// LONG TSPIAPI TSPI_lineConditionalMediaDetection(HDRVLINE hdLine, +// DWORD dwMediaModes, +// LPLINECALLPARAMS const lpCallParams) +// +// Functions: Determines whether the line supports the specified media modes +// and call parameters. +// +// Return: ERROR_SUCCESS if successful +// LINEERR_INVALLINEHANDLE the line handle is invalid +// LINEERR_INVALMEDIAMODE the media mode or the call parameter is +// not supported +// LINEERR_RESOURCEUNAVAIL the outbound call cannot be made +//**************************************************************************** + +LONG TSPIAPI TSPI_lineConditionalMediaDetection(HDRVLINE hdLine, + DWORD dwMediaModes, + LPLINECALLPARAMS const lpCallParams) +{ + PLINEDEV pLineDev; + DWORD dwRet = ERROR_SUCCESS; + + DBG_HDL_ENTER("TSPI_lineConditionalMediaDetection"); + + TRACE3( + IDEVENT_TSPFN_ENTER, + IDFROM_TSPI_lineConditionalMediaDetection, + &hdLine + ); + + if ((pLineDev = GetCBfromHandle ((DWORD)hdLine)) == NULL) + { + dwRet = LINEERR_INVALLINEHANDLE; + goto end; + } + + // Check the requested modes. There must be only our media modes. + // + if (dwMediaModes & ~pLineDev->dwMediaModes) + { + dwRet = LINEERR_INVALMEDIAMODE; + } + else + { + // Check the call paramaters + // + if ((lpCallParams->dwBearerMode & (~pLineDev->dwBearerModes)) || + (lpCallParams->dwMediaMode & (~pLineDev->dwMediaModes)) || + (lpCallParams->dwAddressMode & (~LINEADDRESSMODE_ADDRESSID))) + { + dwRet = LINEERR_INVALMEDIAMODE; + }; + }; + + if (dwRet == ERROR_SUCCESS) + { + // Check whether we can make an outbound call + // + if (pLineDev->dwCall & (CALL_ACTIVE | CALL_ALLOCATED)) + { + dwRet = LINEERR_RESOURCEUNAVAIL; + }; + }; + + // Release the modem CB + // + RELEASE_LINEDEV(pLineDev); + +end: + + TRACE4( + IDEVENT_TSPFN_EXIT, + IDFROM_TSPI_lineConditionalMediaDetection, + &hdLine, + dwRet + ); + DBG_HDL_EXIT("TSPI_lineConditionalMediaDetection", dwRet); + + return dwRet; +} + +//**************************************************************************** +// LONG TSPIAPI TSPI_lineGetID(HDRVLINE hdLine, +// DWORD dwAddressID, +// HDRVCALL hdCall, +// DWORD dwSelect, +// LPVARSTRING lpDeviceID, +// LPCSTR lpszDeviceClass, +// HANDLE hTargetProcess) +// +// Functions: Get the line information based on the requested class +// +// Return: ERROR_SUCCESS if successful +// LINEERR_INVALADDRESSID the address ID is invalid +// LINEERR_INVALLINEHANDLE the line handle is invalid +// LINEERR_INVALCALLHANDLE the call handle is invalid +// LINEERR_OPERATIONFAILED the device class is not supported +//**************************************************************************** + +LONG TSPIAPI TSPI_lineGetID(HDRVLINE hdLine, + DWORD dwAddressID, + HDRVCALL hdCall, + DWORD dwSelect, + LPVARSTRING lpDeviceID, + LPCTSTR lpszDeviceClass, + HANDLE hTargetProcess) +{ + PLINEDEV pLineDev; + UINT cbPort; + UINT idClass; + DWORD dwRet = ERROR_SUCCESS; + +#ifdef DEBUG + if (dwSelect == LINECALLSELECT_LINE) + { + DBG_HDL_ENTER("TSPI_lineGetID"); + } + else + { + if (dwSelect == LINECALLSELECT_CALL) + { + DBG_HDC_ENTER("TSPI_lineGetID"); + } + else + { + DBG_ENTER("TSPI_lineGetID"); + } + } +#endif // DEBUG + + TRACE3( + IDEVENT_TSPFN_ENTER, + IDFROM_TSPI_lineGetID, + &hdLine + ); + + + switch (dwSelect) + { + case LINECALLSELECT_ADDRESS: + if (dwAddressID != 0) + { + dwRet = LINEERR_INVALADDRESSID; + goto end; + } + // FALLTHROUGH + + case LINECALLSELECT_LINE: + if ((pLineDev = GetCBfromHandle ((DWORD)hdLine)) == NULL) + { + dwRet = LINEERR_INVALLINEHANDLE; + goto end; + } + break; + + case LINECALLSELECT_CALL: + if ((pLineDev = GetCBfromHandle ((DWORD)hdCall)) == NULL) + { + dwRet = LINEERR_INVALCALLHANDLE; + goto end; + } + break; + + default: + dwRet = LINEERR_OPERATIONFAILED; + goto end; + } + + +#ifdef DYNA_ADDREMOVE + // Fail if out-of-service + // + if (pLineDev->fdwResources&LINEDEVFLAGS_OUTOFSERVICE) + { + dwRet = LINEERR_RESOURCEUNAVAIL; + goto end; + } +#endif // DYNA_ADDREMOVE + + + // Determine the device class + // + for (idClass = 0; idClass < MAX_SUPPORT_CLASS; idClass++) + { + if (lstrcmpi(lpszDeviceClass, aGetID[idClass].szClassName) == 0) + break; + }; + + + // Determine the required size + // + switch (idClass) + { + case TAPILINE: + cbPort = sizeof(DWORD); + break; + + case COMM: +#ifdef UNICODE + cbPort = WideCharToMultiByte(CP_ACP, + 0, + pLineDev->szDeviceName, + -1, + NULL, + 0, + NULL, + NULL); + if (cbPort == 0) + { + dwRet = LINEERR_OPERATIONFAILED; + } +#else // UNICODE + cbPort = lstrlen(pLineDev->szDeviceName) + 1; +#endif // UNICODE + break; + + case COMMMODEM: +#ifdef UNICODE + cbPort = WideCharToMultiByte(CP_ACP, + 0, + pLineDev->szDeviceName, + -1, + NULL, + 0, + NULL, + NULL) + sizeof(DWORD); + if (cbPort == 0) + { + dwRet = LINEERR_OPERATIONFAILED; + } +#else // UNICODE + cbPort = lstrlen(pLineDev->szDeviceName) + 1 + sizeof(DWORD); +#endif // UNICODE + break; + + case COMMMODEMPORTNAME: + { + HKEY hKey; + DWORD dwSize, dwType; + + if (ERROR_SUCCESS == RegOpenKey(HKEY_LOCAL_MACHINE, + pLineDev->szDriverKey, + &hKey)) + { + // Check on the length of an ANSI return string. + if (ERROR_SUCCESS == RegQueryValueExA(hKey, + szAttachedTo, + NULL, + &dwType, + NULL, + &dwSize)) + { + cbPort = dwSize; + } + else + { + // If we aren't attached to anything return a null string. + cbPort = 1; + } + + RegCloseKey(hKey); + } + } + break; + + case NDIS: +#ifdef UNICODE + cbPort = WideCharToMultiByte(CP_ACP, + 0, + g_szDeviceClass, + -1, + NULL, + 0, + NULL, + NULL) + sizeof(DWORD); + if (cbPort == 0) + { + dwRet = LINEERR_OPERATIONFAILED; + } +#else // UNICODE + cbPort = sizeof(g_szDeviceClass) + sizeof(DWORD); +#endif // UNICODE + break; + + default: + dwRet = LINEERR_OPERATIONFAILED; + break; + }; + + // Calculate the require size + // + // lpDeviceID->dwUsedSize = sizeof(VARSTRING); // TAPI fills it in. + // + if (dwRet == ERROR_SUCCESS) + { + // BUG! BUG! Do we need to check dwTotalSize? + // Tue 03-Oct-1995 09:23:01 -by- Viroon Touranachun [viroont] + // + + // Return the structure information + // + lpDeviceID->dwNeededSize = sizeof(VARSTRING) + cbPort; + lpDeviceID->dwStringFormat = aGetID[idClass].dwFormat; + ASSERT(lpDeviceID->dwUsedSize == sizeof(VARSTRING)); + + // Check for the extra space for more information + // + if ((lpDeviceID->dwTotalSize - lpDeviceID->dwUsedSize) >= + cbPort) + { + // We have enough space to return valid information + // + lpDeviceID->dwStringSize = cbPort; + lpDeviceID->dwStringOffset = sizeof(VARSTRING); + lpDeviceID->dwUsedSize += cbPort; + + // Return the useful information + // + switch (idClass) + { + // "tapi/line" returns the line device ID + // + case TAPILINE: + { + LPDWORD lpdwDeviceID; + + lpdwDeviceID = (LPDWORD)(((LPBYTE)lpDeviceID) + sizeof(VARSTRING)); + *lpdwDeviceID = pLineDev->dwID; + break; + } + + // "comm" returns the modem name + // + case COMM: + { +#ifdef UNICODE + if (0 == + WideCharToMultiByte(CP_ACP, + 0, + pLineDev->szDeviceName, + -1, + (LPSTR)((LPBYTE)lpDeviceID + sizeof(VARSTRING)), + cbPort, + NULL, + NULL)) + { + dwRet = LINEERR_OPERATIONFAILED; + } +#else // UNICODE + lstrcpyn(((LPSTR)lpDeviceID) + sizeof(VARSTRING), + pLineDev->szDeviceName, cbPort); +#endif // UNICODE + break; + } + + // "comm/datamodem" returns the Win32 comm handle (if any) and + // the modem name + // + case COMMMODEM: + { + LPHANDLE lphClientDevice; + + // Duplicate a Win32 comm handle (for the caller process) + // + lphClientDevice = (LPHANDLE) + (((LPBYTE)lpDeviceID) + sizeof(VARSTRING)); + + if (pLineDev->hDevice != INVALID_DEVICE) + { + HANDLE hDevice; + TCHAR szPort[MAXDEVICENAME+1]; + + // Initialize szPort to be "\\.\" + lstrcpy(szPort, cszDevicePrefix); + + // Concatenate FriendlyName onto szPort to form "\\.\Modem Name" + lstrcat(szPort, pLineDev->szDeviceName); + + hDevice = CreateFile(szPort, + GENERIC_WRITE | GENERIC_READ, + FILE_SHARE_WRITE | FILE_SHARE_READ, + NULL, + OPEN_EXISTING, + FILE_FLAG_OVERLAPPED, + NULL); + + if (hDevice != INVALID_HANDLE_VALUE) + { + if (!DuplicateHandle(GetCurrentProcess(), + hDevice, + hTargetProcess, + lphClientDevice, + 0L, FALSE, + DUPLICATE_SAME_ACCESS)) + { + DPRINTF1("lineGetID DuplicateHandle() failed! (%d)", + GetLastError); + *lphClientDevice = NULL; + dwRet = LINEERR_OPERATIONFAILED; + } + + CloseHandle(hDevice); + } + else + { + DPRINTF1("lineGetID CreateFile() failed! (%d)", GetLastError); + *lphClientDevice = NULL; + } + } + else + { + *lphClientDevice = NULL; + }; + + // Also return the modem name + // +#ifdef UNICODE + if (ERROR_SUCCESS == dwRet && + 0 == WideCharToMultiByte(CP_ACP, + 0, + pLineDev->szDeviceName, + -1, + (LPSTR)(lphClientDevice + 1), + cbPort - sizeof(DWORD), + NULL, + NULL)) + { + dwRet = LINEERR_OPERATIONFAILED; + } +#else // UNICODE + lstrcpy((LPSTR)(lphClientDevice+1), pLineDev->szDeviceName); +#endif // UNICODE + break; + } + + // "comm/datamodem/portname" returns the name of the port the modem + // is attached to or the modem name itself if not attached to anything. + // + case COMMMODEMPORTNAME: + { + HKEY hKey; + DWORD dwSize, dwType; + + if (ERROR_SUCCESS == RegOpenKey(HKEY_LOCAL_MACHINE, + pLineDev->szDriverKey, + &hKey)) + { + dwSize = cbPort; + // Check on the length of an ANSI return string. + if (ERROR_SUCCESS != RegQueryValueExA( + hKey, + szAttachedTo, + NULL, + &dwType, + (LPBYTE)lpDeviceID + + sizeof(VARSTRING), + &dwSize)) + { + // If we aren't attached to anything return a null + // string. + *(LPSTR)((LPBYTE)lpDeviceID + sizeof(VARSTRING)) = 0; + } + + RegCloseKey(hKey); + } + } + break; + + // "ndis" returns the device class and handle which can be used by + // the NDIS device driver + // + case NDIS: + { + LPDWORD lpdwDeviceID; + + // The NDIS device handle is ring_0 comm handle + // + lpdwDeviceID = (LPDWORD)(((LPBYTE)lpDeviceID) + sizeof(VARSTRING)); + + DPRINTF ("Someone wants NDIS class info. Return ring-3 comm handle."); + + *lpdwDeviceID = (DWORD)(pLineDev->hDevice != INVALID_DEVICE ? + pLineDev->hDevice : NULL); + + // Also returns the device class + // +#ifdef UNICODE + if (0 == WideCharToMultiByte(CP_ACP, + 0, + g_szDeviceClass, + -1, + (LPSTR)(lpdwDeviceID + 1), + cbPort, + NULL, + NULL)) + { + dwRet = LINEERR_OPERATIONFAILED; + } +#else // UNICODE + lstrcpy((LPSTR)(lpdwDeviceID+1), g_szDeviceClass); +#endif // UNICODE + break; + } + }; + }; + }; + + // Release the modem CB + // + RELEASE_LINEDEV(pLineDev); + +end: + + TRACE4( + IDEVENT_TSPFN_EXIT, + IDFROM_TSPI_lineGetID, + &hdLine, + dwRet + ); + +#ifdef DEBUG + if (dwSelect == LINECALLSELECT_LINE) + { + DBG_HDL_EXIT("TSPI_lineGetID", dwRet); + } + else + { + if (dwSelect == LINECALLSELECT_CALL) + { + DBG_HDC_EXIT("TSPI_lineGetID", dwRet); + } + else + { + DBG_EXIT_UL("TSPI_lineGetID", dwRet); + } + } +#endif // DEBUG + + return dwRet; +} + +//**************************************************************************** +// LONG TSPIAPI TSPI_lineGetLineDevStatus(HDRVLINE hdLine, +// LPLINEDEVSTATUS lpLineDevStatus) +// +// Functions: Get the current state of the line device +// +// Return: ERROR_SUCCESS if successful +// LINEERR_INVALLINEHANDLE if invalid line handle +//**************************************************************************** + +LONG TSPIAPI TSPI_lineGetLineDevStatus(HDRVLINE hdLine, + LPLINEDEVSTATUS lpLineDevStatus) +{ + PLINEDEV pLineDev; + LONG lRet = LINEERR_OPERATIONFAILED; // assume failure + + TRACE3( + IDEVENT_TSPFN_ENTER, + IDFROM_TSPI_lineGetLineDevStatus, + &hdLine + ); + + DBG_HDL_ENTER("TSPI_lineGetLineDevStatus"); + + if ((pLineDev = GetCBfromHandle ((DWORD)hdLine)) == NULL) + { + lRet = LINEERR_INVALLINEHANDLE; + goto end; + } + + // No device specifc portion + // + lpLineDevStatus->dwUsedSize = sizeof(LINEDEVSTATUS); + lpLineDevStatus->dwNeededSize = sizeof(LINEDEVSTATUS); + + // Call information + // + //lpLineDevStatus->dwNumOnHoldCalls = 0; + //lpLineDevStatus->dwNumOnHoldPendCalls = 0; + //lpLineDevStatus->dwNumCallCompletions = 0; + //lpLineDevStatus->dwRingMode = 0; + // + if (pLineDev->dwCall & CALL_ACTIVE) + { + lpLineDevStatus->dwNumActiveCalls = 1; + lpLineDevStatus->dwLineFeatures = 0; + lpLineDevStatus->dwAvailableMediaModes = 0; + } + else + { + lpLineDevStatus->dwNumActiveCalls = 0; + + if (pLineDev->dwCall & CALL_ALLOCATED) + { + lpLineDevStatus->dwLineFeatures = 0; + lpLineDevStatus->dwAvailableMediaModes = 0; + } + else + { + lpLineDevStatus->dwLineFeatures = LINEFEATURE_MAKECALL; + lpLineDevStatus->dwAvailableMediaModes = pLineDev->dwMediaModes; + }; + }; + + // Line hardware information + // + lpLineDevStatus->dwSignalLevel = 0x0000FFFF; + lpLineDevStatus->dwBatteryLevel = 0x0000FFFF; + lpLineDevStatus->dwRoamMode = LINEROAMMODE_UNAVAIL; + + // Always allow TAPI calls + // + lpLineDevStatus->dwDevStatusFlags = LINEDEVSTATUSFLAGS_CONNECTED; + if (!(pLineDev->fdwResources & LINEDEVFLAGS_OUTOFSERVICE)) + { + lpLineDevStatus->dwDevStatusFlags |= LINEDEVSTATUSFLAGS_INSERVICE; + }; + + // No terminal settings + // + //lpLineDevStatus->dwTerminalModesSize = 0; + //lpLineDevStatus->dwTerminalModesOffset = 0; + + // No device specific + // + //lpLineDevStatus->dwDevSpecificSize = 0; + //lpLineDevStatus->dwDevSpecificOffset = 0; + + //lpLineDevStatus->dwAppInfoSize = 0; + //lpLineDevStatus->dwAppInfoOffset = 0; + + // Release the modem CB + // + RELEASE_LINEDEV(pLineDev); + + lRet = ERROR_SUCCESS; + +end: + + TRACE4( + IDEVENT_TSPFN_EXIT, + IDFROM_TSPI_lineGetLineDevStatus, + &hdLine, + lRet + ); + + DBG_HDL_EXIT("TSPI_lineGetLineDevStatus", lRet); + return lRet; +} + +//**************************************************************************** +// LONG TSPIAPI TSPI_lineGetNumAddressIDs(HDRVLINE hdLine, +// LPDWORD lpNumAddressIDs) +// +// Functions: Get the number of addresses for the line handle +// +// Return: ERROR_SUCCESS if successful +// LINEERR_INVALLINEHANDLE if invalid line handle +//**************************************************************************** + +LONG TSPIAPI TSPI_lineGetNumAddressIDs(HDRVLINE hdLine, + LPDWORD lpNumAddressIDs) +{ + PLINEDEV pLineDev; + LONG lRet = LINEERR_OPERATIONFAILED; // assume failure + + DBG_HDL_ENTER("TSPI_lineGetNumAddressIDs"); + + TRACE3( + IDEVENT_TSPFN_ENTER, + IDFROM_TSPI_lineGetNumAddressIDs, + &hdLine + ); + + // Validate the line handle + // + if ((pLineDev = GetCBfromHandle ((DWORD)hdLine)) == NULL) + { + lRet = LINEERR_INVALLINEHANDLE; + goto end; + } + RELEASE_LINEDEV(pLineDev); + + // We only support one address. + // + *lpNumAddressIDs = 1; + lRet = ERROR_SUCCESS; + +end: + + TRACE4( + IDEVENT_TSPFN_EXIT, + IDFROM_TSPI_lineGetNumAddressIDs, + &hdLine, + lRet + ); + DBG_HDL_EXIT("TSPI_lineGetNumAddressIDs", lRet); + + return lRet; +} + +//**************************************************************************** +// LONG TSPIAPI TSPI_lineSetStatusMessages(HDRVLINE hdLine, +// DWORD dwLineStates, +// DWORD dwAddressStates) +// +// Functions: Sets the line notification mask +// +// Return: ERROR_SUCCESS if successful +// LINEERR_INVALLINEHANDLE if invalid line handle +//**************************************************************************** + +LONG TSPIAPI TSPI_lineSetStatusMessages(HDRVLINE hdLine, + DWORD dwLineStates, + DWORD dwAddressStates) +{ + PLINEDEV pLineDev; + LONG lRet = LINEERR_OPERATIONFAILED; // assume failure + + DBG_HDL_ENTER("TSPI_lineSetStatusMessages"); + + TRACE3( + IDEVENT_TSPFN_ENTER, + IDFROM_TSPI_lineSetStatusMessages, + &hdLine + ); + + // Validate the line handle + // + if ((pLineDev = GetCBfromHandle ((DWORD)hdLine)) == NULL) + { + lRet = LINEERR_INVALLINEHANDLE; + goto end; + } + + RELEASE_LINEDEV(pLineDev); + + // BUG! BUG! we should record this settings and filter the notification + // based on this settings. + // + // Mon 14-Feb-1994 13:09:57 -by- Viroon Touranachun [viroont] + // + lRet = ERROR_SUCCESS; + +end: + + DBG_HDL_EXIT("TSPI_lineSetStatusMessages", lRet); + + TRACE4( + IDEVENT_TSPFN_EXIT, + IDFROM_TSPI_lineSetStatusMessages, + &hdLine, + lRet + ); + + return lRet; +} + +//**************************************************************************** +// LONG TSPIAPI TSPI_lineClose(HDRVLINE hdLine) +// +// Functions: Closes the line +// +// Return: ERROR_SUCCESS if successful +// LINEERR_OPERATIONFAILED if invalid line handle +//**************************************************************************** + +LONG TSPIAPI TSPI_lineClose(HDRVLINE hdLine) +{ + PLINEDEV pLineDev; + LONG lRet = LINEERR_OPERATIONFAILED; + + DBG_HDL_ENTER("TSPI_lineClose"); + + TRACE3(IDEVENT_TSPFN_ENTER, IDFROM_TSPI_lineClose, &hdLine); + + if ((pLineDev = GetCBfromHandle ((DWORD)hdLine)) == NULL) + { + goto end; + } + + // Make sure that we do not leave anything open + // + DevlineClose(pLineDev); + +#ifdef UNDER_CONSTRUCTION + // If we are out of service, clean up and bail out + // + if (pLineDev->fdwResources & LINEDEVFLAGS_OUTOFSERVICE) + { + DevlineDisabled (pLineDev); + } + else +#endif // UNDER_CONSTRUCTION + { + // Reinit the line device + // + NullifyLineDevice(pLineDev); + }; + + // Release the modem CB + // + RELEASE_LINEDEV(pLineDev); + + lRet=ERROR_SUCCESS; + +end: + + TRACE4(IDEVENT_TSPFN_EXIT, IDFROM_TSPI_lineClose, &hdLine, lRet); + DBG_HDL_EXIT("TSPI_lineClose", lRet); + + return lRet; +} + +//**************************************************************************** +//************************** The Call Specific Calls************************** +//**************************************************************************** + +//**************************************************************************** +// LONG TSPIAPI TSPI_lineMakeCall(DRV_REQUESTID dwRequestID, +// HDRVLINE hdLine, +// HTAPICALL htCall, +// LPHDRVCALL lphdCall, +// LPCSTR lpszDestAddress, +// DWORD dwCountryCode, +// LPLINECALLPARAMS const lpCallParams) +// +// Functions: Sets up the outbound call and start dialing if the destination +// number is provided +// +// Return: A positive pending ID number (dwRequestID) if successful +// LINEERR_INVALLINEHANDLE An invalid line handle +// LINEERR_CALLUNAVAIL No call is available for the line +// LINEERR_INVALMEDIAMODE The requested mediamode is invalid +// LINEERR_INVALBEARERMODE The requested bearer mode is invalid +// LINEERR_OPERATIONFAILED The call cannot be made. +//**************************************************************************** + +LONG TSPIAPI TSPI_lineMakeCall(DRV_REQUESTID dwRequestID, + HDRVLINE hdLine, + HTAPICALL htCall, + LPHDRVCALL lphdCall, + LPCTSTR lpszDestAddress, + DWORD dwCountryCode, + LPLINECALLPARAMS const lpCallParams) +{ + PLINEDEV pLineDev; + DWORD dwRet=LINEERR_OPERATIONFAILED; + BOOL fDoTakeover = FALSE; + + DBG_HDL_ENTER("TSPI_lineMakeCall"); + + TRACE3( + IDEVENT_TSPFN_ENTER, + IDFROM_TSPI_lineMakeCall, + &dwRequestID + ); + + // Validate the line handle + // + if ((pLineDev = GetCBfromHandle ((DWORD)hdLine)) == NULL) + { + DBG_HDL_EXIT("TSPI_lineMakeCall", LINEERR_INVALLINEHANDLE); + dwRet = LINEERR_INVALLINEHANDLE; + goto end; + } + + // See if we have a free call struct. + if (pLineDev->dwCall & CALL_ALLOCATED) + { + RELEASE_LINEDEV(pLineDev); + DBG_HDL_EXIT("TSPI_lineMakeCall", LINEERR_CALLUNAVAIL); + dwRet = LINEERR_CALLUNAVAIL; + goto end; + }; + + ASSERT(pLineDev->pDevCfg != NULL); + + // If a line config is specified in the callparams struct, + // set it to the line + // + if (lpCallParams) + { + if (lpCallParams->dwDeviceConfigSize != 0) + { + // We will tolerate the failure if the line config in the callparams + // struct cannot be set. + // + TSPI_lineSetDevConfig(pLineDev->dwID, + (LPVOID)(((LPBYTE)lpCallParams)+lpCallParams->dwDeviceConfigOffset), + lpCallParams->dwDeviceConfigSize, + lpCallParams->dwDeviceClassSize == 0 ? szNull : + (LPTSTR)(((LPBYTE)lpCallParams)+lpCallParams->dwDeviceClassOffset)); + }; + }; + + // Set default dwDialOptions + pLineDev->dwDialOptions = pLineDev->dwModemOptions & MDM_MASK; // Get modem caps + pLineDev->dwDialOptions &= ((LPMODEMSETTINGS)&((LPCOMMCONFIG)&(pLineDev->pDevCfg + ->commconfig))->wcProviderData[0])->dwPreferredModemOptions; + + + + // Examine LINECALLPARAMS, if present + if (lpCallParams) + { + // verify media mode +#ifdef VOICEVIEW + if ((lpCallParams->dwMediaMode & ~pLineDev->dwMediaModes) || + (lpCallParams->dwMediaMode == LINEMEDIAMODE_VOICEVIEW) ) +#else + if (lpCallParams->dwMediaMode & ~pLineDev->dwMediaModes) +#endif // VOICEVIEW + { + RELEASE_LINEDEV(pLineDev); + DBG_HDL_EXIT("TSPI_lineMakeCall", LINEERR_INVALMEDIAMODE); + dwRet = LINEERR_INVALMEDIAMODE; + goto end; + } + + // verify bearer mode + if ((~pLineDev->dwBearerModes) & lpCallParams->dwBearerMode) + { + RELEASE_LINEDEV(pLineDev); + DBG_HDL_EXIT("TSPI_lineMakeCall", LINEERR_INVALBEARERMODE); + dwRet = LINEERR_INVALBEARERMODE; + goto end; + } + // Takeover via BEARERMODE_PASSTHROUGH? + if (lpCallParams->dwBearerMode & LINEBEARERMODE_PASSTHROUGH) + { + fDoTakeover = TRUE; + } + else + { + // We're not requested to do passthrough. Can we actually + // dial the media modes without passthrough? This is to + // prevent G3FAX from being used without passthrough... + // (We can only dial with DATAMODEM or INTERACTIVEVOICE) + if ((lpCallParams->dwMediaMode & + (LINEMEDIAMODE_DATAMODEM | LINEMEDIAMODE_INTERACTIVEVOICE)) == 0) + { + RELEASE_LINEDEV(pLineDev); + DBG_HDL_EXIT("TSPI_lineMakeCall", LINEERR_INVALMEDIAMODE); + dwRet = LINEERR_INVALMEDIAMODE; + goto end; + } + } + + pLineDev->dwCurBearerModes = lpCallParams->dwBearerMode; + pLineDev->dwCurMediaModes = lpCallParams->dwMediaMode; + + if (!(lpCallParams->dwCallParamFlags & LINECALLPARAMFLAGS_IDLE)) + { + // Turn on blind dialing + pLineDev->dwDialOptions |= MDM_BLIND_DIAL; + } + + // BUGBUG: should preserve other fields of call params for call info + } + else + { + // set the standard defaults + // use INTERACTIVEVOICE if we can, else use DATAMODEM + if (pLineDev->dwMediaModes & LINEMEDIAMODE_INTERACTIVEVOICE) + { + pLineDev->dwCurMediaModes = LINEMEDIAMODE_INTERACTIVEVOICE; + } + else + { + ASSERT(pLineDev->dwMediaModes & LINEMEDIAMODE_DATAMODEM); + pLineDev->dwCurMediaModes = LINEMEDIAMODE_DATAMODEM; + } + pLineDev->dwCurBearerModes = pLineDev->dwBearerModes & ~LINEBEARERMODE_PASSTHROUGH; + } + + // Do we have a phone number? + // + if (!fDoTakeover) + { + if (IS_NULL_MODEM(pLineDev) || (GETOPTIONS(pLineDev->pDevCfg) & MANUAL_DIAL)) + { + + if (IS_NULL_MODEM(pLineDev)) { + + *pLineDev->szAddress = '\0'; + + } else { + + dwRet = ValidateAddress(pLineDev, lpszDestAddress, pLineDev->szAddress); + + if (ERROR_SUCCESS != dwRet) { + + *pLineDev->szAddress = '\0'; + } + } + + // Turn on blind dialing if this is MANUAL_DIAL. + if (GETOPTIONS(pLineDev->pDevCfg) & MANUAL_DIAL) + { + pLineDev->dwDialOptions |= MDM_BLIND_DIAL; + } + } + else + { + + if (lpszDestAddress != NULL) { + // + // Validate lpszDestAddress and get the processed form of it. + // + dwRet = ValidateAddress(pLineDev, lpszDestAddress, pLineDev->szAddress); + + if (ERROR_SUCCESS != dwRet) + { + RELEASE_LINEDEV(pLineDev); + DBG_HDL_EXIT("TSPI_lineMakeCall", dwRet); + goto end; + } + + if (pLineDev->szAddress[0] == '\0') { + // + // If it is an empty string, I don't think we would expect dial tone + // + pLineDev->dwDialOptions |= MDM_BLIND_DIAL; + } + + } else { + // + // if the lpszDestAddress was NULL then we just want to do a + // dialtone detection. We expect that lineDial will be called. + // Setting the szAddress to ";" will do this. + // + lstrcpyA(pLineDev->szAddress, szSemicolon); + } + } + } + + // Record the call attributes + pLineDev->htCall = htCall; + pLineDev->dwCall = CALL_ALLOCATED; + pLineDev->dwCallState = LINECALLSTATE_UNKNOWN; + pLineDev->dwCallStateMode = 0; + + *lphdCall = (HDRVCALL)pLineDev; + + // We allow to make call to an already-opened line if the line is monitoring + // a call. Therefore, if the line is in use, try making a call. The make-call + // routine will return error if the state is not appropriate. + // + if (((dwRet = DevlineOpen(pLineDev)) == ERROR_SUCCESS) || + (dwRet == LINEERR_ALLOCATED)) + { + if (fDoTakeover) + { + if (pLineDev->DevState == DEVST_PORTLISTENING || + pLineDev->DevState == DEVST_PORTLISTENINIT || + pLineDev->DevState == DEVST_DISCONNECTED) + { + // do we go into passthrough now or later? + if (pLineDev->DevState == DEVST_PORTLISTENINIT) + { + // later + // 7/96 JosephJ: BUGBUG: why is dwPendingType not changed??? + SetPendingRequest( + pLineDev, + dwRequestID, + pLineDev->dwPendingType + ); + } + else + { + // now + UnimodemSetPassthrough(pLineDev, PASSTHROUGH_ON); + pLineDev->DevState = DEVST_CONNECTED; + (*gfnCompletionCallback)(dwRequestID, 0L); + NEW_CALLSTATE(pLineDev, LINECALLSTATE_CONNECTED, 0); + } + pLineDev->fTakeoverMode = TRUE; + dwRet = dwRequestID; + } + else + { + dwRet = LINEERR_OPERATIONFAILED; + } + } + else + { + // We can make a call here + SetPendingRequest(pLineDev, dwRequestID, PENDING_LINEMAKECALL); + + if (((dwRet = DevlineMakeCall(pLineDev)) != ERROR_SUCCESS) && + (IS_TAPI_ERROR(dwRet))) + { + DevlineClose(pLineDev); + } + } + }; + + // Check if an error occurs + // + if (IS_TAPI_ERROR(dwRet)) + { + ClearPendingRequest(pLineDev); + + // Deallocate the call from this line + // + pLineDev->htCall = NULL; + pLineDev->dwCall = 0; + *lphdCall = NULL; + }; + + // Release the modem CB + // + RELEASE_LINEDEV(pLineDev); + +end: + + TRACE4( + IDEVENT_TSPFN_EXIT, + IDFROM_TSPI_lineMakeCall, + &dwRequestID, + dwRet + ); + + + DBG_HDL_EXIT("TSPI_lineMakeCall", dwRet); + return dwRet; +} + +//**************************************************************************** +// LONG TSPIAPI TSPI_lineDial(DRV_REQUESTID dwRequestID, +// HDRVCALL hdCall, +// LPCSTR lpszDestAddress, +// DWORD dwCountryCode) +// +// Functions: Dials numbers for the outbound call. +// +// Return: A positive pending ID number (dwRequestID) if successful +// LINEERR_INVALCALLHANDLE An invalid call handle +// LINEERR_INVALCALLSTATE Cannot dial in the current call state +//**************************************************************************** + +LONG TSPIAPI TSPI_lineDial(DRV_REQUESTID dwRequestID, + HDRVCALL hdCall, + LPCTSTR lpszDestAddress, + DWORD dwCountryCode) +{ + PLINEDEV pLineDev; + DWORD dwRet = LINEERR_OPERATIONFAILED; // assume failure + + DBG_HDC_ENTER("TSPI_lineDial"); + + TRACE3( + IDEVENT_TSPFN_ENTER, + IDFROM_TSPI_lineDial, + &dwRequestID + ); + + if ((pLineDev = GetCBfromHandle ((DWORD)hdCall)) == NULL) + { + dwRet = LINEERR_INVALCALLHANDLE; + goto end; + } + + // We can only be called when our devstate is DEVST_PORTCONNECTWAITFORLINEDIAL. + if (pLineDev->DevState != DEVST_PORTCONNECTWAITFORLINEDIAL) + { + RELEASE_LINEDEV(pLineDev); + dwRet = LINEERR_INVALCALLSTATE; + goto end; + } + + // Validate lpszDestAddress and get the processed form of it. + dwRet = ValidateAddress(pLineDev, lpszDestAddress, pLineDev->szAddress); + if (ERROR_SUCCESS != dwRet) + { + RELEASE_LINEDEV(pLineDev); + goto end; + } + + // Now we can dial the number + // + if ((dwRet = DevlineDial(pLineDev)) == ERROR_SUCCESS) + { + SetPendingRequest(pLineDev, dwRequestID, PENDING_LINEDIAL); + dwRet = dwRequestID; + }; + + // Release the modem CB + // + RELEASE_LINEDEV(pLineDev); + +end: + + DBG_HDC_EXIT("TSPI_lineDial", dwRet); + + TRACE4( + IDEVENT_TSPFN_EXIT, + IDFROM_TSPI_lineDial, + &dwRequestID, + dwRet + ); + + return dwRet; +} + +//**************************************************************************** +// LONG TSPIAPI TSPI_lineAccept(DRV_REQUESTID dwRequestID, +// HDRVCALL hdCall, +// LPCSTR lpsUserUserInfo, +// DWORD dwSize) +// +// Functions: Accepts the offered inbound call +// +// Return: A positive pending ID number (dwRequestID) if successful +// LINEERR_INVALCALLHANDLE An invalid call handle +// LINEERR_INVALCALLSTATE Cannot accept call in the current state +//**************************************************************************** + +LONG TSPIAPI TSPI_lineAccept(DRV_REQUESTID dwRequestID, + HDRVCALL hdCall, + LPCSTR lpsUserUserInfo, + DWORD dwSize) +{ + PLINEDEV pLineDev; + DWORD dwRet = LINEERR_OPERATIONFAILED; // assume failure + + DBG_HDC_ENTER("TSPI_lineAccept"); + + TRACE3( + IDEVENT_TSPFN_ENTER, + IDFROM_TSPI_lineAccept, + &dwRequestID + ); + + if ((pLineDev = GetCBfromHandle ((DWORD)hdCall)) == NULL) + { + dwRet = LINEERR_INVALCALLHANDLE; + goto end; + } + + if (LINECALLSTATE_OFFERING == pLineDev->dwCallState) + { + NEW_CALLSTATE(pLineDev, LINECALLSTATE_ACCEPTED, 0); + (*gfnCompletionCallback)(dwRequestID, 0L); + dwRet = dwRequestID; + } + else + { + dwRet = LINEERR_INVALCALLSTATE; + } + + // Release the modem CB + // + RELEASE_LINEDEV(pLineDev); + +end: + + DBG_HDC_EXIT("TSPI_lineAccept", dwRet); + TRACE4( + IDEVENT_TSPFN_EXIT, + IDFROM_TSPI_lineAccept, + &dwRequestID, + dwRet + ); + + return dwRet; +} + +//**************************************************************************** +// LONG TSPIAPI TSPI_lineAnswer(HDRVCALL hdCall, +// LPCSTR lpsUserUserInfo, +// DWORD dwSize) +// +// Functions: Answers the offered/accepted inbound call. +// +// Return: A positive pending ID number (dwRequestID) if successful +// LINEERR_INVALCALLHANDLE An invalid call handle +// LINEERR_INVALCALLSTATE Cannot answer call in the current state +// LINEERR_OPERATIONUNAVAIL Invalid mediamode +//**************************************************************************** + +LONG TSPIAPI TSPI_lineAnswer(DRV_REQUESTID dwRequestID, + HDRVCALL hdCall, + LPCSTR lpsUserUserInfo, + DWORD dwSize) +{ + PLINEDEV pLineDev; + DWORD dwRet = ERROR_SUCCESS; + + DBG_HDC_ENTER("TSPI_lineAnswer"); + //DPRINTF1("TSPI_lineAnswer(dwReq=0x%08lx)", dwRequestID); + + TRACE3( + IDEVENT_TSPFN_ENTER, + IDFROM_TSPI_lineAnswer, + &dwRequestID + ); + + if ((pLineDev = GetCBfromHandle ((DWORD)hdCall)) == NULL) + { + dwRet = LINEERR_INVALCALLHANDLE; + goto end; + } + + // Validate the line capabilties and call state + // + if (pLineDev->fTakeoverMode) + { + dwRet = LINEERR_OPERATIONUNAVAIL; + } + else + { + if (LINECALLSTATE_OFFERING != pLineDev->dwCallState && + LINECALLSTATE_ACCEPTED != pLineDev->dwCallState) + { + dwRet = LINEERR_INVALCALLSTATE; + } + else + { + // We can only answer DATAMODEM calls + if ((pLineDev->dwCurMediaModes & LINEMEDIAMODE_DATAMODEM) == 0) + { + dwRet = LINEERR_OPERATIONUNAVAIL; + }; + }; + }; + + // If the call state and line capabilties are validated + // + if (dwRet == ERROR_SUCCESS) + { + // Answer the call + // + SetPendingRequest(pLineDev, dwRequestID, PENDING_LINEANSWER); + + dwRet = DevlineAnswer(pLineDev); + + // If we can answer the call + // + if (!IS_TAPI_ERROR(dwRet)) + { + // Notify an async completion since we have grabbed the line + // + (*gfnCompletionCallback)(pLineDev->dwPendingID, 0L); + + // if a lineAccept wasn't done, notify acceptance + if (LINECALLSTATE_OFFERING == pLineDev->dwCallState) + { + NEW_CALLSTATE(pLineDev, LINECALLSTATE_ACCEPTED, 0); + }; + }; + ClearPendingRequest(pLineDev); + }; + + // Release the modem CB + // + RELEASE_LINEDEV(pLineDev); + +end: + + DBG_HDC_EXIT("TSPI_lineAnswer", dwRet); + TRACE4( + IDEVENT_TSPFN_EXIT, + IDFROM_TSPI_lineAnswer, + &dwRequestID, + dwRet + ); + + //DPRINTF2("TSPI_lineAnswer(dwReq=0x%08lx, ret = 0x%08lx)", dwRequestID, dwRet); + return dwRet; +} + +//**************************************************************************** +// LONG TSPIAPI TSPI_lineGetCallStatus(HDRVCALL hdCall, +// LPLINECALLSTATUS lpCallStatus) +// +// Functions: Get the current status of the call. +// +// Return: ERROR_SUCCESS if successful +// LINEERR_INVALCALLHANDLE An invalid call handle +//**************************************************************************** + +LONG TSPIAPI TSPI_lineGetCallStatus(HDRVCALL hdCall, + LPLINECALLSTATUS lpCallStatus) +{ + PLINEDEV pLineDev; + LONG lRet = LINEERR_OPERATIONFAILED; // assume failure + + DBG_HDC_ENTER("TSPI_lineGetCallStatus"); + + TRACE3( + IDEVENT_TSPFN_ENTER, + IDFROM_TSPI_lineGetCallStatus, + &hdCall + ); + + if ((pLineDev = GetCBfromHandle ((DWORD)hdCall)) == NULL) + { + lRet = LINEERR_INVALCALLHANDLE; + goto end; + } + + // Current call information + // + lpCallStatus->dwCallState = pLineDev->dwCallState; + lpCallStatus->dwCallStateMode = pLineDev->dwCallStateMode; + + // if we are in takeover mode, disallow all dwCallFeatures + // + if (!pLineDev->fTakeoverMode) + { + switch(lpCallStatus->dwCallState) + { + case LINECALLSTATE_OFFERING: + lpCallStatus->dwCallFeatures = LINECALLFEATURE_ACCEPT | + LINECALLFEATURE_SETCALLPARAMS | + LINECALLFEATURE_DROP; + // We can only answer if a possible media mode is DATAMODEM. + if (pLineDev->dwCurMediaModes & LINEMEDIAMODE_DATAMODEM) + { + lpCallStatus->dwCallFeatures |= LINECALLFEATURE_ANSWER; + } + break; + + case LINECALLSTATE_DIALTONE: + lpCallStatus->dwCallFeatures = LINECALLFEATURE_DROP; + break; + + case LINECALLSTATE_DIALING: + lpCallStatus->dwCallFeatures = LINECALLFEATURE_DROP; + if (DEVST_PORTCONNECTWAITFORLINEDIAL == pLineDev->DevState) + { + lpCallStatus->dwCallFeatures |= LINECALLFEATURE_DIAL; + } + break; + + case LINECALLSTATE_ACCEPTED: + lpCallStatus->dwCallFeatures = LINECALLFEATURE_SETCALLPARAMS | + LINECALLFEATURE_DROP; + // We can only answer if a possible media mode is DATAMODEM. + if (pLineDev->dwCurMediaModes & LINEMEDIAMODE_DATAMODEM) + { + lpCallStatus->dwCallFeatures |= LINECALLFEATURE_ANSWER; + } + break; + + case LINECALLSTATE_CONNECTED: + lpCallStatus->dwCallFeatures = LINECALLFEATURE_SETCALLPARAMS | + LINECALLFEATURE_DROP; + break; + + case LINECALLSTATE_UNKNOWN: + case LINECALLSTATE_PROCEEDING: + case LINECALLSTATE_DISCONNECTED: + lpCallStatus->dwCallFeatures = LINECALLFEATURE_DROP; + break; + + case LINECALLSTATE_IDLE: + default: + lpCallStatus->dwCallFeatures = 0; + break; + }; + } + else + { + // Make sure the call feature are all off + // + ASSERT(lpCallStatus->dwCallFeatures == 0); + }; + + // Release the modem CB + // + RELEASE_LINEDEV(pLineDev); + lRet = ERROR_SUCCESS; + +end: + + DBG_HDC_EXIT("TSPI_lineGetCallStatus", lRet); + TRACE4( + IDEVENT_TSPFN_EXIT, + IDFROM_TSPI_lineGetCallStatus, + &hdCall, + lRet + ); + + return lRet; +} + +//**************************************************************************** +// LONG TSPIAPI TSPI_lineGetCallInfo(HDRVCALL hdCall, +// LPLINECALLINFO lpCallInfo) +// +// Functions: Get the current call information +// +// Return: ERROR_SUCCESS if successful +// LINEERR_INVALCALLHANDLE An invalid call handle +//**************************************************************************** + +LONG TSPIAPI TSPI_lineGetCallInfo(HDRVCALL hdCall, + LPLINECALLINFO lpCallInfo) +{ + PLINEDEV pLineDev; + LONG lRet = LINEERR_OPERATIONFAILED; // assume failure + + DBG_HDC_ENTER("TSPI_lineGetCallInfo"); + + TRACE3( + IDEVENT_TSPFN_ENTER, + IDFROM_TSPI_lineGetCallInfo, + &hdCall + ); + + if ((pLineDev = GetCBfromHandle ((DWORD)hdCall)) == NULL) + { + lRet = LINEERR_INVALCALLHANDLE; + goto end; + } + + //lpCallInfo->dwUsedSize = sizeof(LINECALLINFO); + //lpCallInfo->dwNeededSize = sizeof(LINECALLINFO); + ASSERT(lpCallInfo->dwNeededSize == sizeof(LINECALLINFO)); + + lpCallInfo->dwLineDeviceID = pLineDev->dwID; + + lpCallInfo->dwAddressID = 0; + lpCallInfo->dwBearerMode = pLineDev->dwCurBearerModes; + lpCallInfo->dwRate = pLineDev->dwNegotiatedRate; + lpCallInfo->dwMediaMode = pLineDev->dwCurMediaModes; + + lpCallInfo->dwAppSpecific = pLineDev->dwAppSpecific; + + //lpCallInfo->dwCallID = 0; + //lpCallInfo->dwRelatedCallID = 0; + //lpCallInfo->dwCallParamFlags= 0; + + lpCallInfo->dwCallStates = pLineDev->dwCall & CALL_INBOUND ? + (LINECALLSTATE_IDLE | + LINECALLSTATE_OFFERING | + LINECALLSTATE_ACCEPTED | + LINECALLSTATE_CONNECTED | + LINECALLSTATE_DISCONNECTED | + LINECALLSTATE_UNKNOWN) : + (LINECALLSTATE_IDLE | + LINECALLSTATE_DIALTONE | + LINECALLSTATE_DIALING | + LINECALLSTATE_PROCEEDING | + LINECALLSTATE_CONNECTED | + LINECALLSTATE_DISCONNECTED | + LINECALLSTATE_UNKNOWN); + + //lpCallInfo->DialParams.dwDialPause = 0; + //lpCallInfo->DialParams.dwDialSpeed = 0; + //lpCallInfo->DialParams.dwDigitDuration = 0; + //lpCallInfo->DialParams.dwWaitForDialtone = 0; + + lpCallInfo->dwOrigin = pLineDev->dwCall & CALL_INBOUND ? + LINECALLORIGIN_INBOUND : + LINECALLORIGIN_OUTBOUND; + lpCallInfo->dwReason = pLineDev->dwCall & CALL_INBOUND ? + LINECALLREASON_UNAVAIL : + LINECALLREASON_DIRECT; + + //lpCallInfo->dwCompletionID = 0; + //lpCallInfo->dwCountryCode = 0; + //lpCallInfo->dwTrunk = 0; + + lpCallInfo->dwCallerIDFlags = LINECALLPARTYID_UNAVAIL; + //lpCallInfo->dwCallerIDSize = 0; + //lpCallInfo->dwCallerIDOffset = 0; + + //lpCallInfo->dwCallerIDNameSize = 0; + //lpCallInfo->dwCallerIDNameOffset = 0; + + lpCallInfo->dwCalledIDFlags = LINECALLPARTYID_UNAVAIL; + //lpCallInfo->dwCalledIDSize = 0; + //lpCallInfo->dwCalledIDOffset = 0; + //lpCallInfo->dwCalledIDNameSize = 0; + //lpCallInfo->dwCalledIDNameOffset= 0; + + lpCallInfo->dwConnectedIDFlags = LINECALLPARTYID_UNAVAIL; + //lpCallInfo->dwConnectedIDSize = 0; + //lpCallInfo->dwConnectedIDOffset = 0; + //lpCallInfo->dwConnectedIDNameSize = 0; + //lpCallInfo->dwConnectedIDNameOffset = 0; + + lpCallInfo->dwRedirectionIDFlags = LINECALLPARTYID_UNAVAIL; + //lpCallInfo->dwRedirectionIDSize = 0; + //lpCallInfo->dwRedirectionIDOffset = 0; + //lpCallInfo->dwRedirectionIDNameSize = 0; + //lpCallInfo->dwRedirectionIDNameOffset = 0; + + lpCallInfo->dwRedirectingIDFlags = LINECALLPARTYID_UNAVAIL; + //lpCallInfo->dwRedirectingIDSize = 0; + //lpCallInfo->dwRedirectingIDOffset = 0; + //lpCallInfo->dwRedirectingIDNameSize = 0; + //lpCallInfo->dwRedirectingIDNameOffset = 0; + + //lpCallInfo->dwDisplaySize = 0; + //lpCallInfo->dwDisplayOffset = 0; + + //lpCallInfo->dwUserUserInfoSize = 0; + //lpCallInfo->dwUserUserInfoOffset = 0; + + //lpCallInfo->dwHighLevelCompSize = 0; + //lpCallInfo->dwHighLevelCompOffset = 0; + + //lpCallInfo->dwLowLevelCompSize = 0; + //lpCallInfo->dwLowLevelCompOffset = 0; + + //lpCallInfo->dwChargingInfoSize = 0; + //lpCallInfo->dwChargingInfoOffset = 0; + + //lpCallInfo->dwTerminalModesSize = 0; + //lpCallInfo->dwTerminalModesOffset = 0; + + //lpCallInfo->dwDevSpecificSize = 0; + //lpCallInfo->dwDevSpecificOffset = 0; + + // Release the modem CB + // + RELEASE_LINEDEV(pLineDev); + + lRet = ERROR_SUCCESS; + +end: + + DBG_HDC_EXIT("TSPI_lineGetCallInfo", lRet); + TRACE4( + IDEVENT_TSPFN_EXIT, + IDFROM_TSPI_lineGetCallInfo, + &hdCall, + lRet + ); + + return lRet; +} + +//**************************************************************************** +// LONG TSPIAPI TSPI_lineGetCallAddressID(HDRVCALL hdCall, +// LPDWORD lpdwAddressID) +// +// Functions: get the address ID for the call +// +// Return: ERROR_SUCCESS if successful +// LINEERR_INVALCALLHANDLE An invalid call handle +//**************************************************************************** + +LONG TSPIAPI TSPI_lineGetCallAddressID(HDRVCALL hdCall, + LPDWORD lpdwAddressID) +{ + PLINEDEV pLineDev; + LONG lRet = LINEERR_OPERATIONFAILED; // assume failure + + DBG_HDC_ENTER("TSPI_lineGetCallAddressID"); + + TRACE3( + IDEVENT_TSPFN_ENTER, + IDFROM_TSPI_lineGetCallAddressID, + &hdCall + ); + + if ((pLineDev = GetCBfromHandle ((DWORD)hdCall)) == NULL) + { + lRet = LINEERR_INVALCALLHANDLE; + goto end; + } + + // There is but a single address where a call may exist. + // + *lpdwAddressID = 0; + + // Release the modem CB + // + RELEASE_LINEDEV(pLineDev); + lRet = ERROR_SUCCESS; + +end: + + DBG_HDC_EXIT("TSPI_lineGetCallAddressID", lRet); + TRACE4( + IDEVENT_TSPFN_EXIT, + IDFROM_TSPI_lineGetCallAddressID, + &hdCall, + lRet + ); + + return lRet; +} + +//**************************************************************************** +// LONG TSPIAPI TSPI_lineDrop(DRV_REQUESTID dwRequestID, +// HDRVCALL hdCall, +// LPCSTR lpsUserUserInfo, +// DWORD dwSize) +// +// Functions: Transition a call to the DISCONNECTED state. +// +// Return: A positive pending ID number (dwRequestID) if successful +// LINEERR_INVALCALLHANDLE An invalid call handle +//**************************************************************************** + +LONG TSPIAPI TSPI_lineDrop(DRV_REQUESTID dwRequestID, + HDRVCALL hdCall, + LPCSTR lpsUserUserInfo, + DWORD dwSize) +{ + PLINEDEV pLineDev; + DWORD dwRet=LINEERR_OPERATIONFAILED; + + DBG_HDC_ENTER("TSPI_lineDrop"); + + TRACE3( + IDEVENT_TSPFN_ENTER, + IDFROM_TSPI_lineDrop, + &dwRequestID + ); + + if ((pLineDev = GetCBfromHandle ((DWORD)hdCall)) == NULL) + { + dwRet= LINEERR_INVALCALLHANDLE; + goto end; + } + + if (pLineDev->fTakeoverMode) + { + UnimodemSetPassthrough(pLineDev, PASSTHROUGH_OFF); + + pLineDev->fTakeoverMode = FALSE; + pLineDev->DevState = DEVST_DISCONNECTED; + NEW_CALLSTATE(pLineDev, LINECALLSTATE_IDLE, 0); + (*gfnCompletionCallback)(dwRequestID, 0L); + dwRet = dwRequestID; + } + else + { + if (DEVST_DISCONNECTING == pLineDev->DevState) { + + TSPPRINTF("LineDrop called more than once"); + + (*gfnCompletionCallback)(dwRequestID, 0L); + dwRet = dwRequestID; + + } else { + + // Disconnect the line + // + SetPendingRequest(pLineDev, dwRequestID, PENDING_LINEDROP); + + if ((dwRet = DevlineDrop(pLineDev, FALSE)) != ERROR_SUCCESS) + { + ClearPendingRequest(pLineDev); + } + else + { + dwRet = dwRequestID; + } + } + } + + // Release the modem CB + // + RELEASE_LINEDEV(pLineDev); + +end: + + TRACE4( + IDEVENT_TSPFN_EXIT, + IDFROM_TSPI_lineDrop, + &dwRequestID, + dwRet + ); + DBG_HDC_EXIT("TSPI_lineDrop", dwRet); + + return dwRet; +} + + +//**************************************************************************** +// LONG TSPIAPI TSPI_lineCloseCall(HDRVCALL hdCall) +// +// Functions: Terminates the call. +// +// Return: ERROR_SUCCESS if successful +// LINEERR_INVALCALLHANDLE An invalid call handle +//**************************************************************************** + +LONG TSPIAPI TSPI_lineCloseCall(HDRVCALL hdCall) +{ + PLINEDEV pLineDev; + DWORD dwRet = ERROR_SUCCESS; + + DBG_HDC_ENTER("TSPI_lineCloseCall"); + TRACE3( + IDEVENT_TSPFN_ENTER, + IDFROM_TSPI_lineCloseCall, + &hdCall + ); + + if ((pLineDev = GetCBfromHandle ((DWORD)hdCall)) == NULL) + { + dwRet = LINEERR_INVALCALLHANDLE; + goto end; + } + + // Turn off takeover mode + // + if (pLineDev->fTakeoverMode) + { + UnimodemSetPassthrough(pLineDev, PASSTHROUGH_OFF); + + pLineDev->fTakeoverMode = FALSE; + pLineDev->DevState = DEVST_DISCONNECTED; + } + else + { + // If the line is not disconnected, drop the line synchronously + // + if (pLineDev->DevState != DEVST_DISCONNECTED) + { + DevlineDrop(pLineDev, TRUE); + pLineDev->DevState = DEVST_DISCONNECTED; + }; + }; + + // + // kill lights if it is running + // + if (pLineDev->hLights != NULL) { + + TerminateModemLight(pLineDev->hLights); + pLineDev->hLights = NULL; + } + + + NEW_CALLSTATE(pLineDev, LINECALLSTATE_IDLE, 0); + + // At this point, the call has already been dropped, + // so we only need to deallocate it. + // + pLineDev->htCall = NULL; + pLineDev->dwCall = 0L; + pLineDev->dwNegotiatedRate = 0L; + + // If we need to detect the line, reopen and listen to the line + if ((pLineDev->dwDetMediaModes) && !(pLineDev->fdwResources & LINEDEVFLAGS_OUTOFSERVICE)) + { + if ((dwRet = DevlineDetectCall(pLineDev)) != ERROR_SUCCESS) { + + // + // init failed + // + //ASSERT(0); + DPRINTF("***ASSERTION FAILED**** (init failed)"); + + pLineDev->LineClosed=TRUE; + + // + // tell the app + // + (*pLineDev->lpfnEvent)(pLineDev->htLine, NULL, LINE_CLOSE, + 0L, 0L, 0L); + } + + } + else + { + // No need to detect the line, just close it. + // + DevlineClose(pLineDev); + +#ifdef UNDER_CONSTRUCTION + // If we are out of service, clean up and bail out + // + if (pLineDev->fdwResources & LINEDEVFLAGS_OUTOFSERVICE) + { + DevlineDisabled(pLineDev); + }; +#endif //UNDER_CONSTRUCTION + }; + + // Release the modem CB + // + RELEASE_LINEDEV(pLineDev); + +end: + + DBG_HDC_EXIT("TSPI_lineCloseCall", dwRet); + + TRACE4( + IDEVENT_TSPFN_EXIT, + IDFROM_TSPI_lineCloseCall, + &hdCall, + dwRet + ); + + return dwRet; +} + +//**************************************************************************** +// LONG TSPIAPI TSPI_lineSetMediaMode(HDRVCALL hdCall, +// DWORD dwMediaMode) +// +// Functions: Set the mediamode for the call. +// +// Return: ERROR_SUCCESS if successful +// LINEERR_INVALCALLHANDLE An invalid call handle +// LINEERR_INVALMEDIAMODE An invalid media mode +//**************************************************************************** +LONG TSPIAPI TSPI_lineSetMediaMode(HDRVCALL hdCall, + DWORD dwMediaMode) +{ + PLINEDEV pLineDev; + LONG lRet = LINEERR_OPERATIONFAILED; // assume failure + + DBG_HDC_ENTER("TSPI_lineSetMediaMode"); + + TRACE3( + IDEVENT_TSPFN_ENTER, + IDFROM_TSPI_lineSetMediaMode, + &hdCall + ); + + if ((pLineDev = GetCBfromHandle ((DWORD)hdCall)) == NULL) + { + lRet = LINEERR_INVALCALLHANDLE; + goto end; + } + + // Check the requested modes. There must be only our media modes + // + if (dwMediaMode & ~pLineDev->dwMediaModes) + { + lRet = LINEERR_INVALMEDIAMODE; + } + else + { + // If the specifed media mode is not equal to the current media mode + // + if (pLineDev->dwCurMediaModes != dwMediaMode) + { + // Set it and notify the media mode change + // + pLineDev->dwCurMediaModes = dwMediaMode; + (*(pLineDev->lpfnEvent))(pLineDev->htLine, pLineDev->htCall, + LINE_CALLINFO, LINECALLINFOSTATE_MEDIAMODE, + 0, 0); + }; + lRet = ERROR_SUCCESS; + }; + + // Release the modem CB + // + RELEASE_LINEDEV(pLineDev); + +end: + + DBG_HDC_EXIT("TSPI_lineSetMediaMode", lRet); + TRACE4( + IDEVENT_TSPFN_EXIT, + IDFROM_TSPI_lineSetMediaMode, + &hdCall, + lRet + ); + + return lRet; +} + +//**************************************************************************** +// LONG TSPIAPI TSPI_lineSetAppSpecific() +// +// Functions: Set the application specific value for the call. +// +// Return: ERROR_SUCCESS if successful +// LINEERR_INVALCALLHANDLE An invalid call handle +//**************************************************************************** + +LONG TSPIAPI TSPI_lineSetAppSpecific(HDRVCALL hdCall, + DWORD dwAppSpecific) +{ + PLINEDEV pLineDev; + LONG lRet = LINEERR_OPERATIONFAILED; // assume failure + + DBG_HDC_ENTER("TSPI_lineSetAppSpecific"); + + TRACE3( + IDEVENT_TSPFN_ENTER, + IDFROM_TSPI_lineSetAppSpecific, + &hdCall + ); + + if ((pLineDev = GetCBfromHandle ((DWORD)hdCall)) == NULL) + { + lRet = LINEERR_INVALCALLHANDLE; + goto end; + } + + pLineDev->dwAppSpecific = dwAppSpecific; + (*(pLineDev->lpfnEvent))(pLineDev->htLine, pLineDev->htCall, + LINE_CALLINFO, LINECALLINFOSTATE_APPSPECIFIC, + 0, 0); + + RELEASE_LINEDEV(pLineDev); + + lRet = ERROR_SUCCESS; + +end: + + DBG_HDC_EXIT("TSPI_lineSetAppSpecific", lRet); + TRACE4( + IDEVENT_TSPFN_EXIT, + IDFROM_TSPI_lineSetAppSpecific, + &hdCall, + lRet + ); + return lRet; +} + + +//**************************************************************************** +// LONG TSPIAPI TSPI_lineSetCallParams() +// +// Functions: Set the call parameters. +// +// Return: ERROR_SUCCESS if successful +// LINEERR_INVALCALLHANDLE An invalid call handle +// LINEERR_INVALMEDIAMODE An invalid media mode +// LINEERR_INVALCALLSTATE Call params can't be set in this state +//**************************************************************************** + +LONG TSPIAPI TSPI_lineSetCallParams(DRV_REQUESTID dwRequestID, + HDRVCALL hdCall, + DWORD dwBearerMode, + DWORD dwMinRate, + DWORD dwMaxRate, + LPLINEDIALPARAMS const lpDialParams) +{ + PLINEDEV pLineDev; + LONG lRet = LINEERR_OPERATIONFAILED; // assume failure + + DBG_HDC_ENTER("TSPI_lineSetCallParams"); + TRACE3( + IDEVENT_TSPFN_ENTER, + IDFROM_TSPI_lineSetCallParams, + &dwRequestID + ); + + if ((pLineDev = GetCBfromHandle ((DWORD)hdCall)) == NULL) + { + lRet = LINEERR_INVALCALLHANDLE; + goto end; + } + + if (LINECALLSTATE_OFFERING != pLineDev->dwCallState && + LINECALLSTATE_ACCEPTED != pLineDev->dwCallState && + LINECALLSTATE_CONNECTED != pLineDev->dwCallState) + { + RELEASE_LINEDEV(pLineDev); + lRet = LINEERR_INVALCALLSTATE; + goto end; + } + + // verify bearer mode + if ((~pLineDev->dwBearerModes) & dwBearerMode) + { + RELEASE_LINEDEV(pLineDev); + lRet = LINEERR_INVALBEARERMODE; + goto end; + } + + + // Check bearermode for passthrough + if (dwBearerMode & LINEBEARERMODE_PASSTHROUGH) + { + // are we not already in passthrough? + if (!(pLineDev->dwCurBearerModes & LINEBEARERMODE_PASSTHROUGH)) + { + // we need to switch into passthrough + pLineDev->dwCurBearerModes = LINEBEARERMODE_PASSTHROUGH; + UnimodemSetPassthrough(pLineDev, PASSTHROUGH_ON); + pLineDev->fTakeoverMode = TRUE; + pLineDev->DevState = DEVST_CONNECTED; + if (LINECALLSTATE_CONNECTED != pLineDev->dwCallState) + { + NEW_CALLSTATE(pLineDev, LINECALLSTATE_CONNECTED, 0); + } + } + } + else + { + // are we already in passthrough? + if (pLineDev->dwCurBearerModes & LINEBEARERMODE_PASSTHROUGH) + { + // we need to switch out of passthrough + + UnimodemSetPassthrough(pLineDev, PASSTHROUGH_OFF_BUT_CONNECTED); + pLineDev->fTakeoverMode = FALSE; + + if (pLineDev->DevState == DEVST_CONNECTED) { + + // + // Start monitoring the remote disconnection here + // + UnimodemMonitorDisconnect(pLineDev); + } + + + } + + pLineDev->dwCurBearerModes = dwBearerMode; + } + + RELEASE_LINEDEV(pLineDev); + (*gfnCompletionCallback)(dwRequestID, 0L); + lRet = dwRequestID; + +end: + + DBG_HDC_EXIT("TSPI_lineSetCallParams", lRet); + TRACE4( + IDEVENT_TSPFN_EXIT, + IDFROM_TSPI_lineSetCallParams, + &dwRequestID, + lRet + ); + + return lRet; +} + +//**************************************************************************** +//************************ The Address Specific Calls************************* +//**************************************************************************** + +//**************************************************************************** +// LONG TSPIAPI TSPI_lineGetAddressCaps(DWORD dwDeviceID, +// DWORD dwAddressID, +// DWORD dwTSPIVersion, +// DWORD dwExtVersion, +// LPLINEADDRESSCAPS lpAddressCaps) +// +// Functions: Get the capabilities of the specified address. +// +// Return: ERROR_SUCCESS if successful +// LINEERR_NODEVICE An invalid device id +// LINEERR_INVALADDRESSID An invalid address id for the line +//**************************************************************************** + +LONG TSPIAPI TSPI_lineGetAddressCaps(DWORD dwDeviceID, + DWORD dwAddressID, + DWORD dwTSPIVersion, + DWORD dwExtVersion, + LPLINEADDRESSCAPS lpAddressCaps) + +{ + PLINEDEV pLineDev; + DWORD dwRet = LINEERR_OPERATIONFAILED; // assume failure + + DBG_DDI_ENTER("TSPI_lineGetAddressCaps"); + + TRACE3( + IDEVENT_TSPFN_ENTER, + IDFROM_TSPI_lineGetAddressCaps, + &dwDeviceID + ); + + // Validate the version number + // + VALIDATE_VERSION(dwTSPIVersion); + + // Validate the device ID + // + if ((pLineDev = GetCBfromID(dwDeviceID)) == NULL) + { + dwRet = LINEERR_NODEVICE; + goto end; + } + + // Validate the address ID + // + if(dwAddressID != 0) + { + dwRet = LINEERR_INVALADDRESSID; + } + else + { + // Check to see if we have enough memory in the structure. + // + //lpAddressCaps->dwAddressSize = 0; + //lpAddressCaps->dwAddressOffset = 0; + + // Other device attributes + // + //lpAddressCaps->dwDevSpecificSize = 0; + //lpAddressCaps->dwDevSpecificOffset = 0; + // + lpAddressCaps->dwLineDeviceID = dwDeviceID; + + lpAddressCaps->dwAddressSharing = LINEADDRESSSHARING_PRIVATE; + //lpAddressCaps->dwAddressStates = 0; + lpAddressCaps->dwCallInfoStates = LINECALLINFOSTATE_APPSPECIFIC | LINECALLINFOSTATE_MEDIAMODE; + lpAddressCaps->dwCallerIDFlags = LINECALLPARTYID_UNAVAIL; + lpAddressCaps->dwCalledIDFlags = LINECALLPARTYID_UNAVAIL; + lpAddressCaps->dwConnectedIDFlags = LINECALLPARTYID_UNAVAIL; + lpAddressCaps->dwRedirectionIDFlags = LINECALLPARTYID_UNAVAIL; + lpAddressCaps->dwRedirectingIDFlags = LINECALLPARTYID_UNAVAIL; + + lpAddressCaps->dwCallStates = LINECALLSTATE_IDLE | + LINECALLSTATE_OFFERING | + LINECALLSTATE_ACCEPTED | + LINECALLSTATE_DIALTONE | + LINECALLSTATE_DIALING | + LINECALLSTATE_CONNECTED | + LINECALLSTATE_PROCEEDING | + LINECALLSTATE_DISCONNECTED | + LINECALLSTATE_UNKNOWN; + + lpAddressCaps->dwDialToneModes = LINEDIALTONEMODE_UNAVAIL; + lpAddressCaps->dwBusyModes = LINEBUSYMODE_UNAVAIL; + + lpAddressCaps->dwSpecialInfo = LINESPECIALINFO_UNAVAIL; + + lpAddressCaps->dwDisconnectModes = LINEDISCONNECTMODE_UNAVAIL | + LINEDISCONNECTMODE_NORMAL | + LINEDISCONNECTMODE_BUSY | + LINEDISCONNECTMODE_NODIALTONE | + LINEDISCONNECTMODE_NOANSWER; + + lpAddressCaps->dwMaxNumActiveCalls = 1; + //lpAddressCaps->dwMaxNumOnHoldCalls = 0; + //lpAddressCaps->dwMaxNumOnHoldPendingCalls = 0; + //lpAddressCaps->dwMaxNumConference = 0; + //lpAddressCaps->dwMaxNumTransConf = 0; + + // dwAddrCapFlags + if (!IS_NULL_MODEM(pLineDev)) + { + lpAddressCaps->dwAddrCapFlags = LINEADDRCAPFLAGS_DIALED; + } + if (pLineDev->fPartialDialing) + { + lpAddressCaps->dwAddrCapFlags |= LINEADDRCAPFLAGS_PARTIALDIAL; + } + + lpAddressCaps->dwCallFeatures = LINECALLFEATURE_ANSWER | + LINECALLFEATURE_ACCEPT | + LINECALLFEATURE_SETCALLPARAMS | + LINECALLFEATURE_DIAL | + LINECALLFEATURE_DROP; + + //lpAddressCaps->dwRemoveFromConfCaps = 0; + //lpAddressCaps->dwRemoveFromConfState = 0; + //lpAddressCaps->dwTransferModes = 0; + //lpAddressCaps->dwParkModes = 0; + + //lpAddressCaps->dwForwardModes = 0; + //lpAddressCaps->dwMaxForwardEntries = 0; + //lpAddressCaps->dwMaxSpecificEntries = 0; + //lpAddressCaps->dwMinFwdNumRings = 0; + //lpAddressCaps->dwMaxFwdNumRings = 0; + + //lpAddressCaps->dwMaxCallCompletions = 0; + //lpAddressCaps->dwCallCompletionConds = 0; + //lpAddressCaps->dwCallCompletionModes = 0; + + //lpAddressCaps->dwNumCompletionMessages = 0; + //lpAddressCaps->dwCompletionMsgTextEntrySize = 0; + //lpAddressCaps->dwCompletionMsgTextSize = 0; + //lpAddressCaps->dwCompletionMsgTextOffset = 0; + + lpAddressCaps->dwAddressFeatures = LINEADDRFEATURE_MAKECALL; + + //lpAddressCaps->dwPredictiveAutoTransferStates = 0; + //lpAddressCaps->dwAgentStates = 0; + //lpAddressCaps->dwNextAgentStates = 0; + //lpAddressCaps->dwMaxNumAgentEntries = 0; + + //lpAddressCaps->dwNumCallTreatments = 0; + //lpAddressCaps->dwCallTreatmentListSize = 0; + //lpAddressCaps->dwCallTreatmentListOffset = 0; + + lpAddressCaps->dwUsedSize = sizeof(LINEADDRESSCAPS); + lpAddressCaps->dwNeededSize = lpAddressCaps->dwUsedSize + + sizeof(LINEADDRESSCAPS); + + if (lpAddressCaps->dwTotalSize >= lpAddressCaps->dwNeededSize) + { + lpAddressCaps->dwUsedSize += sizeof(g_szzClassList); + lpAddressCaps->dwDeviceClassesSize = sizeof(g_szzClassList); + lpAddressCaps->dwDeviceClassesOffset= sizeof(LINEADDRESSCAPS); + hmemcpy((LPBYTE)(lpAddressCaps+1), g_szzClassList, + sizeof(g_szzClassList)); + } + else + { + lpAddressCaps->dwDeviceClassesSize = 0; + lpAddressCaps->dwDeviceClassesOffset= 0; + }; + + //lpAddressCaps->dwMaxCallDataSize = 0; + //lpAddressCaps->dwCallFeatures2 = 0; + //lpAddressCaps->dwMaxNoAnswerTimeout= 0; + //lpAddressCaps->dwConnectedModes = 0; + //lpAddressCaps->dwOfferingModes = 0; + + lpAddressCaps->dwAvailableMediaModes = pLineDev->dwMediaModes; + + dwRet = ERROR_SUCCESS; + }; + + // Release the modem CB + // + RELEASE_LINEDEV(pLineDev); + +end: + + DBG_DDI_EXIT("TSPI_lineGetAddressCaps", dwRet); + TRACE4( + IDEVENT_TSPFN_EXIT, + IDFROM_TSPI_lineGetAddressCaps, + &dwDeviceID, + dwRet + ); + + return dwRet; +} + +//**************************************************************************** +// LONG TSPIAPI TSPI_lineGetAddressStatus(HDRVLINE hdLine, +// DWORD dwAddressID, +// LPLINEADDRESSSTATUS lpAddressStatus) +// +// Functions: Get the current status of the specified address for the line. +// +// Return: ERROR_SUCCESS if successful +// LINEERR_INVALLINEHANDLE An invalid line handle +// LINEERR_INVALADDRESSID An invalid address id for the line +//**************************************************************************** + +LONG TSPIAPI TSPI_lineGetAddressStatus(HDRVLINE hdLine, + DWORD dwAddressID, + LPLINEADDRESSSTATUS lpAddressStatus) +{ + PLINEDEV pLineDev; + DWORD dwRet = LINEERR_OPERATIONFAILED; // assume failure + + DBG_HDL_ENTER("TSPI_lineGetAddressStatus"); + TRACE3( + IDEVENT_TSPFN_ENTER, + IDFROM_TSPI_lineGetAddressStatus, + &hdLine + ); + + // Validate the line handle + // + if ((pLineDev = GetCBfromHandle ((DWORD)hdLine)) == NULL) + { + dwRet = LINEERR_INVALLINEHANDLE; + goto end; + } + + // Validate the address ID + // + if (dwAddressID != 0) + { + dwRet = LINEERR_INVALADDRESSID; + } + else + { + //lpAddressStatus->dwUsedSize = sizeof(LINEADDRESSSTATUS); + //lpAddressStatus->dwNeededSize = sizeof(LINEADDRESSSTATUS); + ASSERT(lpAddressStatus->dwNeededSize == sizeof(LINEADDRESSSTATUS)); + + if (pLineDev->dwCall & CALL_ACTIVE) + { + lpAddressStatus->dwNumInUse = 1; + lpAddressStatus->dwNumActiveCalls = (pLineDev->dwCallState != LINECALLSTATE_IDLE) ? + 1 : 0; + } + else + { + lpAddressStatus->dwNumInUse = 0; + lpAddressStatus->dwNumActiveCalls = 0; + }; + + lpAddressStatus->dwAddressFeatures = (pLineDev->dwCall & CALL_ALLOCATED) ? + 0 : LINEADDRFEATURE_MAKECALL; + + //lpAddressStatus->dwNumOnHoldCalls = 0; + //lpAddressStatus->dwNumOnHoldPendCalls = 0; + //lpAddressStatus->dwNumRingsNoAnswer = 0; + + //lpAddressStatus->dwForwardNumEntries = 0; + //lpAddressStatus->dwForwardSize = 0; + //lpAddressStatus->dwForwardOffset = 0; + + //lpAddressStatus->dwTerminalModesSize = 0; + //lpAddressStatus->dwTerminalModesOffset= 0; + + //lpAddressStatus->dwDevSpecificSize = 0; + //lpAddressStatus->dwDevSpecificOffset = 0; + + dwRet=ERROR_SUCCESS; + }; + + // Release the modem CB + // + RELEASE_LINEDEV(pLineDev); + +end: + + DBG_HDL_EXIT("TSPI_lineGetAddressStatus", dwRet); + TRACE4( + IDEVENT_TSPFN_EXIT, + IDFROM_TSPI_lineGetAddressStatus, + &hdLine, + dwRet + ); + + return dwRet; +} + +void SetPendingRequest( + PLINEDEV pLineDev, + DWORD dwRequestID, + DWORD dwRequestOp + ) +{ + ASSERT(pLineDev->dwPendingID == INVALID_PENDINGID); + ASSERT(pLineDev->dwPendingType == INVALID_PENDINGOP); + pLineDev->dwPendingID = dwRequestID; + pLineDev->dwPendingType = dwRequestOp; +} + + +void ClearPendingRequest( + PLINEDEV pLineDev + ) +{ + pLineDev->dwPendingID = INVALID_PENDINGID; + pLineDev->dwPendingType = INVALID_PENDINGOP; +} |