mirror of https://github.com/lianthony/NT4.0
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
3399 lines
95 KiB
3399 lines
95 KiB
//****************************************************************************
|
|
//
|
|
// 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;
|
|
}
|