mirror of https://github.com/lianthony/NT4.0
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
817 lines
21 KiB
817 lines
21 KiB
//////////////////////////////////////////////////////////////////
|
|
//
|
|
// ACDUTILS.C
|
|
//
|
|
// Some utility functions used in ACDSMPL
|
|
//
|
|
//////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
#include <windows.h>
|
|
#include "acdsmpl.h"
|
|
|
|
extern ACDGLOBALS g;
|
|
|
|
//////////////////////////////////////////////////////////////////
|
|
//
|
|
// LPVOID ACDAlloc(DWORD dwSize)
|
|
//
|
|
//////////////////////////////////////////////////////////////////
|
|
LPVOID ACDAlloc(DWORD dwSize)
|
|
{
|
|
LPVOID pBuf;
|
|
|
|
pBuf = GlobalAlloc(GPTR, dwSize);
|
|
|
|
return pBuf;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////
|
|
//
|
|
// void ACDFree(LPVOID pBuf)
|
|
//
|
|
///////////////////////////////////////////////////////////////////
|
|
void ACDFree(LPVOID pBuf)
|
|
{
|
|
if (pBuf)
|
|
GlobalFree(pBuf);
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////
|
|
//
|
|
// LPVOID ACDReAlloc()
|
|
//
|
|
///////////////////////////////////////////////////////////////////
|
|
LPVOID ACDReAlloc(LPVOID pBuf,
|
|
DWORD dwSize)
|
|
{
|
|
if (pBuf)
|
|
{
|
|
pBuf = GlobalReAlloc(pBuf,
|
|
dwSize,
|
|
GMEM_MOVEABLE);
|
|
}
|
|
|
|
return pBuf;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// BOOL InsertStruct(PGENERICSTRUCT * ppRoot,
|
|
// PGENERICSTRUCT pStruct)
|
|
//
|
|
// Adds a structure to the end of a linked list
|
|
//
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
BOOL InsertStruct(PGENERICSTRUCT * ppRoot,
|
|
PGENERICSTRUCT pStruct)
|
|
{
|
|
PGENERICSTRUCT pHold = NULL;
|
|
|
|
if (!*ppRoot)
|
|
{
|
|
*ppRoot = pStruct;
|
|
}
|
|
else
|
|
{
|
|
pHold = *ppRoot;
|
|
}
|
|
|
|
if (pHold)
|
|
{
|
|
while (pHold->pNext)
|
|
{
|
|
pHold = pHold->pNext;
|
|
}
|
|
|
|
pHold->pNext = pStruct;
|
|
pStruct->pPrev = pHold;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////
|
|
//
|
|
// BOOL DeleteStruct
|
|
// Delete structure
|
|
//
|
|
// Delete a structure from a linked list and
|
|
// frees memory associated with it.
|
|
//
|
|
//////////////////////////////////////////////////////////////
|
|
BOOL DeleteStruct(PGENERICSTRUCT * ppRoot,
|
|
PGENERICSTRUCT pStruct)
|
|
{
|
|
if (pStruct->pPrev)
|
|
{
|
|
pStruct->pPrev->pNext = pStruct->pNext;
|
|
}
|
|
else
|
|
{
|
|
*ppRoot = pStruct->pNext;
|
|
}
|
|
|
|
if (pStruct->pNext)
|
|
{
|
|
pStruct->pNext->pPrev = pStruct->pPrev;
|
|
}
|
|
|
|
ACDFree(pStruct);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
//////////////////////////////////////////////////////////////
|
|
//
|
|
// PGROUP AddGroup
|
|
//
|
|
// Adds a group to the global group list
|
|
//
|
|
//////////////////////////////////////////////////////////////
|
|
PGROUP AddGroup(LPTSTR lpszName,
|
|
DWORD dwDeviceID,
|
|
DWORD dwAddress)
|
|
{
|
|
PGROUP pGroup, pHold = NULL;
|
|
LONG lResult;
|
|
|
|
// alloc memory
|
|
pGroup = (PGROUP)ACDAlloc(sizeof(GROUP));
|
|
|
|
if (!pGroup)
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
pGroup->lpszName = (LPTSTR)ACDAlloc((lstrlen(lpszName) + 1) * sizeof(TCHAR));
|
|
|
|
// bail if there is a problem
|
|
if (!pGroup->lpszName)
|
|
{
|
|
ACDFree(pGroup);
|
|
return NULL;
|
|
}
|
|
|
|
// init stuff
|
|
lstrcpy(pGroup->lpszName, lpszName);
|
|
|
|
pGroup->dwKey = GROUPKEY;
|
|
pGroup->dwSize = sizeof(GROUP);
|
|
pGroup->dwDeviceID = dwDeviceID;
|
|
|
|
|
|
// open the line in owner mode, so we can
|
|
// get the incoming calls
|
|
lResult = lineOpen(g.hLineApp,
|
|
dwDeviceID,
|
|
&pGroup->hLine,
|
|
TAPI_CURRENT_VERSION,
|
|
0,
|
|
0,
|
|
LINECALLPRIVILEGE_OWNER,
|
|
LINEMEDIAMODE_INTERACTIVEVOICE,
|
|
NULL);
|
|
|
|
if (lResult < 0)
|
|
{
|
|
// LogTapiError(lResult, "lineOpen line %lu", dwDeviceID);
|
|
ACDFree(pGroup->lpszName);
|
|
ACDFree(pGroup);
|
|
|
|
return NULL;
|
|
}
|
|
|
|
// insert into global list
|
|
InsertStruct((PGENERICSTRUCT *)&g.pGroups,
|
|
(PGENERICSTRUCT)pGroup);
|
|
|
|
// increment
|
|
g.dwNumGroups++;
|
|
|
|
return pGroup;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////
|
|
//
|
|
// PAGENT AddAgent
|
|
//
|
|
// Adds an agent to the global agent list
|
|
//
|
|
// NOTE: There is a ton of verification type stuff that can
|
|
// be put in here for a real implementation. For example,
|
|
// might want to restrict a user to a single line, or restrict
|
|
// a single line to have one person.
|
|
//
|
|
//////////////////////////////////////////////////////////////
|
|
PAGENT AddAgent(LPTSTR lpszName,
|
|
LPTSTR lpszNumber,
|
|
DWORD dwDeviceID)
|
|
{
|
|
PAGENT pAgent, pHold = NULL;
|
|
LPLINEDEVCAPS pLDC;
|
|
LPLINECALLPARAMS pLCP;
|
|
LONG lResult;
|
|
LPDWORD pdwProxyRequests;
|
|
|
|
// alloc memory
|
|
pAgent = (PAGENT)ACDAlloc(sizeof(AGENT));
|
|
|
|
if (!pAgent)
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
pAgent->lpszName = (LPTSTR)ACDAlloc((lstrlen(lpszName) + 1) * sizeof(TCHAR));
|
|
pAgent->lpszNumber = (LPTSTR)ACDAlloc((lstrlen(lpszNumber) + 1) * sizeof(TCHAR));
|
|
|
|
// bail if there is a problem
|
|
if (!pAgent->lpszName || !pAgent->lpszNumber)
|
|
{
|
|
ACDFree(pAgent);
|
|
return NULL;
|
|
}
|
|
|
|
|
|
// init stuff
|
|
lstrcpy(pAgent->lpszName, lpszName);
|
|
lstrcpy(pAgent->lpszNumber, lpszNumber);
|
|
|
|
pAgent->dwKey = AGENTKEY;
|
|
pAgent->dwSize = sizeof(AGENT);
|
|
pAgent->dwDeviceID = dwDeviceID;
|
|
pAgent->dwPermID = g.pdwPermIDs[dwDeviceID];
|
|
|
|
// insert into global agent list
|
|
InsertStruct((PGENERICSTRUCT *)&g.pAgents,
|
|
(PGENERICSTRUCT)pAgent);
|
|
|
|
// lineOpen is where the application lets TAPI know that it is a Proxy Request handler
|
|
// for this line. The LINEOPENOPTION_PROXY is added to the privileges. Also,
|
|
// the dev specific portion of LINECALLPARAMS contains the proxy request constants
|
|
// that indicate which requests this app can handle
|
|
|
|
// This sample handles 7 types of proxy requests - all the ones that are defined
|
|
// except for AGENTSPECIFIC
|
|
pLCP = (LPLINECALLPARAMS)ACDAlloc(sizeof(LINECALLPARAMS) + 7*sizeof(DWORD));
|
|
|
|
pLCP->dwTotalSize = sizeof(LINECALLPARAMS) + 7*sizeof(DWORD);
|
|
pLCP->dwDevSpecificOffset = sizeof(LINECALLPARAMS);
|
|
pLCP->dwDevSpecificSize = sizeof(DWORD) * 7;
|
|
|
|
pdwProxyRequests = (LPDWORD)((LPBYTE)pLCP + sizeof(LINECALLPARAMS));
|
|
// each constant is in a DWORD at the end of LINECALLPARAMS
|
|
*pdwProxyRequests++ = LINEPROXYREQUEST_SETAGENTGROUP;
|
|
*pdwProxyRequests++ = LINEPROXYREQUEST_SETAGENTSTATE;
|
|
*pdwProxyRequests++ = LINEPROXYREQUEST_SETAGENTACTIVITY;
|
|
*pdwProxyRequests++ = LINEPROXYREQUEST_GETAGENTSTATUS;
|
|
*pdwProxyRequests++ = LINEPROXYREQUEST_GETAGENTCAPS;
|
|
*pdwProxyRequests++ = LINEPROXYREQUEST_GETAGENTACTIVITYLIST;
|
|
*pdwProxyRequests = LINEPROXYREQUEST_GETAGENTGROUPLIST;
|
|
|
|
lResult = lineOpen(g.hLineApp,
|
|
dwDeviceID,
|
|
&pAgent->hLine,
|
|
TAPI_CURRENT_VERSION,
|
|
0,
|
|
0,
|
|
LINEOPENOPTION_PROXY | LINECALLPRIVILEGE_MONITOR,
|
|
LINEMEDIAMODE_INTERACTIVEVOICE,
|
|
pLCP);
|
|
|
|
ACDFree(pLCP);
|
|
|
|
if (lResult)
|
|
{
|
|
//
|
|
ACDFree(pAgent->lpszName);
|
|
ACDFree(pAgent);
|
|
|
|
}
|
|
|
|
pLDC = LineGetDevCaps(g.hLineApp,
|
|
pAgent->dwDeviceID);
|
|
|
|
if (!pLDC)
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
// alloc memory for address specific info
|
|
pAgent->pAddressInfo = (PADDRESSINFO)ACDAlloc(sizeof(ADDRESSINFO) * pLDC->dwNumAddresses);
|
|
pAgent->dwNumAddresses = pLDC->dwNumAddresses;
|
|
|
|
ACDFree(pLDC);
|
|
|
|
// increment number of agents
|
|
g.dwNumAgents++;
|
|
|
|
return pAgent;
|
|
}
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// BOOL DeleteAgent(PAGENT pAgent)
|
|
//
|
|
// Frees all memory associated with pAgent, removes
|
|
// agent from group lists, and remove pAgent from
|
|
// global agent list
|
|
//
|
|
//////////////////////////////////////////////////////////////////////////
|
|
BOOL DeleteAgent(PAGENT pAgent)
|
|
{
|
|
PGROUP pGroup;
|
|
|
|
|
|
lineClose(pAgent->hLine);
|
|
|
|
// free name
|
|
ACDFree(pAgent->lpszName);
|
|
ACDFree(pAgent->lpszNumber);
|
|
|
|
// free address info
|
|
ACDFree(pAgent->pAddressInfo);
|
|
|
|
pGroup = g.pGroups;
|
|
|
|
// walk through groups and remove from
|
|
// group list if in group list
|
|
while (pGroup)
|
|
{
|
|
if (IsAgentInList(pGroup->pAgentList,
|
|
pAgent))
|
|
{
|
|
RemoveFromGroupList(pGroup,
|
|
pAgent);
|
|
}
|
|
|
|
pGroup = pGroup->pNext;
|
|
|
|
}
|
|
|
|
// finally, remove pAgent from global list
|
|
DeleteStruct((PGENERICSTRUCT *)&g.pAgents,
|
|
(PGENERICSTRUCT)pAgent);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// BOOL DeleteGroup(PGROUP pGroup)
|
|
//
|
|
// Frees memory assocated with pGroup, and removes the structure from
|
|
// the global list
|
|
//
|
|
//////////////////////////////////////////////////////////////////////////
|
|
BOOL DeleteGroup(PGROUP pGroup)
|
|
{
|
|
PLISTITEM pList, pListNext;
|
|
|
|
lineClose(pGroup->hLine);
|
|
|
|
ACDFree(pGroup->lpszName);
|
|
|
|
pList = pGroup->pAgentList;
|
|
|
|
while (pList)
|
|
{
|
|
pListNext = pList->pNext;
|
|
ACDFree(pList);
|
|
pList = pListNext;
|
|
}
|
|
|
|
DeleteStruct((PGENERICSTRUCT *)&g.pGroups,
|
|
(PGENERICSTRUCT)pGroup);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// BOOL InsertIntoGroupList(PGROUP pGroup,
|
|
// PAGENT pAgent)
|
|
//
|
|
// Insert an agent in a group
|
|
//
|
|
//////////////////////////////////////////////////////////////////////////
|
|
BOOL InsertIntoGroupList(PGROUP pGroup,
|
|
PAGENT pAgent)
|
|
{
|
|
PLISTITEM pListItem;
|
|
|
|
pListItem = (PLISTITEM)ACDAlloc(sizeof(LISTITEM));
|
|
|
|
pListItem->dwKey = LISTKEY;
|
|
pListItem->dwSize = sizeof(LISTITEM);
|
|
pListItem->pAgent = pAgent;
|
|
|
|
InsertStruct((PGENERICSTRUCT *)&pGroup->pAgentList,
|
|
(PGENERICSTRUCT)pListItem);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// BOOL RemoveFromGroupList(PGROUP pGroup,
|
|
//
|
|
// remove an agent from a group's list
|
|
//
|
|
//////////////////////////////////////////////////////////////////////////
|
|
BOOL RemoveFromGroupList(PGROUP pGroup,
|
|
PAGENT pAgent)
|
|
{
|
|
PLISTITEM pList;
|
|
|
|
pList = pGroup->pAgentList;
|
|
|
|
while (pList)
|
|
{
|
|
if (pList->pAgent == pAgent)
|
|
{
|
|
break;
|
|
}
|
|
|
|
pList = pList->pNext;
|
|
}
|
|
|
|
if (!pList)
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
DeleteStruct((PGENERICSTRUCT *)&pGroup->pAgentList,
|
|
(PGENERICSTRUCT)pList);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
//PLISTITEM IsAgentInList(PLISTITEM pList,
|
|
// PAGENT pAgent)
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
PLISTITEM IsAgentInList(PLISTITEM pList,
|
|
PAGENT pAgent)
|
|
{
|
|
while (pList)
|
|
{
|
|
if (pList->pAgent == pAgent)
|
|
{
|
|
return pList;
|
|
}
|
|
|
|
pList = pList->pNext;
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// PAGENT GetAgentFromName(LPTSTR lpszName)
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
PAGENT GetAgentFromName(LPTSTR lpszName)
|
|
{
|
|
PAGENT pHold;
|
|
|
|
pHold = g.pAgents;
|
|
|
|
while (pHold)
|
|
{
|
|
if (!lstrcmpi(pHold->lpszName,
|
|
lpszName))
|
|
{
|
|
return pHold;
|
|
}
|
|
|
|
pHold = pHold->pNext;
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// PAGENT GetAgentFromhLine(HLINE hLine)
|
|
//
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
PAGENT GetAgentFromhLine(HLINE hLine)
|
|
{
|
|
PAGENT pAgent;
|
|
|
|
pAgent = g.pAgents;
|
|
|
|
while (pAgent)
|
|
{
|
|
if (pAgent->hLine == hLine)
|
|
{
|
|
return pAgent;
|
|
}
|
|
|
|
pAgent = pAgent->pNext;
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// DWORD GetDeviceID(DWORD dwPermID)
|
|
//
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
DWORD GetDeviceID(DWORD dwPermID)
|
|
{
|
|
DWORD dwCount;
|
|
|
|
for (dwCount = 0; dwCount < g.dwNumDevs; dwCount++)
|
|
{
|
|
if (g.pdwPermIDs[dwCount] == dwPermID)
|
|
{
|
|
return dwCount;
|
|
}
|
|
}
|
|
|
|
return (DWORD)-1;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// **************TAPI WRAPPER FUNCTIONS**************
|
|
//
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// LineGetAddressCaps()
|
|
//
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
LINEADDRESSCAPS * LineGetAddressCaps (HLINEAPP hLineApp,
|
|
DWORD dwDeviceID,
|
|
DWORD dwAddressID)
|
|
{
|
|
LONG lRetVal;
|
|
LINEADDRESSCAPS * pLineAddressCaps;
|
|
static DWORD dwMaxNeededSize = sizeof(LINEADDRESSCAPS);
|
|
|
|
// Allocate an initial block of memory for the LINEADDRESSCAPS structure,
|
|
// which may or may not be big enough to hold all of the information.
|
|
//
|
|
pLineAddressCaps = ACDAlloc(dwMaxNeededSize);
|
|
|
|
for (;;)
|
|
{
|
|
if (pLineAddressCaps == NULL)
|
|
{
|
|
return NULL;
|
|
}
|
|
pLineAddressCaps->dwTotalSize = dwMaxNeededSize;
|
|
|
|
// Try (or retry) to get the LINEADDRESSCAPS information
|
|
//
|
|
lRetVal = lineGetAddressCaps(hLineApp,
|
|
dwDeviceID,
|
|
dwAddressID,
|
|
TAPI_CURRENT_VERSION,
|
|
0,
|
|
pLineAddressCaps);
|
|
if (lRetVal < 0)
|
|
{
|
|
ACDFree((HLOCAL)pLineAddressCaps);
|
|
return NULL;
|
|
}
|
|
|
|
// If the currently allocated LINEADDRESSCAPS memory block was big
|
|
// enough, we're all done, else we need to realloc the memory block
|
|
// and try again.
|
|
//
|
|
if (pLineAddressCaps->dwNeededSize <= dwMaxNeededSize)
|
|
{
|
|
return pLineAddressCaps;
|
|
}
|
|
else
|
|
{
|
|
dwMaxNeededSize = pLineAddressCaps->dwNeededSize;
|
|
pLineAddressCaps = ACDReAlloc((HLOCAL)pLineAddressCaps,
|
|
dwMaxNeededSize);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// LineGetCallInfo()
|
|
//
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
LINECALLINFO * LineGetCallInfo (HCALL hCall)
|
|
{
|
|
LONG lRetVal;
|
|
LINECALLINFO * pLineCallInfo;
|
|
static DWORD dwMaxNeededSize = sizeof(LINECALLINFO);
|
|
|
|
// Allocate an initial block of memory for the LINECALLINFO structure,
|
|
// which may or may not be big enough to hold all of the information.
|
|
//
|
|
pLineCallInfo = ACDAlloc(dwMaxNeededSize);
|
|
|
|
for (;;)
|
|
{
|
|
if (pLineCallInfo == NULL)
|
|
{
|
|
return NULL;
|
|
}
|
|
pLineCallInfo->dwTotalSize = dwMaxNeededSize;
|
|
|
|
// Try (or retry) to get the LINECALLINFO information
|
|
//
|
|
lRetVal = lineGetCallInfo(hCall,
|
|
pLineCallInfo);
|
|
if (lRetVal < 0)
|
|
{
|
|
ACDFree((HLOCAL)pLineCallInfo);
|
|
return NULL;
|
|
}
|
|
|
|
// If the currently allocated LINECALLINFO memory block was big
|
|
// enough, we're all done, else we need to realloc the memory block
|
|
// and try again.
|
|
//
|
|
if (pLineCallInfo->dwNeededSize <= dwMaxNeededSize)
|
|
{
|
|
return pLineCallInfo;
|
|
}
|
|
else
|
|
{
|
|
dwMaxNeededSize = pLineCallInfo->dwNeededSize;
|
|
pLineCallInfo = ACDReAlloc((HLOCAL)pLineCallInfo,
|
|
dwMaxNeededSize);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// LineGetDevCaps()
|
|
//
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
LINEDEVCAPS * LineGetDevCaps (HLINEAPP hLineApp,
|
|
DWORD dwDeviceID)
|
|
{
|
|
LONG lRetVal;
|
|
LINEDEVCAPS * pLineDevCaps;
|
|
static DWORD dwMaxNeededSize = sizeof(LINEDEVCAPS);
|
|
|
|
pLineDevCaps = ACDAlloc(dwMaxNeededSize);
|
|
for (;;)
|
|
{
|
|
if (pLineDevCaps == NULL)
|
|
{
|
|
return NULL;
|
|
}
|
|
pLineDevCaps->dwTotalSize = dwMaxNeededSize;
|
|
lRetVal = lineGetDevCaps(hLineApp,
|
|
dwDeviceID,
|
|
TAPI_CURRENT_VERSION,
|
|
0,
|
|
pLineDevCaps);
|
|
if (lRetVal < 0)
|
|
{
|
|
ACDFree((HLOCAL)pLineDevCaps);
|
|
return NULL;
|
|
}
|
|
if (pLineDevCaps->dwNeededSize <= dwMaxNeededSize)
|
|
{
|
|
return pLineDevCaps;
|
|
}
|
|
else
|
|
{
|
|
dwMaxNeededSize = pLineDevCaps->dwNeededSize;
|
|
pLineDevCaps = ACDReAlloc((HLOCAL)pLineDevCaps,
|
|
dwMaxNeededSize);
|
|
}
|
|
}
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// LineGetID()
|
|
//
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
VARSTRING * LineGetID (HLINE hLine,
|
|
DWORD dwAddressID,
|
|
HCALL hCall,
|
|
DWORD dwSelect,
|
|
LPCTSTR lpszDeviceClass)
|
|
{
|
|
LONG lRetVal;
|
|
VARSTRING * pVarString;
|
|
static DWORD dwMaxNeededSize = sizeof(VARSTRING);
|
|
|
|
// Allocate an initial block of memory for the VARSTRING structure,
|
|
// which may or may not be big enough to hold all of the information.
|
|
//
|
|
pVarString = ACDAlloc(dwMaxNeededSize);
|
|
|
|
for (;;)
|
|
{
|
|
if (pVarString == NULL)
|
|
{
|
|
return NULL;
|
|
}
|
|
pVarString->dwTotalSize = dwMaxNeededSize;
|
|
|
|
// Try (or retry) to get the VARSTRING information
|
|
//
|
|
lRetVal = lineGetID(hLine,
|
|
dwAddressID,
|
|
hCall,
|
|
dwSelect,
|
|
pVarString,
|
|
lpszDeviceClass);
|
|
if (lRetVal < 0)
|
|
{
|
|
ACDFree(pVarString);
|
|
return NULL;
|
|
}
|
|
|
|
// If the currently allocated VARSTRING memory block was big
|
|
// enough, we're all done, else we need to realloc the memory block
|
|
// and try again.
|
|
//
|
|
if (pVarString->dwNeededSize <= dwMaxNeededSize)
|
|
{
|
|
return pVarString;
|
|
}
|
|
else
|
|
{
|
|
dwMaxNeededSize = pVarString->dwNeededSize;
|
|
pVarString = ACDReAlloc((HLOCAL)pVarString,
|
|
dwMaxNeededSize);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// LineGetCallStatus()
|
|
//
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
LINECALLSTATUS * LineGetCallStatus (HCALL hCall)
|
|
{
|
|
LONG lRetVal;
|
|
LINECALLSTATUS * pLineCallStatus;
|
|
static DWORD dwMaxNeededSize = sizeof(LINECALLSTATUS);
|
|
|
|
// Allocate an initial block of memory for the LINECALLSTATUS structure,
|
|
// which may or may not be big enough to hold all of the information.
|
|
//
|
|
pLineCallStatus = ACDAlloc(dwMaxNeededSize);
|
|
|
|
while (TRUE)
|
|
{
|
|
if (pLineCallStatus == NULL)
|
|
{
|
|
return NULL;
|
|
}
|
|
pLineCallStatus->dwTotalSize = dwMaxNeededSize;
|
|
|
|
// Try (or retry) to get the LINECALLSTATUS information
|
|
//
|
|
lRetVal = lineGetCallStatus(hCall,
|
|
pLineCallStatus);
|
|
if (lRetVal < 0)
|
|
{
|
|
ACDFree((HLOCAL)pLineCallStatus);
|
|
return NULL;
|
|
}
|
|
|
|
// If the currently allocated LINECALLSTATUS memory block was big
|
|
// enough, we're all done, else we need to realloc the memory block
|
|
// and try again.
|
|
//
|
|
if (pLineCallStatus->dwNeededSize <= dwMaxNeededSize)
|
|
{
|
|
return pLineCallStatus;
|
|
}
|
|
else
|
|
{
|
|
dwMaxNeededSize = pLineCallStatus->dwNeededSize;
|
|
pLineCallStatus = ACDReAlloc((HLOCAL)pLineCallStatus,
|
|
dwMaxNeededSize);
|
|
}
|
|
}
|
|
}
|
|
|