1918 lines
44 KiB
C
1918 lines
44 KiB
C
|
/*++
|
|||
|
|
|||
|
Copyright (c) 1997 Microsoft Corporation
|
|||
|
|
|||
|
Module Name:
|
|||
|
|
|||
|
line.c
|
|||
|
|
|||
|
Abstract:
|
|||
|
|
|||
|
TAPI Service Provider functions related to manipulating lines.
|
|||
|
|
|||
|
TSPI_lineClose
|
|||
|
TSPI_lineGetDevCaps
|
|||
|
TSPI_lineGetLineDevStatus
|
|||
|
TSPI_lineGetNumAddressIDs
|
|||
|
TSPI_lineOpen
|
|||
|
TSPI_lineSetLineDevStatus
|
|||
|
|
|||
|
Environment:
|
|||
|
|
|||
|
User Mode - Win32
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
///////////////////////////////////////////////////////////////////////////////
|
|||
|
// //
|
|||
|
// Include files //
|
|||
|
// //
|
|||
|
///////////////////////////////////////////////////////////////////////////////
|
|||
|
|
|||
|
#include "globals.h"
|
|||
|
#include "provider.h"
|
|||
|
#include "callback.h"
|
|||
|
#include "registry.h"
|
|||
|
#include "version.h"
|
|||
|
#include "line.h"
|
|||
|
#include "call.h"
|
|||
|
|
|||
|
|
|||
|
///////////////////////////////////////////////////////////////////////////////
|
|||
|
// //
|
|||
|
// Global variables //
|
|||
|
// //
|
|||
|
///////////////////////////////////////////////////////////////////////////////
|
|||
|
|
|||
|
PH323_LINE_TABLE g_pLineTable = NULL;
|
|||
|
DWORD g_dwLineDeviceUniqueID = 0;
|
|||
|
|
|||
|
|
|||
|
///////////////////////////////////////////////////////////////////////////////
|
|||
|
// //
|
|||
|
// Private procedures //
|
|||
|
// //
|
|||
|
///////////////////////////////////////////////////////////////////////////////
|
|||
|
|
|||
|
BOOL
|
|||
|
H323ResetLine(
|
|||
|
PH323_LINE pLine
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Resets line object to original state for re-use.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
pLine - Pointer to line object to reset.
|
|||
|
|
|||
|
Return Values:
|
|||
|
|
|||
|
Returns true if successful.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
// reset state of line object
|
|||
|
pLine->nState = H323_LINESTATE_ALLOCATED;
|
|||
|
|
|||
|
// line not marked for deletion
|
|||
|
pLine->fIsMarkedForDeletion = FALSE;
|
|||
|
|
|||
|
// reset tapi handles
|
|||
|
pLine->hdLine = (HDRVLINE)NULL;
|
|||
|
pLine->htLine = (HTAPILINE)NULL;
|
|||
|
pLine->dwDeviceID = UNINITIALIZED;
|
|||
|
|
|||
|
// reset tapi info
|
|||
|
pLine->dwTSPIVersion = 0;
|
|||
|
pLine->dwMediaModes = 0;
|
|||
|
|
|||
|
// reset bogus handle count
|
|||
|
pLine->dwNextMSPHandle = 0;
|
|||
|
|
|||
|
// uninitialize listen handle
|
|||
|
pLine->hccListen = UNINITIALIZED;
|
|||
|
|
|||
|
// reset line name
|
|||
|
pLine->wszAddr[0] = UNICODE_NULL;
|
|||
|
|
|||
|
// success
|
|||
|
return TRUE;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
BOOL
|
|||
|
H323AllocLine(
|
|||
|
PH323_LINE * ppLine
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Allocates line device.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
ppLine - Pointer to DWORD-sized value which service provider must
|
|||
|
write the newly allocated line.
|
|||
|
|
|||
|
Return Values:
|
|||
|
|
|||
|
Returns true if successful.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
HRESULT hr;
|
|||
|
PH323_LINE pLine;
|
|||
|
|
|||
|
// allocate object from heap
|
|||
|
pLine = H323HeapAlloc(sizeof(H323_LINE));
|
|||
|
|
|||
|
// validate pointer
|
|||
|
if (pLine == NULL) {
|
|||
|
|
|||
|
H323DBG((
|
|||
|
DEBUG_LEVEL_ERROR,
|
|||
|
"could not allocate line object.\n"
|
|||
|
));
|
|||
|
|
|||
|
// failure
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
|
|||
|
__try {
|
|||
|
|
|||
|
// initialize lock (and allocate event immediately)
|
|||
|
InitializeCriticalSectionAndSpinCount(&pLine->Lock,H323_SPIN_COUNT);
|
|||
|
|
|||
|
} __except ((GetExceptionCode() == STATUS_NO_MEMORY)
|
|||
|
? EXCEPTION_EXECUTE_HANDLER
|
|||
|
: EXCEPTION_CONTINUE_SEARCH
|
|||
|
) {
|
|||
|
|
|||
|
// release object
|
|||
|
H323HeapFree(pLine);
|
|||
|
|
|||
|
// failure
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
|
|||
|
// allocate call table
|
|||
|
if (!H323AllocCallTable(&pLine->pCallTable)) {
|
|||
|
|
|||
|
// release critical section
|
|||
|
DeleteCriticalSection(&pLine->Lock);
|
|||
|
|
|||
|
// release object
|
|||
|
H323HeapFree(pLine);
|
|||
|
|
|||
|
// failure
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
|
|||
|
// initialize rtp/rtcp base port
|
|||
|
pLine->dwNextPort = H323_RTPBASEPORT;
|
|||
|
|
|||
|
// reset line
|
|||
|
H323ResetLine(pLine);
|
|||
|
|
|||
|
// transfer
|
|||
|
*ppLine = pLine;
|
|||
|
|
|||
|
// success
|
|||
|
return TRUE;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
BOOL
|
|||
|
H323FreeLine(
|
|||
|
PH323_LINE pLine
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Releases line device.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
pLine - Pointer to line device to release.
|
|||
|
|
|||
|
Return Values:
|
|||
|
|
|||
|
Returns true if successful.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
// validate pointer
|
|||
|
if (pLine != NULL) {
|
|||
|
|
|||
|
// release memory for call table
|
|||
|
H323FreeCallTable(pLine->pCallTable);
|
|||
|
|
|||
|
// release critical section
|
|||
|
DeleteCriticalSection(&pLine->Lock);
|
|||
|
|
|||
|
// release line
|
|||
|
H323HeapFree(pLine);
|
|||
|
}
|
|||
|
|
|||
|
H323DBG((
|
|||
|
DEBUG_LEVEL_VERBOSE,
|
|||
|
"line 0x%08lx released.\n",
|
|||
|
pLine
|
|||
|
));
|
|||
|
|
|||
|
// success
|
|||
|
return TRUE;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
BOOL
|
|||
|
H323OpenLine(
|
|||
|
PH323_LINE pLine,
|
|||
|
HTAPILINE htLine,
|
|||
|
DWORD dwTSPIVersion
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Initiate activities on line device and allocate resources.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
pLine - Pointer to line device to open.
|
|||
|
|
|||
|
htLine - TAPI's handle describing line device to open.
|
|||
|
|
|||
|
dwTSPIVersion - The TSPI version negotiated through
|
|||
|
TSPI_lineNegotiateTSPIVersion under which the Service Provider is
|
|||
|
willing to operate.
|
|||
|
|
|||
|
Return Values:
|
|||
|
|
|||
|
Returns true if successful.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
H323DBG((
|
|||
|
DEBUG_LEVEL_TRACE,
|
|||
|
"line %d opening.\n",
|
|||
|
pLine->dwDeviceID
|
|||
|
));
|
|||
|
|
|||
|
// start listen if necessary
|
|||
|
if (H323IsMediaDetectionEnabled(pLine) &&
|
|||
|
!H323StartListening(pLine)) {
|
|||
|
|
|||
|
// failure
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
|
|||
|
// save line variables now
|
|||
|
pLine->htLine = htLine;
|
|||
|
pLine->dwTSPIVersion = dwTSPIVersion;
|
|||
|
|
|||
|
// change line device state to opened
|
|||
|
pLine->nState = H323_LINESTATE_OPENED;
|
|||
|
|
|||
|
// success
|
|||
|
return TRUE;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
BOOL
|
|||
|
H323CloseLine(
|
|||
|
PH323_LINE pLine
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Terminate activities on line device.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
pLine - Pointer to line device to close.
|
|||
|
|
|||
|
Return Values:
|
|||
|
|
|||
|
Returns true if successful.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
H323DBG((
|
|||
|
DEBUG_LEVEL_TRACE,
|
|||
|
"line %d %s.\n",
|
|||
|
pLine->dwDeviceID,
|
|||
|
pLine->fIsMarkedForDeletion
|
|||
|
? "closing and being removed"
|
|||
|
: "closing"
|
|||
|
));
|
|||
|
|
|||
|
// see if we are listening
|
|||
|
if (H323IsListening(pLine)) {
|
|||
|
|
|||
|
// stop listening first
|
|||
|
H323StopListening(pLine);
|
|||
|
}
|
|||
|
|
|||
|
// change line device state to closing
|
|||
|
pLine->nState = H323_LINESTATE_CLOSING;
|
|||
|
|
|||
|
// close all calls now in table
|
|||
|
H323CloseCallTable(pLine->pCallTable);
|
|||
|
|
|||
|
// delete line if marked
|
|||
|
if (pLine->fIsMarkedForDeletion) {
|
|||
|
|
|||
|
// remove line device from table
|
|||
|
H323FreeLineFromTable(pLine, g_pLineTable);
|
|||
|
|
|||
|
} else {
|
|||
|
|
|||
|
// reset variables
|
|||
|
pLine->htLine = (HTAPILINE)NULL;
|
|||
|
pLine->dwTSPIVersion = 0;
|
|||
|
pLine->dwMediaModes = 0;
|
|||
|
|
|||
|
// change line device state to closed
|
|||
|
pLine->nState = H323_LINESTATE_CLOSED;
|
|||
|
}
|
|||
|
|
|||
|
// success
|
|||
|
return TRUE;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
BOOL
|
|||
|
H323InitializeLine(
|
|||
|
PH323_LINE pLine,
|
|||
|
DWORD dwDeviceID
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Updates line device based on changes in registry.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
pLine - Pointer to line device to update.
|
|||
|
|
|||
|
dwDeviceID - Device ID specified in TSPI_providerInit.
|
|||
|
|
|||
|
Return Values:
|
|||
|
|
|||
|
Returns true if successful.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
DWORD dwSize = sizeof(pLine->wszAddr);
|
|||
|
|
|||
|
// save line device id
|
|||
|
pLine->dwDeviceID = dwDeviceID;
|
|||
|
|
|||
|
// create displayable address
|
|||
|
GetComputerNameW(pLine->wszAddr, &dwSize);
|
|||
|
|
|||
|
H323DBG((
|
|||
|
DEBUG_LEVEL_TRACE,
|
|||
|
"line %d initialized (addr=%S).\n",
|
|||
|
pLine->dwDeviceID,
|
|||
|
pLine->wszAddr
|
|||
|
));
|
|||
|
|
|||
|
// change line device state to closed
|
|||
|
pLine->nState = H323_LINESTATE_CLOSED;
|
|||
|
|
|||
|
// success
|
|||
|
return TRUE;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
///////////////////////////////////////////////////////////////////////////////
|
|||
|
// //
|
|||
|
// Public procedures //
|
|||
|
// //
|
|||
|
///////////////////////////////////////////////////////////////////////////////
|
|||
|
|
|||
|
BOOL
|
|||
|
H323GetLineAndLock(
|
|||
|
PH323_LINE * ppLine,
|
|||
|
HDRVLINE hdLine
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Retrieves pointer to line device given line handle.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
ppLine - Specifies a pointer to a DWORD-sized memory location
|
|||
|
into which the service provider must write the line device pointer
|
|||
|
associated with the given line handle.
|
|||
|
|
|||
|
hdLine - Specifies the Service Provider's opaque handle to the line.
|
|||
|
|
|||
|
Return Values:
|
|||
|
|
|||
|
Returns true if successful.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
DWORD i;
|
|||
|
PH323_LINE pLine = NULL;
|
|||
|
|
|||
|
// lock provider
|
|||
|
H323LockProvider();
|
|||
|
|
|||
|
// retrieve line table index
|
|||
|
i = H323GetLineTableIndex(PtrToUlong(hdLine));
|
|||
|
|
|||
|
// validate line table index
|
|||
|
if (i >= g_pLineTable->dwNumSlots) {
|
|||
|
|
|||
|
H323DBG((
|
|||
|
DEBUG_LEVEL_ERROR,
|
|||
|
"line handle 0x%08lx invalid.\n",
|
|||
|
PtrToUlong(hdLine)
|
|||
|
));
|
|||
|
|
|||
|
// unlock provider
|
|||
|
H323UnlockProvider();
|
|||
|
|
|||
|
// failure
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
|
|||
|
// retrieve line pointer from table
|
|||
|
pLine = g_pLineTable->pLines[i];
|
|||
|
|
|||
|
// validate call information
|
|||
|
if (!H323IsLineEqual(pLine,hdLine)) {
|
|||
|
|
|||
|
H323DBG((
|
|||
|
DEBUG_LEVEL_ERROR,
|
|||
|
"line handle 0x%08lx invalid.\n",
|
|||
|
PtrToUlong(hdLine)
|
|||
|
));
|
|||
|
|
|||
|
// unlock provider
|
|||
|
H323UnlockProvider();
|
|||
|
|
|||
|
// failure
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
|
|||
|
// lock line device
|
|||
|
H323LockLine(pLine);
|
|||
|
|
|||
|
// unlock provider
|
|||
|
H323UnlockProvider();
|
|||
|
|
|||
|
// transfer
|
|||
|
*ppLine = pLine;
|
|||
|
|
|||
|
// success
|
|||
|
return TRUE;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
BOOL
|
|||
|
H323GetLineFromIDAndLock(
|
|||
|
PH323_LINE * ppLine,
|
|||
|
DWORD dwDeviceID
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Retrieves pointer to line device given device id.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
ppLine - Specifies a pointer to a DWORD-sized memory location
|
|||
|
into which the service provider must write the line device pointer
|
|||
|
associated with the given device ID.
|
|||
|
|
|||
|
dwDeviceID - Identifies the line device.
|
|||
|
|
|||
|
Return Values:
|
|||
|
|
|||
|
Returns true if successful.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
DWORD i;
|
|||
|
|
|||
|
// lock provider
|
|||
|
H323LockProvider();
|
|||
|
|
|||
|
// loop through each objectin table
|
|||
|
for (i = 0; i < g_pLineTable->dwNumSlots; i++) {
|
|||
|
|
|||
|
// validate object is allocated
|
|||
|
if (H323IsLineAllocated(g_pLineTable->pLines[i])) {
|
|||
|
|
|||
|
// lock line device
|
|||
|
H323LockLine(g_pLineTable->pLines[i]);
|
|||
|
|
|||
|
// compare stored device id with the one specified
|
|||
|
if (H323IsLineInUse(g_pLineTable->pLines[i]) &&
|
|||
|
(g_pLineTable->pLines[i]->dwDeviceID == dwDeviceID)) {
|
|||
|
|
|||
|
// transfer line device pointer
|
|||
|
*ppLine = g_pLineTable->pLines[i];
|
|||
|
|
|||
|
// unlock provider
|
|||
|
H323UnlockProvider();
|
|||
|
|
|||
|
// success
|
|||
|
return TRUE;
|
|||
|
}
|
|||
|
|
|||
|
// release line device
|
|||
|
H323UnlockLine(g_pLineTable->pLines[i]);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
// unlock provider
|
|||
|
H323UnlockProvider();
|
|||
|
|
|||
|
// initialize
|
|||
|
*ppLine = NULL;
|
|||
|
|
|||
|
// failure
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
BOOL
|
|||
|
H323CallListen(
|
|||
|
PH323_LINE pLine
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Starts listening for calls on given line device.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
pLine - Pointer to line device to start listening.
|
|||
|
|
|||
|
Return Values:
|
|||
|
|
|||
|
Returns true if successful.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
HRESULT hr;
|
|||
|
CC_ADDR ListenAddr;
|
|||
|
|
|||
|
// construct listen address
|
|||
|
ListenAddr.nAddrType = CC_IP_BINARY;
|
|||
|
ListenAddr.Addr.IP_Binary.dwAddr = INADDR_ANY;
|
|||
|
ListenAddr.Addr.IP_Binary.wPort =
|
|||
|
LOWORD(g_RegistrySettings.dwQ931CallSignallingPort);
|
|||
|
ListenAddr.bMulticast = FALSE;
|
|||
|
|
|||
|
// start listening
|
|||
|
hr = CC_CallListen(
|
|||
|
&pLine->hccListen, // phListen
|
|||
|
&ListenAddr, // pListenAddr
|
|||
|
NULL, // pLocalAliasNames
|
|||
|
PtrToUlong(pLine->hdLine), // dwListenToken
|
|||
|
H323ListenCallback // ListenCallback
|
|||
|
);
|
|||
|
|
|||
|
// validate status
|
|||
|
if (hr != S_OK) {
|
|||
|
|
|||
|
H323DBG((
|
|||
|
DEBUG_LEVEL_ERROR,
|
|||
|
"error 0x%08lx calling CC_CallListen.\n", hr
|
|||
|
));
|
|||
|
|
|||
|
// re-initialize call listen handle
|
|||
|
pLine->hccListen = UNINITIALIZED;
|
|||
|
|
|||
|
// failure
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
|
|||
|
H323DBG((
|
|||
|
DEBUG_LEVEL_VERBOSE,
|
|||
|
"line %d listening for incoming calls.\n",
|
|||
|
pLine->dwDeviceID
|
|||
|
));
|
|||
|
|
|||
|
// success
|
|||
|
return TRUE;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
BOOL
|
|||
|
H323StartListening(
|
|||
|
PH323_LINE pLine
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Starts listening for calls on given line device.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
pLine - Pointer to line device to start listening.
|
|||
|
|
|||
|
Return Values:
|
|||
|
|
|||
|
Returns true if successful.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
// attempt to post call listen message
|
|||
|
if (!H323PostCallListenMessage(pLine->hdLine)) {
|
|||
|
|
|||
|
H323DBG((
|
|||
|
DEBUG_LEVEL_ERROR,
|
|||
|
"error 0x%08lx posting call listen.\n",
|
|||
|
GetLastError()
|
|||
|
));
|
|||
|
|
|||
|
// failure
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
|
|||
|
// change state to listening
|
|||
|
pLine->nState = H323_LINESTATE_LISTENING;
|
|||
|
|
|||
|
// success
|
|||
|
return TRUE;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
BOOL
|
|||
|
H323StopListening(
|
|||
|
PH323_LINE pLine
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Stops listening for calls on given line device.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
pLine - Pointer to line device to stop listening.
|
|||
|
|
|||
|
Return Values:
|
|||
|
|
|||
|
Returns true if successful.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
HRESULT hr;
|
|||
|
|
|||
|
// stop listening
|
|||
|
hr = CC_CancelListen(pLine->hccListen);
|
|||
|
|
|||
|
// validate status
|
|||
|
if (hr != S_OK) {
|
|||
|
|
|||
|
H323DBG((
|
|||
|
DEBUG_LEVEL_ERROR,
|
|||
|
"error 0x%08lx calling CC_CancelListen.\n", hr
|
|||
|
));
|
|||
|
|
|||
|
//
|
|||
|
// Unable to cancel listen on line
|
|||
|
// device so uninitialize handle and
|
|||
|
// continue...
|
|||
|
//
|
|||
|
}
|
|||
|
|
|||
|
// change state to opened
|
|||
|
pLine->nState = H323_LINESTATE_OPENED;
|
|||
|
|
|||
|
// uninitialize listen handle
|
|||
|
pLine->hccListen = UNINITIALIZED;
|
|||
|
|
|||
|
H323DBG((
|
|||
|
DEBUG_LEVEL_VERBOSE,
|
|||
|
"line %d no longer listening for incoming calls.\n",
|
|||
|
pLine->dwDeviceID
|
|||
|
));
|
|||
|
|
|||
|
// success
|
|||
|
return TRUE;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
BOOL
|
|||
|
H323AllocLineTable(
|
|||
|
PH323_LINE_TABLE * ppLineTable
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Allocates table of line objects.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
ppLineTable - Pointer to LPVOID-size memory location in which
|
|||
|
service provider will write pointer to line table.
|
|||
|
|
|||
|
Return Values:
|
|||
|
|
|||
|
Returns true if successful.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
int i;
|
|||
|
DWORD dwStatus;
|
|||
|
PH323_LINE_TABLE pLineTable;
|
|||
|
PH323_LINE pLine;
|
|||
|
BOOL fOk = FALSE;
|
|||
|
|
|||
|
// allocate table from heap
|
|||
|
pLineTable = H323HeapAlloc(
|
|||
|
sizeof(H323_LINE_TABLE) +
|
|||
|
sizeof(PH323_LINE) * H323_DEFLINESPERINST
|
|||
|
);
|
|||
|
|
|||
|
// validate table pointer
|
|||
|
if (pLineTable == NULL) {
|
|||
|
|
|||
|
H323DBG((
|
|||
|
DEBUG_LEVEL_ERROR,
|
|||
|
"could not allocate line table.\n"
|
|||
|
));
|
|||
|
|
|||
|
// failure
|
|||
|
goto cleanup;
|
|||
|
}
|
|||
|
|
|||
|
// initialize number of slots
|
|||
|
pLineTable->dwNumSlots = H323_DEFLINESPERINST;
|
|||
|
|
|||
|
// allocate line device
|
|||
|
if (!H323AllocLineFromTable(&pLine,&pLineTable)) {
|
|||
|
|
|||
|
H323DBG((
|
|||
|
DEBUG_LEVEL_ERROR,
|
|||
|
"could not allocate default line.\n"
|
|||
|
));
|
|||
|
|
|||
|
// failure
|
|||
|
goto cleanup;
|
|||
|
}
|
|||
|
|
|||
|
// transfer pointer
|
|||
|
*ppLineTable = pLineTable;
|
|||
|
|
|||
|
// re-initialize
|
|||
|
pLineTable = NULL;
|
|||
|
|
|||
|
// success
|
|||
|
fOk = TRUE;
|
|||
|
|
|||
|
cleanup:
|
|||
|
|
|||
|
// validate pointer
|
|||
|
if (pLineTable != NULL) {
|
|||
|
|
|||
|
// free new table
|
|||
|
H323FreeLineTable(pLineTable);
|
|||
|
}
|
|||
|
|
|||
|
// done...
|
|||
|
return fOk;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
BOOL
|
|||
|
H323FreeLineTable(
|
|||
|
PH323_LINE_TABLE pLineTable
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Deallocates table of line objects.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
pLineTable - Pointer to line table to release.
|
|||
|
|
|||
|
Return Values:
|
|||
|
|
|||
|
Returns true if successful.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
DWORD i;
|
|||
|
|
|||
|
// loop through each object in table
|
|||
|
for (i = 0; i < pLineTable->dwNumSlots; i++) {
|
|||
|
|
|||
|
// validate object has been allocated
|
|||
|
if (H323IsLineAllocated(pLineTable->pLines[i])) {
|
|||
|
|
|||
|
// release memory for object
|
|||
|
H323FreeLine(pLineTable->pLines[i]);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
// release memory for table
|
|||
|
H323HeapFree(pLineTable);
|
|||
|
|
|||
|
// success
|
|||
|
return TRUE;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
BOOL
|
|||
|
H323CloseLineTable(
|
|||
|
PH323_LINE_TABLE pLineTable
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Closes table of line objects.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
pLineTable - Pointer to table to close.
|
|||
|
|
|||
|
Return Values:
|
|||
|
|
|||
|
Returns true if successful.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
DWORD i;
|
|||
|
|
|||
|
// loop through each objectin table
|
|||
|
for (i = 0; i < pLineTable->dwNumSlots; i++) {
|
|||
|
|
|||
|
// validate object is allocated
|
|||
|
if (H323IsLineAllocated(pLineTable->pLines[i])) {
|
|||
|
|
|||
|
// lock line device
|
|||
|
H323LockLine(pLineTable->pLines[i]);
|
|||
|
|
|||
|
// see if line device in use
|
|||
|
if (H323IsLineInUse(pLineTable->pLines[i])) {
|
|||
|
|
|||
|
// close previously opened object
|
|||
|
H323CloseLine(pLineTable->pLines[i]);
|
|||
|
}
|
|||
|
|
|||
|
// release line device
|
|||
|
H323UnlockLine(pLineTable->pLines[i]);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
// reset table information
|
|||
|
pLineTable->dwNumInUse = 0;
|
|||
|
pLineTable->dwNextAvailable = 0;
|
|||
|
|
|||
|
// success
|
|||
|
return TRUE;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
BOOL
|
|||
|
H323AllocLineFromTable(
|
|||
|
PH323_LINE * ppLine,
|
|||
|
PH323_LINE_TABLE * ppLineTable
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Allocates line object in table.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
ppLine - Specifies a pointer to a DWORD-sized value in which the
|
|||
|
service provider must write the allocated line object.
|
|||
|
|
|||
|
ppLineTable - Pointer to pointer to line table in which to
|
|||
|
allocate line from (expands table if necessary).
|
|||
|
|
|||
|
Return Values:
|
|||
|
|
|||
|
Returns true if successful.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
DWORD i;
|
|||
|
PH323_LINE pLine = NULL;
|
|||
|
PH323_LINE_TABLE pLineTable = *ppLineTable;
|
|||
|
|
|||
|
// retrieve index to next entry
|
|||
|
i = pLineTable->dwNextAvailable;
|
|||
|
|
|||
|
// see if previously allocated entries available
|
|||
|
if (pLineTable->dwNumAllocated > pLineTable->dwNumInUse) {
|
|||
|
|
|||
|
// search table looking for available entry
|
|||
|
while (H323IsLineInUse(pLineTable->pLines[i]) ||
|
|||
|
!H323IsLineAllocated(pLineTable->pLines[i])) {
|
|||
|
|
|||
|
// increment index and adjust to wrap
|
|||
|
i = H323GetNextIndex(i, pLineTable->dwNumSlots);
|
|||
|
}
|
|||
|
|
|||
|
// retrieve pointer to object
|
|||
|
pLine = pLineTable->pLines[i];
|
|||
|
|
|||
|
// mark entry as waiting for line device id
|
|||
|
pLine->nState = H323_LINESTATE_WAITING_FOR_ID;
|
|||
|
|
|||
|
// initialize call handle with index
|
|||
|
pLine->hdLine = H323CreateLineHandle(i);
|
|||
|
|
|||
|
// temporary device id
|
|||
|
pLine->dwDeviceID = PtrToUlong(pLine->hdLine);
|
|||
|
|
|||
|
// increment number in use
|
|||
|
pLineTable->dwNumInUse++;
|
|||
|
|
|||
|
// adjust next available index
|
|||
|
pLineTable->dwNextAvailable =
|
|||
|
H323GetNextIndex(i, pLineTable->dwNumSlots);
|
|||
|
|
|||
|
// transfer pointer
|
|||
|
*ppLine = pLine;
|
|||
|
|
|||
|
// success
|
|||
|
return TRUE;
|
|||
|
}
|
|||
|
|
|||
|
// see if table is full and more slots need to be allocated
|
|||
|
if (pLineTable->dwNumAllocated == pLineTable->dwNumSlots) {
|
|||
|
|
|||
|
// attempt to double table
|
|||
|
pLineTable = H323HeapReAlloc(
|
|||
|
pLineTable,
|
|||
|
sizeof(H323_LINE_TABLE) +
|
|||
|
pLineTable->dwNumSlots * 2 * sizeof(PH323_LINE)
|
|||
|
);
|
|||
|
|
|||
|
// validate pointer
|
|||
|
if (pLineTable == NULL) {
|
|||
|
|
|||
|
H323DBG((
|
|||
|
DEBUG_LEVEL_ERROR,
|
|||
|
"could not expand channel table.\n"
|
|||
|
));
|
|||
|
|
|||
|
// failure
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
|
|||
|
// adjust index into table
|
|||
|
i = pLineTable->dwNumSlots;
|
|||
|
|
|||
|
// adjust number of slots
|
|||
|
pLineTable->dwNumSlots *= 2;
|
|||
|
|
|||
|
// transfer pointer to caller
|
|||
|
*ppLineTable = pLineTable;
|
|||
|
}
|
|||
|
|
|||
|
// allocate new object
|
|||
|
if (!H323AllocLine(&pLine)) {
|
|||
|
|
|||
|
// failure
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
|
|||
|
// search table looking for slot with no object allocated
|
|||
|
while (H323IsLineAllocated(pLineTable->pLines[i])) {
|
|||
|
|
|||
|
// increment index and adjust to wrap
|
|||
|
i = H323GetNextIndex(i, pLineTable->dwNumSlots);
|
|||
|
}
|
|||
|
|
|||
|
// store pointer to object
|
|||
|
pLineTable->pLines[i] = pLine;
|
|||
|
|
|||
|
// mark entry as being in use
|
|||
|
pLine->nState = H323_LINESTATE_CLOSED;
|
|||
|
|
|||
|
// initialize call handle with index
|
|||
|
pLine->hdLine = H323CreateLineHandle(i);
|
|||
|
|
|||
|
// temporary device id
|
|||
|
pLine->dwDeviceID = PtrToUlong(pLine->hdLine);
|
|||
|
|
|||
|
// increment number in use
|
|||
|
pLineTable->dwNumInUse++;
|
|||
|
|
|||
|
// increment number allocated
|
|||
|
pLineTable->dwNumAllocated++;
|
|||
|
|
|||
|
// adjust next available index
|
|||
|
pLineTable->dwNextAvailable =
|
|||
|
H323GetNextIndex(i, pLineTable->dwNumSlots);
|
|||
|
|
|||
|
// transfer pointer
|
|||
|
*ppLine = pLine;
|
|||
|
|
|||
|
// success
|
|||
|
return TRUE;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
BOOL
|
|||
|
H323FreeLineFromTable(
|
|||
|
PH323_LINE pLine,
|
|||
|
PH323_LINE_TABLE pLineTable
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Deallocates line object in table.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
pLine - Pointer to object to deallocate.
|
|||
|
|
|||
|
pLineTable - Pointer to table containing object.
|
|||
|
|
|||
|
Return Values:
|
|||
|
|
|||
|
Returns true if successful.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
// reset line object
|
|||
|
H323ResetLine(pLine);
|
|||
|
|
|||
|
// decrement entries in use
|
|||
|
pLineTable->dwNumInUse--;
|
|||
|
|
|||
|
// success
|
|||
|
return TRUE;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
BOOL
|
|||
|
H323InitializeLineTable(
|
|||
|
PH323_LINE_TABLE pLineTable,
|
|||
|
DWORD dwLineDeviceIDBase
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Updates line devices based on changes to registry settings.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
pLineTable - Pointer to line table to update.
|
|||
|
|
|||
|
dwLineDeviceIDBase - Device ID specified in TSPI_providerInit.
|
|||
|
|
|||
|
Return Values:
|
|||
|
|
|||
|
Returns true if successful.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
UINT i;
|
|||
|
|
|||
|
// loop through line device structures
|
|||
|
for (i = 0; i < pLineTable->dwNumSlots; i++) {
|
|||
|
|
|||
|
// see if line is allocated
|
|||
|
if (H323IsLineAllocated(pLineTable->pLines[i])) {
|
|||
|
|
|||
|
// lock line device
|
|||
|
H323LockLine(pLineTable->pLines[i]);
|
|||
|
|
|||
|
// see if line device is in user
|
|||
|
if (H323IsLineInUse(pLineTable->pLines[i])) {
|
|||
|
|
|||
|
// update settings
|
|||
|
H323InitializeLine(
|
|||
|
pLineTable->pLines[i],
|
|||
|
dwLineDeviceIDBase + g_dwLineDeviceUniqueID++
|
|||
|
);
|
|||
|
}
|
|||
|
|
|||
|
// unlock line device
|
|||
|
H323UnlockLine(pLineTable->pLines[i]);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
// success
|
|||
|
return TRUE;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
BOOL
|
|||
|
H323RemoveLine(
|
|||
|
PH323_LINE pLine
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Adds line device to line table.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
pLine - Pointer to line device to remove.
|
|||
|
|
|||
|
Return Values:
|
|||
|
|
|||
|
Returns true if successful.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
// mark line as about to be removed
|
|||
|
pLine->fIsMarkedForDeletion = TRUE;
|
|||
|
|
|||
|
// fire close event
|
|||
|
(*g_pfnLineEventProc)(
|
|||
|
(HTAPILINE)0, // htLine
|
|||
|
(HTAPICALL)0, // htCall
|
|||
|
LINE_REMOVE, // dwMsg
|
|||
|
pLine->dwDeviceID, // dwParam1
|
|||
|
0, // dwParam2
|
|||
|
0 // dwParam3
|
|||
|
);
|
|||
|
|
|||
|
// see if line closed
|
|||
|
if (H323IsLineClosed(pLine)) {
|
|||
|
|
|||
|
H323DBG((
|
|||
|
DEBUG_LEVEL_TRACE,
|
|||
|
"line %d being removed.\n",
|
|||
|
pLine->dwDeviceID
|
|||
|
));
|
|||
|
|
|||
|
// remove line device from table
|
|||
|
H323FreeLineFromTable(pLine, g_pLineTable);
|
|||
|
}
|
|||
|
|
|||
|
// success
|
|||
|
return TRUE;
|
|||
|
}
|
|||
|
|
|||
|
#if defined(DBG) && defined(DEBUG_CRITICAL_SECTIONS)
|
|||
|
|
|||
|
|
|||
|
VOID
|
|||
|
H323LockLine(
|
|||
|
PH323_LINE pLine
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Locks line device.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
pLine - Pointer to line to lock.
|
|||
|
|
|||
|
Return Values:
|
|||
|
|
|||
|
None.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
H323DBG((
|
|||
|
DEBUG_LEVEL_VERBOSE,
|
|||
|
"line %d about to be locked.\n",
|
|||
|
pLine->dwDeviceID
|
|||
|
));
|
|||
|
|
|||
|
// lock line device
|
|||
|
EnterCriticalSection(&pLine->Lock);
|
|||
|
|
|||
|
H323DBG((
|
|||
|
DEBUG_LEVEL_VERBOSE,
|
|||
|
"line %d locked.\n",
|
|||
|
pLine->dwDeviceID
|
|||
|
));
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
VOID
|
|||
|
H323UnlockLine(
|
|||
|
PH323_LINE pLine
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Unlocks line device.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
pLine - Pointer to line to unlock.
|
|||
|
|
|||
|
Return Values:
|
|||
|
|
|||
|
None.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
// unlock line device
|
|||
|
LeaveCriticalSection(&pLine->Lock);
|
|||
|
|
|||
|
H323DBG((
|
|||
|
DEBUG_LEVEL_VERBOSE,
|
|||
|
"line %d unlocked.\n",
|
|||
|
pLine->dwDeviceID
|
|||
|
));
|
|||
|
}
|
|||
|
|
|||
|
#endif // DBG && DEBUG_CRITICAL_SECTIONS
|
|||
|
|
|||
|
|
|||
|
///////////////////////////////////////////////////////////////////////////////
|
|||
|
// //
|
|||
|
// TSPI procedures //
|
|||
|
// //
|
|||
|
///////////////////////////////////////////////////////////////////////////////
|
|||
|
|
|||
|
LONG
|
|||
|
TSPIAPI
|
|||
|
TSPI_lineClose(
|
|||
|
HDRVLINE hdLine
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This function closes the specified open line device after completing or
|
|||
|
aborting all outstanding calls and asynchronous operations on the device.
|
|||
|
|
|||
|
The Service Provider has the responsibility to (eventually) report
|
|||
|
completion for every operation it decides to execute asynchronously.
|
|||
|
If this procedure is called for a line on which there are outstanding
|
|||
|
asynchronous operations, the operations should be reported complete with an
|
|||
|
appropriate result or error code before this procedure returns. Generally
|
|||
|
the TAPI DLL would wait for these to complete in an orderly fashion.
|
|||
|
However, the Service Provider should be prepared to handle an early call to
|
|||
|
TSPI_lineClose in "abort" or "emergency shutdown" situtations.
|
|||
|
|
|||
|
A similar requirement exists for active calls on the line. Such calls must
|
|||
|
be dropped, with outstanding operations reported complete with appropriate
|
|||
|
result or error codes.
|
|||
|
|
|||
|
After this procedure returns the Service Provider must report no further
|
|||
|
events on the line or calls that were on the line. The Service Provider's
|
|||
|
opaque handles for the line and calls on the line become "invalid".
|
|||
|
|
|||
|
The Service Provider must relinquish non-sharable resources it reserves
|
|||
|
while the line is open. For example, closing a line accessed through a
|
|||
|
comm port and modem should result in closing the comm port, making it once
|
|||
|
available for use by other applications.
|
|||
|
|
|||
|
This function is presumed to complete successfully and synchronously.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
hdLine - Specifies the Service Provider's opaque handle to the line to be
|
|||
|
closed. After the line has been successfully closed, this handle is
|
|||
|
no longer valid.
|
|||
|
|
|||
|
Return Values:
|
|||
|
|
|||
|
Returns zero if the function is successful, or a negative error
|
|||
|
number if an error has occurred. Possible error returns are:
|
|||
|
|
|||
|
LINEERR_INVALLINEHANDLE - The specified device handle is invalid.
|
|||
|
|
|||
|
LINEERR_OPERATIONFAILED - The specified operation failed for unknown
|
|||
|
reasons.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
PH323_LINE pLine = NULL;
|
|||
|
|
|||
|
// retrieve line pointer from handle
|
|||
|
if (!H323GetLineAndLock(&pLine, hdLine)) {
|
|||
|
|
|||
|
// invalid line handle
|
|||
|
return LINEERR_INVALLINEHANDLE;
|
|||
|
}
|
|||
|
|
|||
|
// attempt to close line device
|
|||
|
if (!H323CloseLine(pLine)) {
|
|||
|
|
|||
|
// release line device
|
|||
|
H323UnlockLine(pLine);
|
|||
|
|
|||
|
// could not close line device
|
|||
|
return LINEERR_OPERATIONFAILED;
|
|||
|
}
|
|||
|
|
|||
|
// release line device
|
|||
|
H323UnlockLine(pLine);
|
|||
|
|
|||
|
// success
|
|||
|
return NOERROR;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
LONG
|
|||
|
TSPIAPI
|
|||
|
TSPI_lineGetDevCaps(
|
|||
|
DWORD dwDeviceID,
|
|||
|
DWORD dwTSPIVersion,
|
|||
|
DWORD dwExtVersion,
|
|||
|
LPLINEDEVCAPS pLineDevCaps
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This function queries a specified line device to determine its telephony
|
|||
|
capabilities. The returned information is valid for all addresses on the
|
|||
|
line device.
|
|||
|
|
|||
|
Line device ID numbering for a Service Provider is sequential from the
|
|||
|
value set by the function TSPI_lineSetDeviceIDBase.
|
|||
|
|
|||
|
The dwExtVersion field of pLineDevCaps has already been filled in to
|
|||
|
indicate the version number of the Extension information requested. If
|
|||
|
it is zero, no Extension information is requested. If it is non-zero it
|
|||
|
holds a value that has already been negotiated for this device with the
|
|||
|
function TSPI_lineNegotiateExtVersion. The Service Provider should fill
|
|||
|
in Extension information according to the Extension version specified.
|
|||
|
|
|||
|
One of the fields in the LINEDEVCAPS structure returned by this function
|
|||
|
contains the number of addresses assigned to the specified line device.
|
|||
|
The actual address IDs used to reference individual addresses vary from
|
|||
|
zero to one less than the returned number. The capabilities of each
|
|||
|
address may be different. Use TSPI_lineGetAddressCaps for each available
|
|||
|
<dwDeviceID, dwAddressID> combination to determine the exact capabilities
|
|||
|
of each address.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
dwDeviceID - Specifies the line device to be queried.
|
|||
|
|
|||
|
dwTSPIVersion - Specifies the negotiated TSPI version number. This value
|
|||
|
has already been negotiated for this device through the
|
|||
|
TSPI_lineNegotiateTSPIVersion function.
|
|||
|
|
|||
|
pLineDevCaps - Specifies a far pointer to a variable sized structure of
|
|||
|
type LINEDEVCAPS. Upon successful completion of the request, this
|
|||
|
structure is filled with line device capabilities information.
|
|||
|
|
|||
|
Return Values:
|
|||
|
|
|||
|
Returns zero if the function is successful or a negative error
|
|||
|
number if an error has occurred. Possible error returns are:
|
|||
|
|
|||
|
LINEERR_BADDEVICEID - The specified line device ID is out of range.
|
|||
|
|
|||
|
LINEERR_INCOMPATIBLEAPIVERSION - The application requested an API
|
|||
|
version or version range that is either incompatible or cannot
|
|||
|
be supported by the Telephony API implementation and/or
|
|||
|
corresponding service provider.
|
|||
|
|
|||
|
LINEERR_STRUCTURETOOSMALL - The dwTotalSize member of a structure
|
|||
|
does not specify enough memory to contain the fixed portion of
|
|||
|
the structure. The dwNeededSize field has been set to the amount
|
|||
|
required.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
DWORD dwLineNameSize;
|
|||
|
DWORD dwProviderInfoSize;
|
|||
|
|
|||
|
PH323_LINE pLine = NULL;
|
|||
|
|
|||
|
// make sure this is a version we support
|
|||
|
if (!H323ValidateTSPIVersion(dwTSPIVersion)) {
|
|||
|
|
|||
|
// do not support tspi version
|
|||
|
return LINEERR_INCOMPATIBLEAPIVERSION;
|
|||
|
}
|
|||
|
|
|||
|
// make sure this is a version we support
|
|||
|
if (!H323ValidateExtVersion(dwExtVersion)) {
|
|||
|
|
|||
|
// do not support extensions
|
|||
|
return LINEERR_INVALEXTVERSION;
|
|||
|
}
|
|||
|
|
|||
|
// retrieve line device pointer from device id
|
|||
|
if (!H323GetLineFromIDAndLock(&pLine, dwDeviceID)) {
|
|||
|
|
|||
|
// invalid line device id
|
|||
|
return LINEERR_BADDEVICEID;
|
|||
|
}
|
|||
|
|
|||
|
// determine string lengths
|
|||
|
dwProviderInfoSize = H323SizeOfWSZ(g_pwszProviderInfo);
|
|||
|
dwLineNameSize = H323SizeOfWSZ(g_pwszLineName);
|
|||
|
|
|||
|
// calculate number of bytes required
|
|||
|
pLineDevCaps->dwNeededSize = sizeof(LINEDEVCAPS) +
|
|||
|
dwProviderInfoSize +
|
|||
|
dwLineNameSize
|
|||
|
;
|
|||
|
|
|||
|
// make sure buffer is large enough for variable length data
|
|||
|
if (pLineDevCaps->dwTotalSize >= pLineDevCaps->dwNeededSize) {
|
|||
|
|
|||
|
// record amount of memory used
|
|||
|
pLineDevCaps->dwUsedSize = pLineDevCaps->dwNeededSize;
|
|||
|
|
|||
|
// position provider info after fixed portion
|
|||
|
pLineDevCaps->dwProviderInfoSize = dwProviderInfoSize;
|
|||
|
pLineDevCaps->dwProviderInfoOffset = sizeof(LINEDEVCAPS);
|
|||
|
|
|||
|
// position line name after device class
|
|||
|
pLineDevCaps->dwLineNameSize = dwLineNameSize;
|
|||
|
pLineDevCaps->dwLineNameOffset =
|
|||
|
pLineDevCaps->dwProviderInfoOffset +
|
|||
|
pLineDevCaps->dwProviderInfoSize
|
|||
|
;
|
|||
|
|
|||
|
// copy provider info after fixed portion
|
|||
|
memcpy((LPBYTE)pLineDevCaps + pLineDevCaps->dwProviderInfoOffset,
|
|||
|
(LPBYTE)g_pwszProviderInfo,
|
|||
|
pLineDevCaps->dwProviderInfoSize
|
|||
|
);
|
|||
|
|
|||
|
// copy line name after device class
|
|||
|
memcpy((LPBYTE)pLineDevCaps + pLineDevCaps->dwLineNameOffset,
|
|||
|
(LPBYTE)g_pwszLineName,
|
|||
|
pLineDevCaps->dwLineNameSize
|
|||
|
);
|
|||
|
|
|||
|
} else if (pLineDevCaps->dwTotalSize >= sizeof(LINEDEVCAPS)) {
|
|||
|
|
|||
|
H323DBG((
|
|||
|
DEBUG_LEVEL_WARNING,
|
|||
|
"linedevcaps structure too small for strings.\n"
|
|||
|
));
|
|||
|
|
|||
|
// structure only contains fixed portion
|
|||
|
pLineDevCaps->dwUsedSize = sizeof(LINEDEVCAPS);
|
|||
|
|
|||
|
} else {
|
|||
|
|
|||
|
H323DBG((
|
|||
|
DEBUG_LEVEL_WARNING,
|
|||
|
"linedevcaps structure too small.\n"
|
|||
|
));
|
|||
|
|
|||
|
// release line device
|
|||
|
H323UnlockLine(pLine);
|
|||
|
|
|||
|
// structure is too small
|
|||
|
return LINEERR_STRUCTURETOOSMALL;
|
|||
|
}
|
|||
|
|
|||
|
H323DBG((
|
|||
|
DEBUG_LEVEL_VERBOSE,
|
|||
|
"line %d capabilities requested.\n",
|
|||
|
pLine->dwDeviceID
|
|||
|
));
|
|||
|
|
|||
|
// construct permanent line identifier
|
|||
|
pLineDevCaps->dwPermanentLineID = (DWORD)MAKELONG(
|
|||
|
dwDeviceID - g_dwLineDeviceIDBase,
|
|||
|
g_dwPermanentProviderID
|
|||
|
);
|
|||
|
|
|||
|
// notify tapi that strings returned are in unicode
|
|||
|
pLineDevCaps->dwStringFormat = STRINGFORMAT_UNICODE;
|
|||
|
|
|||
|
// initialize line device capabilities
|
|||
|
pLineDevCaps->dwNumAddresses = H323_MAXADDRSPERLINE;
|
|||
|
pLineDevCaps->dwMaxNumActiveCalls = H323_MAXCALLSPERLINE;
|
|||
|
pLineDevCaps->dwAddressModes = H323_LINE_ADDRESSMODES;
|
|||
|
pLineDevCaps->dwBearerModes = H323_LINE_BEARERMODES;
|
|||
|
pLineDevCaps->dwDevCapFlags = H323_LINE_DEVCAPFLAGS;
|
|||
|
pLineDevCaps->dwLineFeatures = H323_LINE_LINEFEATURES;
|
|||
|
pLineDevCaps->dwMaxRate = H323_LINE_MAXRATE;
|
|||
|
pLineDevCaps->dwMediaModes = H323_LINE_MEDIAMODES;
|
|||
|
pLineDevCaps->dwRingModes = 0;
|
|||
|
|
|||
|
// initialize address types to include phone numbers
|
|||
|
pLineDevCaps->dwAddressTypes = H323_LINE_ADDRESSTYPES;
|
|||
|
|
|||
|
// line guid
|
|||
|
memcpy(
|
|||
|
&pLineDevCaps->PermanentLineGuid,
|
|||
|
&LINE_H323,
|
|||
|
sizeof(GUID)
|
|||
|
);
|
|||
|
|
|||
|
// modify GUID to be unique for each line
|
|||
|
pLineDevCaps->PermanentLineGuid.Data1 +=
|
|||
|
dwDeviceID - g_dwLineDeviceIDBase;
|
|||
|
|
|||
|
// protocol guid
|
|||
|
memcpy(
|
|||
|
&pLineDevCaps->ProtocolGuid,
|
|||
|
&TAPIPROTOCOL_H323,
|
|||
|
sizeof(GUID)
|
|||
|
);
|
|||
|
|
|||
|
// add dtmf support via H.245 user input messages
|
|||
|
pLineDevCaps->dwGenerateDigitModes = LINEDIGITMODE_DTMF;
|
|||
|
pLineDevCaps->dwMonitorDigitModes = LINEDIGITMODE_DTMF;
|
|||
|
|
|||
|
// release line device
|
|||
|
H323UnlockLine(pLine);
|
|||
|
|
|||
|
// success
|
|||
|
return NOERROR;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
LONG
|
|||
|
TSPIAPI
|
|||
|
TSPI_lineGetLineDevStatus(
|
|||
|
HDRVLINE hdLine,
|
|||
|
LPLINEDEVSTATUS pLineDevStatus
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This operation enables the TAPI DLL to query the specified open line
|
|||
|
device for its current status.
|
|||
|
|
|||
|
The TAPI DLL uses TSPI_lineGetLineDevStatus to query the line device
|
|||
|
for its current line status. This status information applies globally
|
|||
|
to all addresses on the line device. Use TSPI_lineGetAddressStatus to
|
|||
|
determine status information about a specific address on a line.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
hdLine - Specifies the Service Provider's opaque handle to the line
|
|||
|
to be queried.
|
|||
|
|
|||
|
pLineDevStatus - Specifies a far pointer to a variable sized data
|
|||
|
structure of type LINEDEVSTATUS. Upon successful completion of
|
|||
|
the request, this structure is filled with the line's device status.
|
|||
|
|
|||
|
Return Values:
|
|||
|
|
|||
|
Returns zero if the function is successful or a negative error
|
|||
|
number if an error has occurred. Possible error returns are:
|
|||
|
|
|||
|
LINEERR_INVALLINEHANDLE - The specified line device handle is invalid.
|
|||
|
|
|||
|
LINEERR_STRUCTURETOOSMALL - The dwTotalSize member of a structure does
|
|||
|
not specify enough memory to contain the fixed portion of the
|
|||
|
structure. The dwNeededSize field has been set to the amount
|
|||
|
required.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
PH323_LINE pLine = NULL;
|
|||
|
|
|||
|
// retrieve line device pointer from handle
|
|||
|
if (!H323GetLineAndLock(&pLine, hdLine)) {
|
|||
|
|
|||
|
// invalid line device handle
|
|||
|
return LINEERR_INVALLINEHANDLE;
|
|||
|
}
|
|||
|
|
|||
|
// determine number of bytes needed
|
|||
|
pLineDevStatus->dwNeededSize = sizeof(LINEDEVSTATUS);
|
|||
|
|
|||
|
// see if allocated structure is large enough
|
|||
|
if (pLineDevStatus->dwTotalSize < pLineDevStatus->dwNeededSize) {
|
|||
|
|
|||
|
H323DBG((
|
|||
|
DEBUG_LEVEL_ERROR,
|
|||
|
"linedevstatus structure too small.\n"
|
|||
|
));
|
|||
|
|
|||
|
// release line device
|
|||
|
H323UnlockLine(pLine);
|
|||
|
|
|||
|
// structure too small
|
|||
|
return LINEERR_STRUCTURETOOSMALL;
|
|||
|
}
|
|||
|
|
|||
|
// record number of bytes used
|
|||
|
pLineDevStatus->dwUsedSize = pLineDevStatus->dwNeededSize;
|
|||
|
|
|||
|
// initialize supported line device status fields
|
|||
|
pLineDevStatus->dwLineFeatures = H323_LINE_LINEFEATURES;
|
|||
|
pLineDevStatus->dwDevStatusFlags = H323_LINE_DEVSTATUSFLAGS;
|
|||
|
|
|||
|
// determine number of active calls on the line device
|
|||
|
pLineDevStatus->dwNumActiveCalls = pLine->pCallTable->dwNumInUse;
|
|||
|
|
|||
|
// release line device
|
|||
|
H323UnlockLine(pLine);
|
|||
|
|
|||
|
// success
|
|||
|
return NOERROR;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
LONG
|
|||
|
TSPIAPI
|
|||
|
TSPI_lineGetNumAddressIDs(
|
|||
|
HDRVLINE hdLine,
|
|||
|
LPDWORD pdwNumAddressIDs
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Retrieves the number of address IDs supported on the indicated line.
|
|||
|
|
|||
|
This function is called by TAPI.DLL in response to an application calling
|
|||
|
lineSetNumRings, lineGetNumRings, or lineGetNewCalls. TAPI.DLL uses the
|
|||
|
retrieved value to determine if the specified address ID is within the
|
|||
|
range supported by the service provider.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
hdLine - Specifies the handle to the line for which the number of address
|
|||
|
IDs is to be retrieved.
|
|||
|
|
|||
|
pdwNumAddressIDs - Specifies a far pointer to a DWORD. The location is
|
|||
|
filled with the number of address IDs supported on the indicated line.
|
|||
|
The value should be one or larger.
|
|||
|
|
|||
|
Return Values:
|
|||
|
|
|||
|
Returns zero if the function is successful, or a negative error number
|
|||
|
if an error has occurred. Possible return values are as follows:
|
|||
|
|
|||
|
LINEERR_INVALLINEHANDLE - The specified line device handle is invalid.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
PH323_LINE pLine = NULL;
|
|||
|
|
|||
|
// retrieve line device pointer from handle
|
|||
|
if (!H323GetLineAndLock(&pLine, hdLine)) {
|
|||
|
|
|||
|
// invalid line device handle
|
|||
|
return LINEERR_INVALLINEHANDLE;
|
|||
|
}
|
|||
|
|
|||
|
// transfer number of addresses
|
|||
|
*pdwNumAddressIDs = H323_MAXADDRSPERLINE;
|
|||
|
|
|||
|
// release line device
|
|||
|
H323UnlockLine(pLine);
|
|||
|
|
|||
|
// success
|
|||
|
return NOERROR;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
LONG
|
|||
|
TSPIAPI
|
|||
|
TSPI_lineOpen(
|
|||
|
DWORD dwDeviceID,
|
|||
|
HTAPILINE htLine,
|
|||
|
LPHDRVLINE phdLine,
|
|||
|
DWORD dwTSPIVersion,
|
|||
|
LINEEVENT pfnEventProc
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This function opens the line device whose device ID is given, returning
|
|||
|
the Service Provider's opaque handle for the device and retaining the TAPI
|
|||
|
DLL's opaque handle for the device for use in subsequent calls to the
|
|||
|
LINEEVENT procedure.
|
|||
|
|
|||
|
Opening a line entitles the TAPI DLL to make further requests on the line.
|
|||
|
The line becomes "active" in the sense that the TAPI DLL can initiate
|
|||
|
outbound calls and the Service Provider can report inbound calls. The
|
|||
|
Service Provider reserves whatever non-sharable resources are required to
|
|||
|
manage the line. For example, opening a line accessed through a comm port
|
|||
|
and modem should result in opening the comm port, making it no longer
|
|||
|
available for use by other applications.
|
|||
|
|
|||
|
If the function is successful, both the TAPI DLL and the Service Provider
|
|||
|
become committed to operating under the specified interface version number
|
|||
|
for this open device. Subsquent operations and events identified using
|
|||
|
the exchanged opaque line handles conform to that interface version. This
|
|||
|
commitment and the validity of the handles remain in effect until the TAPI
|
|||
|
DLL closes the line using the TSPI_lineClose operation or the Service
|
|||
|
Provider reports the LINE_CLOSE event. If the function is not successful,
|
|||
|
no such commitment is made and the handles are not valid.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
dwDeviceID - Identifies the line device to be opened. The value
|
|||
|
LINE_MAPPER for a device ID is not permitted.
|
|||
|
|
|||
|
htLine - Specifies the TAPI DLL's opaque handle for the line device to be
|
|||
|
used in subsequent calls to the LINEEVENT callback procedure to
|
|||
|
identify the device.
|
|||
|
|
|||
|
phdLine - A far pointer to a HDRVLINE where the Service Provider fills in
|
|||
|
its opaque handle for the line device to be used by the TAPI DLL in
|
|||
|
subsequent calls to identify the device.
|
|||
|
|
|||
|
dwTSPIVersion - The TSPI version negotiated through
|
|||
|
TSPI_lineNegotiateTSPIVersion under which the Service Provider is
|
|||
|
willing to operate.
|
|||
|
|
|||
|
pfnEventProc - A far pointer to the LINEEVENT callback procedure supplied
|
|||
|
by the TAPI DLL that the Service Provider will call to report
|
|||
|
subsequent events on the line.
|
|||
|
|
|||
|
Return Values:
|
|||
|
|
|||
|
Returns zero if the function is successful, or a negative error number
|
|||
|
if an error has occurred. Possible return values are as follows:
|
|||
|
|
|||
|
LINEERR_BADDEVICEID - The specified line device ID is out of range.
|
|||
|
|
|||
|
LINEERR_INCOMPATIBLEAPIVERSION - The passed TSPI version or version
|
|||
|
range did not match an interface version definition supported by
|
|||
|
the service provider.
|
|||
|
|
|||
|
LINEERR_INUSE - The line device is in use and cannot currently be
|
|||
|
configured, allow a party to be added, allow a call to be
|
|||
|
answered, or allow a call to be placed.
|
|||
|
|
|||
|
LINEERR_OPERATIONFAILED - The operation failed for an unspecified or
|
|||
|
unknown reason.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
PH323_LINE pLine = NULL;
|
|||
|
|
|||
|
// make sure this is a version we support
|
|||
|
if (!H323ValidateTSPIVersion(dwTSPIVersion)) {
|
|||
|
|
|||
|
// failure
|
|||
|
return LINEERR_INCOMPATIBLEAPIVERSION;
|
|||
|
}
|
|||
|
|
|||
|
// retrieve pointer to line device from device id
|
|||
|
if (!H323GetLineFromIDAndLock(&pLine, dwDeviceID)) {
|
|||
|
|
|||
|
// do not recognize device
|
|||
|
return LINEERR_BADDEVICEID;
|
|||
|
}
|
|||
|
|
|||
|
// see if line device is closed
|
|||
|
if (!H323IsLineClosed(pLine) &&
|
|||
|
!pLine->fIsMarkedForDeletion) {
|
|||
|
|
|||
|
// see if line device is open
|
|||
|
if (H323IsLineOpen(pLine)) {
|
|||
|
|
|||
|
H323DBG((
|
|||
|
DEBUG_LEVEL_ERROR,
|
|||
|
"line %d already opened.\n",
|
|||
|
pLine->dwDeviceID
|
|||
|
));
|
|||
|
|
|||
|
// release line device
|
|||
|
H323UnlockLine(pLine);
|
|||
|
|
|||
|
// line already in use
|
|||
|
return LINEERR_INUSE;
|
|||
|
}
|
|||
|
|
|||
|
// release line device
|
|||
|
H323UnlockLine(pLine);
|
|||
|
|
|||
|
// line not intialized
|
|||
|
return LINEERR_INVALLINESTATE;
|
|||
|
}
|
|||
|
|
|||
|
// attempt to open line device
|
|||
|
if (!H323OpenLine(pLine, htLine, dwTSPIVersion)) {
|
|||
|
|
|||
|
// release line device
|
|||
|
H323UnlockLine(pLine);
|
|||
|
|
|||
|
// could not open line device
|
|||
|
return LINEERR_OPERATIONFAILED;
|
|||
|
}
|
|||
|
|
|||
|
// retrurn line handle
|
|||
|
*phdLine = pLine->hdLine;
|
|||
|
|
|||
|
// release line device
|
|||
|
H323UnlockLine(pLine);
|
|||
|
|
|||
|
// success
|
|||
|
return NOERROR;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
LONG
|
|||
|
TSPIAPI
|
|||
|
TSPI_lineCreateMSPInstance(
|
|||
|
HDRVLINE hdLine,
|
|||
|
DWORD dwAddressID,
|
|||
|
HTAPIMSPLINE htMSPLine,
|
|||
|
LPHDRVMSPLINE phdMSPLine
|
|||
|
)
|
|||
|
{
|
|||
|
PH323_LINE pLine = NULL;
|
|||
|
|
|||
|
// retrieve line pointer from handle
|
|||
|
if (!H323GetLineAndLock(&pLine, hdLine)) {
|
|||
|
|
|||
|
// invalid line handle
|
|||
|
return LINEERR_INVALLINEHANDLE;
|
|||
|
}
|
|||
|
// We are not keeping the msp handles. Just fake a handle here.
|
|||
|
*phdMSPLine = (HDRVMSPLINE)pLine->dwNextMSPHandle++;
|
|||
|
|
|||
|
// release line device
|
|||
|
H323UnlockLine(pLine);
|
|||
|
|
|||
|
// success
|
|||
|
return NOERROR;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
LONG
|
|||
|
TSPIAPI
|
|||
|
TSPI_lineCloseMSPInstance(
|
|||
|
HDRVMSPLINE hdMSPLine
|
|||
|
)
|
|||
|
{
|
|||
|
// success
|
|||
|
return NOERROR;
|
|||
|
}
|