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;
|
||
}
|