1357 lines
40 KiB
C
1357 lines
40 KiB
C
|
/*==========================================================================
|
||
|
*
|
||
|
* Copyright (C) 1996-1997 Microsoft Corporation. All Rights Reserved.
|
||
|
*
|
||
|
* File: dial.c
|
||
|
* Content: Wrappers for TAPI routines
|
||
|
*@@BEGIN_MSINTERNAL
|
||
|
* History:
|
||
|
* Date By Reason
|
||
|
* ==== == ======
|
||
|
* 6/10/96 kipo created it
|
||
|
* 6/22/96 kipo close com port when disconnected; allow checking for
|
||
|
* valid TAPI lines during NewComPort().
|
||
|
* 7/08/96 kipo added support for new dialogs
|
||
|
* 8/10/96 kipo added support for dialing location
|
||
|
* 1/06/97 kipo updated for objects
|
||
|
* 1/24/97 kipo bug #5400: Compaq Presario was overwriting the dev caps
|
||
|
* buffer, causing a crash. Fixed to allocated a larger
|
||
|
* buffer with some slop as a workaround.
|
||
|
* 3/04/97 kipo close com port handle when deallocating call; use string
|
||
|
* table for modem strings; updated debug output.
|
||
|
* 3/24/97 kipo added support for specifying which modem to use
|
||
|
* 4/08/97 kipo added support for separate modem and serial baud rates
|
||
|
* 5/07/97 kipo added support for modem choice list
|
||
|
* 5/23/97 kipo added support return status codes
|
||
|
* 4/21/98 a-peterz #22920 Handle LINE_CLOSE message
|
||
|
* 5/07/98 a-peterz #15251 Track call errors in DPDIAL
|
||
|
* 10/13/99 johnkan #413516 - Mismatch between modem dialog selection and TAPI device ID
|
||
|
*@@END_MSINTERNAL
|
||
|
***************************************************************************/
|
||
|
|
||
|
#include <windows.h>
|
||
|
#include <windowsx.h>
|
||
|
|
||
|
#include "dputils.h"
|
||
|
#include "macros.h"
|
||
|
#include "dial.h"
|
||
|
|
||
|
void FAR PASCAL LineCallBackProc(DWORD hDevice, DWORD dwMessage, DWORD_PTR dwInstance,
|
||
|
DWORD_PTR dwParam1, DWORD_PTR dwParam2, DWORD_PTR dwParam3);
|
||
|
void ProcessConnectedState(LPDPDIAL globals, HCALL hCall, DWORD dwCallStateDetail, DWORD dwCallPrivilege);
|
||
|
void ProcessDisconnectedState(LPDPDIAL globals, HCALL hCall, DWORD dwCallStateDetail, DWORD dwCallPrivilege);
|
||
|
void ProcessIdleState(LPDPDIAL globals, HCALL hCall, DWORD dwCallStateDetail, DWORD dwCallPrivilege);
|
||
|
void ProcessOfferingState(LPDPDIAL globals, HCALL hCall, DWORD dwCallPrivilege);
|
||
|
void ProcessReplyMessage(LPDPDIAL globals, DWORD asyncID, LINERESULT lResult);
|
||
|
LINERESULT dialGetDevCaps(LPDPDIAL globals, DWORD dwLine, DWORD dwAPIVersion, LPLINEDEVCAPS *lpDevCapsRet);
|
||
|
LINERESULT dialGetCommHandle(LPDPDIAL globals);
|
||
|
LINERESULT dialCloseCommHandle(LPDPDIAL globals);
|
||
|
LINERESULT dialTranslateAddress(LPDPDIAL globals, DWORD dwDeviceID, DWORD dwAPIVersion,
|
||
|
LPCSTR lpszDialAddress,
|
||
|
LPLINETRANSLATEOUTPUT *lpLineTranslateOutputRet);
|
||
|
LPSTR GetLineErrStr(LONG err);
|
||
|
LPSTR GetCallStateStr(DWORD callState);
|
||
|
LPSTR GetLineMsgStr(DWORD msg);
|
||
|
|
||
|
#ifdef DEBUG
|
||
|
extern LONG lineError(LONG err, LPSTR modName, DWORD lineNum);
|
||
|
#define LINEERROR(err) (lineError(err, DPF_MODNAME, __LINE__))
|
||
|
#else
|
||
|
#define LINEERROR(err) (err)
|
||
|
#endif
|
||
|
|
||
|
/* dial initialize */
|
||
|
|
||
|
#undef DPF_MODNAME
|
||
|
#define DPF_MODNAME "dialInitialize"
|
||
|
|
||
|
LINERESULT dialInitialize(HINSTANCE hInst, LPTSTR szAppName,
|
||
|
LPDPCOMPORT lpComPort, LPDPDIAL *storage)
|
||
|
{
|
||
|
LPDPDIAL globals;
|
||
|
LINERESULT lResult; /* Stores return code from TAPI calls */
|
||
|
|
||
|
// create globals
|
||
|
globals =(LPDPDIAL) GlobalAllocPtr(GHND, sizeof(DPDIAL));
|
||
|
FAILWITHACTION(globals == NULL, lResult = LINEERR_NOMEM, Failure);
|
||
|
|
||
|
DPF(3, "lineInitialize");
|
||
|
DPF(3, "> hInstance: %08X", hInst);
|
||
|
DPF(3, "> szAppName: %s", szAppName);
|
||
|
|
||
|
// init the line
|
||
|
lResult = lineInitialize(&globals->hLineApp,
|
||
|
hInst,
|
||
|
LineCallBackProc,
|
||
|
szAppName,
|
||
|
&globals->dwNumLines);
|
||
|
FAILIF(LINEERROR(lResult), Failure);
|
||
|
|
||
|
DPF(3, "< hLineApp: %08X", globals->hLineApp);
|
||
|
DPF(3, "< dwNumLines: %d", globals->dwNumLines);
|
||
|
|
||
|
// no lines available
|
||
|
FAILWITHACTION(globals->dwNumLines == 0, lResult = LINEERR_NODEVICE, Failure);
|
||
|
|
||
|
// store pointer to com port object
|
||
|
globals->lpComPort = lpComPort;
|
||
|
|
||
|
*storage = globals;
|
||
|
return (SUCCESS);
|
||
|
|
||
|
Failure:
|
||
|
dialShutdown(globals);
|
||
|
|
||
|
return (lResult);
|
||
|
}
|
||
|
|
||
|
/* dial shutdown */
|
||
|
|
||
|
#undef DPF_MODNAME
|
||
|
#define DPF_MODNAME "dialShutdown"
|
||
|
|
||
|
LINERESULT dialShutdown(LPDPDIAL globals)
|
||
|
{
|
||
|
LINERESULT lResult;
|
||
|
|
||
|
if (globals == NULL)
|
||
|
return (SUCCESS);
|
||
|
|
||
|
if (globals->hLineApp)
|
||
|
{
|
||
|
dialDropCall(globals);
|
||
|
dialDeallocCall(globals);
|
||
|
dialLineClose(globals);
|
||
|
|
||
|
DPF(3, "lineShutdown");
|
||
|
DPF(3, "> hLineApp: %08X", globals->hLineApp);
|
||
|
|
||
|
lResult = lineShutdown(globals->hLineApp);
|
||
|
LINEERROR(lResult);
|
||
|
}
|
||
|
|
||
|
GlobalFreePtr(globals);
|
||
|
|
||
|
return (SUCCESS);
|
||
|
}
|
||
|
|
||
|
/* dialLineOpen - wrapper for lineOpen */
|
||
|
|
||
|
#undef DPF_MODNAME
|
||
|
#define DPF_MODNAME "dialLineOpen"
|
||
|
|
||
|
LINERESULT dialLineOpen(LPDPDIAL globals, DWORD dwLine)
|
||
|
{
|
||
|
LINEEXTENSIONID lineExtensionID; // Will be set to 0 to indicate no known extensions
|
||
|
LPLINEDEVCAPS lpLineDevCaps = NULL;
|
||
|
LINERESULT lResult;
|
||
|
|
||
|
// fail if line is already open
|
||
|
FAILWITHACTION(globals->hLine != 0, lResult = LINEERR_INVALLINEHANDLE, Failure);
|
||
|
|
||
|
/* negotiate API version for each line */
|
||
|
lResult = lineNegotiateAPIVersion(globals->hLineApp, dwLine,
|
||
|
TAPIVERSION, TAPIVERSION,
|
||
|
&globals->dwAPIVersion, &lineExtensionID);
|
||
|
FAILIF(LINEERROR(lResult), Failure);
|
||
|
|
||
|
lResult = dialGetDevCaps(globals, dwLine, globals->dwAPIVersion, &lpLineDevCaps);
|
||
|
FAILIF(LINEERROR(lResult), Failure);
|
||
|
|
||
|
/* check for supported media mode. If not datamodem, continue to next line */
|
||
|
FAILWITHACTION(!(lpLineDevCaps->dwMediaModes & LINEMEDIAMODE_DATAMODEM),
|
||
|
lResult = LINEERR_NODEVICE, Failure);
|
||
|
|
||
|
DPF(3, "lineOpen");
|
||
|
DPF(3, "> hLineApp: %08X", globals->hLineApp);
|
||
|
DPF(3, "> dwDeviceID: %d", dwLine);
|
||
|
|
||
|
// reset error tracking
|
||
|
globals->dwCallError = CALL_OK;
|
||
|
|
||
|
/* open the line that supports data modems */
|
||
|
lResult = lineOpen( globals->hLineApp, dwLine, &globals->hLine,
|
||
|
globals->dwAPIVersion, 0L,
|
||
|
(DWORD_PTR) globals,
|
||
|
LINECALLPRIVILEGE_OWNER, LINEMEDIAMODE_DATAMODEM,
|
||
|
NULL);
|
||
|
FAILIF(LINEERROR(lResult), Failure);
|
||
|
|
||
|
DPF(3, "< hLine: %08X", globals->hLine);
|
||
|
|
||
|
/* if we are here then we found a compatible line */
|
||
|
globals->dwLineID = dwLine;
|
||
|
globals->dwCallState = LINECALLSTATE_IDLE; // line is now idle and ready to make/receive calls
|
||
|
lResult = SUCCESS;
|
||
|
|
||
|
Failure:
|
||
|
if (lpLineDevCaps)
|
||
|
GlobalFreePtr(lpLineDevCaps);
|
||
|
return (lResult);
|
||
|
}
|
||
|
|
||
|
/* dialLineClose - wrapper for lineClose */
|
||
|
|
||
|
#undef DPF_MODNAME
|
||
|
#define DPF_MODNAME "dialLineClose"
|
||
|
|
||
|
LINERESULT dialLineClose(LPDPDIAL globals)
|
||
|
{
|
||
|
LINERESULT lResult;
|
||
|
|
||
|
// fail if line is already closed
|
||
|
FAILWITHACTION(globals->hLine == 0, lResult = LINEERR_INVALLINEHANDLE, Failure);
|
||
|
|
||
|
DPF(3, "lineClose");
|
||
|
DPF(3, "> hLine: %08X", globals->hLine);
|
||
|
|
||
|
lResult = lineClose(globals->hLine);
|
||
|
LINEERROR(lResult);
|
||
|
|
||
|
globals->hLine = 0;
|
||
|
|
||
|
Failure:
|
||
|
return (lResult);
|
||
|
}
|
||
|
|
||
|
/* dialMakeCall - wrapper for lineMakeCall */
|
||
|
|
||
|
#undef DPF_MODNAME
|
||
|
#define DPF_MODNAME "dialMakeCall"
|
||
|
|
||
|
LINERESULT dialMakeCall(LPDPDIAL globals, LPTSTR szDestination)
|
||
|
{
|
||
|
LINECALLPARAMS callparams;
|
||
|
LINERESULT lResult;
|
||
|
|
||
|
// fail if line not open or if call is already open
|
||
|
FAILWITHACTION(globals->hLine == 0, lResult = LINEERR_INVALLINEHANDLE, Failure);
|
||
|
FAILWITHACTION(globals->hCall != 0, lResult = LINEERR_INVALCALLHANDLE, Failure);
|
||
|
|
||
|
// set call parameters
|
||
|
ZeroMemory(&callparams, sizeof(LINECALLPARAMS));
|
||
|
callparams.dwBearerMode = LINEBEARERMODE_VOICE;
|
||
|
callparams.dwMediaMode = LINEMEDIAMODE_DATAMODEM;
|
||
|
callparams.dwTotalSize = sizeof(LINECALLPARAMS);
|
||
|
|
||
|
DPF(3, "lineMakeCall");
|
||
|
DPF(3, "> hLine: %08X", globals->hLine);
|
||
|
DPF(3, "> szDestAddr: \"%s\"", szDestination);
|
||
|
|
||
|
lResult = lineMakeCall(globals->hLine, &globals->hCall, szDestination, 0, &callparams);
|
||
|
|
||
|
// lResult will be > 0 if call is asynchronous
|
||
|
FAILWITHACTION(lResult < 0, LINEERROR(lResult), Failure);
|
||
|
FAILMSG(lResult == 0);
|
||
|
|
||
|
DPF(3, "< hCall: %08X", globals->hCall);
|
||
|
DPF(3, "< dwAsyncID: %d", lResult);
|
||
|
|
||
|
globals->dwAsyncID = lResult; // store async ID
|
||
|
lResult = SUCCESS;
|
||
|
|
||
|
Failure:
|
||
|
return (lResult);
|
||
|
}
|
||
|
|
||
|
/* dialDropCall - wrapper for lineDrop */
|
||
|
|
||
|
#undef DPF_MODNAME
|
||
|
#define DPF_MODNAME "dialDropCall"
|
||
|
|
||
|
LINERESULT dialDropCall(LPDPDIAL globals)
|
||
|
{
|
||
|
MSG msg;
|
||
|
DWORD dwStopTicks;
|
||
|
LINERESULT lResult;
|
||
|
|
||
|
// fail if line not open or if call not open
|
||
|
FAILWITHACTION(globals->hLine == 0, lResult = LINEERR_INVALLINEHANDLE, Failure);
|
||
|
FAILWITHACTION(globals->hCall == 0, lResult = LINEERR_INVALCALLHANDLE, Failure);
|
||
|
|
||
|
DPF(3, "lineDrop");
|
||
|
DPF(3, "> hCall: %08X", globals->hCall);
|
||
|
|
||
|
lResult = lineDrop(globals->hCall, NULL, 0);
|
||
|
|
||
|
// lResult will be > 0 if call is asynchronous
|
||
|
FAILWITHACTION(lResult < 0, LINEERROR(lResult), Failure);
|
||
|
FAILMSG(lResult == 0);
|
||
|
|
||
|
DPF(3, "< dwAsyncID: %d", lResult);
|
||
|
|
||
|
globals->dwAsyncID = lResult; // store async ID
|
||
|
|
||
|
// wait for call to get dropped
|
||
|
dwStopTicks = GetTickCount() + LINEDROPTIMEOUT;
|
||
|
while (GetTickCount() < dwStopTicks)
|
||
|
{
|
||
|
// see if reply has occured and we are idle
|
||
|
if ((globals->dwAsyncID == 0) &&
|
||
|
(globals->dwCallState == LINECALLSTATE_IDLE))
|
||
|
{
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
// give TAPI a chance to call our callback
|
||
|
if (PeekMessage(&msg, 0, 0, 0, PM_REMOVE))
|
||
|
{
|
||
|
TranslateMessage(&msg);
|
||
|
DispatchMessage(&msg);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
lResult = SUCCESS;
|
||
|
|
||
|
Failure:
|
||
|
return (lResult);
|
||
|
}
|
||
|
|
||
|
/* dialDeallocCall - wrapper for lineDeallocCall */
|
||
|
|
||
|
#undef DPF_MODNAME
|
||
|
#define DPF_MODNAME "dialDeallocCall"
|
||
|
|
||
|
LINERESULT dialDeallocCall(LPDPDIAL globals)
|
||
|
{
|
||
|
LINERESULT lResult;
|
||
|
|
||
|
// fail if line not open or if call not open
|
||
|
FAILWITHACTION(globals->hLine == 0, lResult = LINEERR_INVALLINEHANDLE, Failure);
|
||
|
FAILWITHACTION(globals->hCall == 0, lResult = LINEERR_INVALCALLHANDLE, Failure);
|
||
|
|
||
|
// close the com port
|
||
|
dialCloseCommHandle(globals);
|
||
|
|
||
|
DPF(3, "lineDeallocateCall");
|
||
|
DPF(3, "> hCall: %08X", globals->hCall);
|
||
|
|
||
|
lResult = lineDeallocateCall(globals->hCall);
|
||
|
LINEERROR(lResult);
|
||
|
|
||
|
globals->hCall = 0;
|
||
|
|
||
|
Failure:
|
||
|
return (lResult);
|
||
|
}
|
||
|
|
||
|
/* dialIsConnected- returns TRUE if call is connected */
|
||
|
|
||
|
#undef DPF_MODNAME
|
||
|
#define DPF_MODNAME "dialIsConnected"
|
||
|
|
||
|
BOOL dialIsConnected(LPDPDIAL globals)
|
||
|
{
|
||
|
// connected if we have a call handle and the state is connected
|
||
|
if ((globals->hCall) &&
|
||
|
(globals->dwCallState == LINECALLSTATE_CONNECTED))
|
||
|
return (TRUE);
|
||
|
else
|
||
|
return (FALSE);
|
||
|
}
|
||
|
|
||
|
/* callback function */
|
||
|
|
||
|
#undef DPF_MODNAME
|
||
|
#define DPF_MODNAME "LineCallBackProc"
|
||
|
|
||
|
void FAR PASCAL LineCallBackProc(DWORD hDevice, DWORD dwMessage, DWORD_PTR dwInstance,
|
||
|
DWORD_PTR dwParam1, DWORD_PTR dwParam2, DWORD_PTR dwParam3)
|
||
|
{
|
||
|
LPDPDIAL globals = (LPDPDIAL) dwInstance;
|
||
|
|
||
|
DPF(3, "Line message: %s", GetLineMsgStr(dwMessage));
|
||
|
|
||
|
switch (dwMessage)
|
||
|
{
|
||
|
case LINE_LINEDEVSTATE:
|
||
|
break;
|
||
|
|
||
|
case LINE_CALLSTATE:
|
||
|
|
||
|
globals->dwCallState = dwParam1;
|
||
|
|
||
|
DPF(3, " call state: %s", GetCallStateStr((DWORD)globals->dwCallState));
|
||
|
|
||
|
switch (globals->dwCallState)
|
||
|
{
|
||
|
case LINECALLSTATE_OFFERING:
|
||
|
ProcessOfferingState(globals, (HCALL) hDevice, (DWORD)dwParam3);
|
||
|
break;
|
||
|
|
||
|
case LINECALLSTATE_CONNECTED:
|
||
|
ProcessConnectedState(globals, (HCALL) hDevice, (DWORD)dwParam2, (DWORD)dwParam3);
|
||
|
break;
|
||
|
|
||
|
case LINECALLSTATE_DISCONNECTED:
|
||
|
ProcessDisconnectedState(globals, (HCALL) hDevice, (DWORD)dwParam2, (DWORD)dwParam3);
|
||
|
break;
|
||
|
|
||
|
case LINECALLSTATE_IDLE:
|
||
|
ProcessIdleState(globals, (HCALL) hDevice, (DWORD)dwParam2, (DWORD)dwParam3);
|
||
|
break;
|
||
|
|
||
|
case LINECALLSTATE_BUSY:
|
||
|
break;
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case LINE_REPLY:
|
||
|
ProcessReplyMessage(globals, (DWORD)dwParam1, (LINERESULT) dwParam2);
|
||
|
break;
|
||
|
|
||
|
/* other messages that can be processed */
|
||
|
case LINE_CLOSE:
|
||
|
// the line has shut itself down
|
||
|
globals->hLine = 0;
|
||
|
globals->dwCallError = CALL_CLOSED;
|
||
|
break;
|
||
|
case LINE_ADDRESSSTATE:
|
||
|
break;
|
||
|
case LINE_CALLINFO:
|
||
|
break;
|
||
|
case LINE_DEVSPECIFIC:
|
||
|
break;
|
||
|
case LINE_DEVSPECIFICFEATURE:
|
||
|
break;
|
||
|
case LINE_GATHERDIGITS:
|
||
|
break;
|
||
|
case LINE_GENERATE:
|
||
|
break;
|
||
|
case LINE_MONITORDIGITS:
|
||
|
break;
|
||
|
case LINE_MONITORMEDIA:
|
||
|
break;
|
||
|
case LINE_MONITORTONE:
|
||
|
break;
|
||
|
} /* switch */
|
||
|
|
||
|
} /* LineCallBackProc */
|
||
|
|
||
|
/* ProcessOfferingState - handler for LINECALLSTATE_OFFERING state */
|
||
|
|
||
|
#undef DPF_MODNAME
|
||
|
#define DPF_MODNAME "ProcessOfferingState"
|
||
|
|
||
|
void ProcessOfferingState(LPDPDIAL globals, HCALL hCall, DWORD dwCallPrivilege)
|
||
|
{
|
||
|
LINERESULT lResult;
|
||
|
|
||
|
DDASSERT(hCall);
|
||
|
DDASSERT(globals->hCall == 0);
|
||
|
DDASSERT(globals->dwAsyncID == 0);
|
||
|
|
||
|
DPF(3, " hCall: %08X", hCall);
|
||
|
DPF(3, " privilege: %08X", (DWORD)dwCallPrivilege);
|
||
|
|
||
|
// fail if we don't own the call
|
||
|
FAILIF(dwCallPrivilege != LINECALLPRIVILEGE_OWNER, Failure);
|
||
|
|
||
|
// answer the call
|
||
|
lResult = lineAnswer(hCall, NULL, 0);
|
||
|
|
||
|
// lResult will be > 0 if call is asynchronous
|
||
|
FAILWITHACTION(lResult < 0, LINEERROR(lResult), Failure);
|
||
|
FAILMSG(lResult == 0);
|
||
|
|
||
|
globals->hCall = hCall; // store call handle
|
||
|
globals->dwAsyncID = lResult; // store async ID
|
||
|
|
||
|
Failure:
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
/* ProcessConnectedState - handler for LINECALLSTATE_CONNECTED state */
|
||
|
|
||
|
#undef DPF_MODNAME
|
||
|
#define DPF_MODNAME "ProcessConnectedState"
|
||
|
|
||
|
void ProcessConnectedState(LPDPDIAL globals, HCALL hCall, DWORD dwCallStateDetail, DWORD dwCallPrivilege)
|
||
|
{
|
||
|
LINERESULT lResult;
|
||
|
HRESULT hr;
|
||
|
|
||
|
DDASSERT(hCall);
|
||
|
DDASSERT(globals->hCall);
|
||
|
DDASSERT(globals->hCall == hCall);
|
||
|
|
||
|
DPF(3, " hCall: %08X", hCall);
|
||
|
DPF(3, " privilege: %08X", dwCallPrivilege);
|
||
|
DPF(3, " detail: %08X", dwCallStateDetail);
|
||
|
|
||
|
// get the id of the COM device connected to the modem
|
||
|
// NOTE: once we get the handle, it is our responsibility to close it
|
||
|
lResult = dialGetCommHandle(globals);
|
||
|
FAILIF(LINEERROR(lResult), Failure);
|
||
|
|
||
|
DPF(3, " hComPort: %08X", globals->hComm);
|
||
|
|
||
|
// setup com port
|
||
|
hr = globals->lpComPort->Setup(globals->lpComPort, globals->hComm);
|
||
|
FAILIF(FAILED(hr), Failure);
|
||
|
|
||
|
{
|
||
|
DWORD dwBaudRate;
|
||
|
|
||
|
lResult = dialGetBaudRate(globals, &dwBaudRate);
|
||
|
}
|
||
|
|
||
|
Failure:
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
/* ProcessDisconnectedState - handler for LINECALLSTATE_DISCONNECTED state */
|
||
|
|
||
|
#undef DPF_MODNAME
|
||
|
#define DPF_MODNAME "ProcessDisconnectedState"
|
||
|
|
||
|
void ProcessDisconnectedState(LPDPDIAL globals, HCALL hCall, DWORD dwCallStateDetail, DWORD dwCallPrivilege)
|
||
|
{
|
||
|
LINERESULT lResult;
|
||
|
|
||
|
DDASSERT(hCall);
|
||
|
DDASSERT(globals->hCall);
|
||
|
DDASSERT(globals->hCall == hCall);
|
||
|
|
||
|
DPF(3, " hCall: %08X", hCall);
|
||
|
DPF(3, " privilege: %08X", dwCallPrivilege);
|
||
|
DPF(3, " detail: %08X", dwCallStateDetail);
|
||
|
|
||
|
// record error
|
||
|
globals->dwCallError = CALL_DISCONNECTED;
|
||
|
|
||
|
// shutdown com port and deallocate call handle
|
||
|
lResult = dialDeallocCall(globals);
|
||
|
FAILMSG(LINEERROR(lResult));
|
||
|
}
|
||
|
|
||
|
/* ProcessIdleState - handler for LINECALLSTATE_IDLE state */
|
||
|
|
||
|
#undef DPF_MODNAME
|
||
|
#define DPF_MODNAME "ProcessIdleState"
|
||
|
|
||
|
void ProcessIdleState(LPDPDIAL globals, HCALL hCall, DWORD dwCallStateDetail, DWORD dwCallPrivilege)
|
||
|
{
|
||
|
DDASSERT(hCall);
|
||
|
|
||
|
DPF(3, " hCall: %08X", hCall);
|
||
|
DPF(3, " privilege: %08X", dwCallPrivilege);
|
||
|
DPF(3, " detail: %08X", dwCallStateDetail);
|
||
|
}
|
||
|
|
||
|
/* ProcessReplyMessage - handler for LINE_REPLY message */
|
||
|
|
||
|
#undef DPF_MODNAME
|
||
|
#define DPF_MODNAME "ProcessReplyMessage"
|
||
|
|
||
|
void ProcessReplyMessage(LPDPDIAL globals, DWORD dwAsyncID, LINERESULT lResult)
|
||
|
{
|
||
|
DDASSERT(dwAsyncID);
|
||
|
DDASSERT(globals->dwAsyncID);
|
||
|
DDASSERT(globals->dwAsyncID == dwAsyncID);
|
||
|
|
||
|
DPF(3, " dwAsyncID: %d", dwAsyncID);
|
||
|
DPF(3, " error: %d", lResult);
|
||
|
|
||
|
// check for an error
|
||
|
if (LINEERROR(lResult))
|
||
|
globals->dwCallError = CALL_LINEERROR;
|
||
|
|
||
|
|
||
|
// reset field so we know reply happened
|
||
|
globals->dwAsyncID = 0;
|
||
|
}
|
||
|
|
||
|
/* dialGetDevCaps - wrapper for lineGetDevCaps */
|
||
|
|
||
|
/* Bug #5400 -
|
||
|
|
||
|
My trusty Compaq Presario returns two line devices. The second device says it
|
||
|
needs 555 bytes for dev caps, but when you give it a pointer to a 555-byte block
|
||
|
it actually writes 559 (!) bytes into the buffer! Whoah, Bessy!
|
||
|
|
||
|
This makes Windows very unhappy in strange and magical ways.
|
||
|
|
||
|
The fix is to start with a very large buffer (1024 bytes?) like all the samples do
|
||
|
and then leave some slop in subsequent reallocs, which should hopefully clean up
|
||
|
after these messy critters.
|
||
|
*/
|
||
|
|
||
|
#define DEVCAPSINITIALSIZE 1024 // size of first alloc
|
||
|
#define DEVCAPSSLOP 100 // extra space that loser service providers can party on
|
||
|
|
||
|
#undef DPF_MODNAME
|
||
|
#define DPF_MODNAME "dialGetDevCaps"
|
||
|
|
||
|
LINERESULT dialGetDevCaps(LPDPDIAL globals, DWORD dwLine, DWORD dwAPIVersion, LPLINEDEVCAPS *lpDevCapsRet)
|
||
|
{
|
||
|
LPLINEDEVCAPS lpDevCaps;
|
||
|
LINERESULT lResult;
|
||
|
LPVOID lpTemp;
|
||
|
|
||
|
// create a buffer for dev caps
|
||
|
lpDevCaps = (LPLINEDEVCAPS) GlobalAllocPtr(GHND, DEVCAPSINITIALSIZE + DEVCAPSSLOP);
|
||
|
FAILWITHACTION(lpDevCaps == NULL, lResult = LINEERROR(LINEERR_NOMEM), Failure);
|
||
|
lpDevCaps->dwTotalSize = DEVCAPSINITIALSIZE;
|
||
|
|
||
|
while (TRUE)
|
||
|
{
|
||
|
// get device caps
|
||
|
lResult = lineGetDevCaps(globals->hLineApp, dwLine,
|
||
|
dwAPIVersion, 0, lpDevCaps);
|
||
|
|
||
|
if (lResult == SUCCESS)
|
||
|
{
|
||
|
// make sure there is enough space
|
||
|
if (lpDevCaps->dwNeededSize <= lpDevCaps->dwTotalSize)
|
||
|
break; // there is enough space, so exit
|
||
|
}
|
||
|
else if (lResult != LINEERR_STRUCTURETOOSMALL)
|
||
|
{
|
||
|
LINEERROR(lResult);
|
||
|
goto Failure;
|
||
|
}
|
||
|
|
||
|
// reallocate buffer if not big enough */
|
||
|
|
||
|
lpTemp = GlobalReAllocPtr(lpDevCaps, lpDevCaps->dwNeededSize + DEVCAPSSLOP, 0);
|
||
|
FAILWITHACTION(lpTemp == NULL, lResult = LINEERROR(LINEERR_NOMEM), Failure);
|
||
|
|
||
|
lpDevCaps = lpTemp;
|
||
|
lpDevCaps->dwTotalSize = lpDevCaps->dwNeededSize;
|
||
|
}
|
||
|
|
||
|
*lpDevCapsRet = lpDevCaps;
|
||
|
return (SUCCESS);
|
||
|
|
||
|
Failure:
|
||
|
if (lpDevCaps)
|
||
|
GlobalFreePtr(lpDevCaps);
|
||
|
return (lResult);
|
||
|
}
|
||
|
|
||
|
/* dialGetCallInfo - wrapper for lineGetCallInfo */
|
||
|
|
||
|
#undef DPF_MODNAME
|
||
|
#define DPF_MODNAME "dialGetCallInfo"
|
||
|
|
||
|
LINERESULT dialGetCallInfo(LPDPDIAL globals, LPLINECALLINFO *lpCallInfoRet)
|
||
|
{
|
||
|
LPLINECALLINFO lpCallInfo;
|
||
|
LINERESULT lResult;
|
||
|
LPVOID lpTemp;
|
||
|
|
||
|
// create a buffer for call info
|
||
|
lpCallInfo = (LPLINECALLINFO) GlobalAllocPtr(GHND, sizeof(LINECALLINFO));
|
||
|
FAILWITHACTION(lpCallInfo == NULL, lResult = LINEERROR(LINEERR_NOMEM), Failure);
|
||
|
lpCallInfo->dwTotalSize = sizeof(LINECALLINFO);
|
||
|
|
||
|
while (TRUE)
|
||
|
{
|
||
|
// get device info
|
||
|
lResult = lineGetCallInfo(globals->hCall, lpCallInfo);
|
||
|
|
||
|
if (lResult == SUCCESS)
|
||
|
{
|
||
|
// make sure there is enough space
|
||
|
if (lpCallInfo->dwNeededSize <= lpCallInfo->dwTotalSize)
|
||
|
break; // there is enough space, so exit
|
||
|
}
|
||
|
else if (lResult != LINEERR_STRUCTURETOOSMALL)
|
||
|
{
|
||
|
LINEERROR(lResult);
|
||
|
goto Failure;
|
||
|
}
|
||
|
|
||
|
// reallocate buffer if not big enough */
|
||
|
|
||
|
lpTemp = GlobalReAllocPtr(lpCallInfo, lpCallInfo->dwNeededSize, 0);
|
||
|
FAILWITHACTION(lpTemp == NULL, lResult = LINEERROR(LINEERR_NOMEM), Failure);
|
||
|
|
||
|
lpCallInfo = lpTemp;
|
||
|
lpCallInfo->dwTotalSize = lpCallInfo->dwNeededSize;
|
||
|
}
|
||
|
|
||
|
*lpCallInfoRet = lpCallInfo;
|
||
|
return (SUCCESS);
|
||
|
|
||
|
Failure:
|
||
|
if (lpCallInfo)
|
||
|
GlobalFreePtr(lpCallInfo);
|
||
|
return (lResult);
|
||
|
}
|
||
|
|
||
|
/* dialGetBaudRate - get baud rate of current connecton */
|
||
|
|
||
|
#undef DPF_MODNAME
|
||
|
#define DPF_MODNAME "dialGetBaudRate"
|
||
|
|
||
|
LINERESULT dialGetBaudRate(LPDPDIAL globals, LPDWORD lpdwBaudRate)
|
||
|
{
|
||
|
LPLINECALLINFO lpCallInfo;
|
||
|
LINERESULT lResult;
|
||
|
|
||
|
lResult = dialGetCallInfo(globals, &lpCallInfo);
|
||
|
if LINEERROR(lResult)
|
||
|
return (lResult);
|
||
|
|
||
|
*lpdwBaudRate = lpCallInfo->dwRate;
|
||
|
|
||
|
GlobalFreePtr(lpCallInfo);
|
||
|
|
||
|
return (SUCCESS);
|
||
|
}
|
||
|
|
||
|
/* dialGetTranslateCaps - wrapper for lineGetTranslateCaps */
|
||
|
|
||
|
#undef DPF_MODNAME
|
||
|
#define DPF_MODNAME "dialGetTranslateCaps"
|
||
|
|
||
|
LINERESULT dialGetTranslateCaps(LPDPDIAL globals, DWORD dwAPIVersion, LPLINETRANSLATECAPS *lpTranslateCapsRet)
|
||
|
{
|
||
|
LPLINETRANSLATECAPS lpTranslateCaps;
|
||
|
LPVOID lpTemp;
|
||
|
LINERESULT lResult;
|
||
|
|
||
|
// create a buffer for translate caps
|
||
|
lpTranslateCaps = (LPLINETRANSLATECAPS) GlobalAllocPtr(GHND, sizeof(LINETRANSLATECAPS));
|
||
|
FAILWITHACTION(lpTranslateCaps == NULL, lResult = LINEERROR(LINEERR_NOMEM), Failure);
|
||
|
lpTranslateCaps->dwTotalSize = sizeof(LINETRANSLATECAPS);
|
||
|
|
||
|
while (TRUE)
|
||
|
{
|
||
|
// get translate caps
|
||
|
lResult = lineGetTranslateCaps(globals->hLineApp, dwAPIVersion, lpTranslateCaps);
|
||
|
|
||
|
if (lResult == SUCCESS)
|
||
|
{
|
||
|
// make sure there is enough space
|
||
|
if (lpTranslateCaps->dwNeededSize <= lpTranslateCaps->dwTotalSize)
|
||
|
break; // there is enough space, so exit
|
||
|
}
|
||
|
else if (lResult != LINEERR_STRUCTURETOOSMALL)
|
||
|
{
|
||
|
LINEERROR(lResult);
|
||
|
goto Failure;
|
||
|
}
|
||
|
|
||
|
// reallocate buffer if not big enough */
|
||
|
|
||
|
lpTemp = GlobalReAllocPtr(lpTranslateCaps, lpTranslateCaps->dwNeededSize, 0);
|
||
|
FAILWITHACTION(lpTemp == NULL, lResult = LINEERROR(LINEERR_NOMEM), Failure);
|
||
|
|
||
|
lpTranslateCaps = lpTemp;
|
||
|
lpTranslateCaps->dwTotalSize = lpTranslateCaps->dwNeededSize;
|
||
|
}
|
||
|
|
||
|
*lpTranslateCapsRet = lpTranslateCaps;
|
||
|
return (SUCCESS);
|
||
|
|
||
|
Failure:
|
||
|
if (lpTranslateCaps)
|
||
|
GlobalFreePtr(lpTranslateCaps);
|
||
|
return (lResult);
|
||
|
}
|
||
|
|
||
|
/* dialGetCommHandle - wrapper for lineGetID */
|
||
|
|
||
|
#undef DPF_MODNAME
|
||
|
#define DPF_MODNAME "dialGetCommHandle"
|
||
|
|
||
|
/* structure returned by Unimodem which contains device handle and name */
|
||
|
typedef struct {
|
||
|
HANDLE hComm;
|
||
|
CHAR szDeviceName[1];
|
||
|
} COMMID, *LPCOMMID;
|
||
|
|
||
|
LINERESULT dialGetCommHandle(LPDPDIAL globals)
|
||
|
{
|
||
|
LPCOMMID lpCommID;
|
||
|
VARSTRING *vs, *temp;
|
||
|
LINERESULT lResult;
|
||
|
|
||
|
vs = (VARSTRING *) GlobalAllocPtr(GHND, sizeof(VARSTRING));
|
||
|
FAILWITHACTION(vs == NULL, lResult = LINEERR_NOMEM, Failure);
|
||
|
|
||
|
vs->dwTotalSize = sizeof(VARSTRING);
|
||
|
vs->dwStringFormat = STRINGFORMAT_BINARY;
|
||
|
|
||
|
while (TRUE)
|
||
|
{
|
||
|
// get line ID
|
||
|
lResult = lineGetID(0, 0L, globals->hCall, LINECALLSELECT_CALL, vs, "comm/datamodem");
|
||
|
|
||
|
if (lResult == SUCCESS)
|
||
|
{
|
||
|
// make sure there is enough space
|
||
|
if (vs->dwNeededSize <= vs->dwTotalSize)
|
||
|
break; // there is enough space, so exit
|
||
|
}
|
||
|
else if (lResult != LINEERR_STRUCTURETOOSMALL)
|
||
|
{
|
||
|
LINEERROR(lResult);
|
||
|
goto Failure;
|
||
|
}
|
||
|
|
||
|
// reallocate buffer if not big enough */
|
||
|
|
||
|
temp = GlobalReAllocPtr(vs, vs->dwNeededSize, 0);
|
||
|
FAILWITHACTION(temp == NULL, lResult = LINEERROR(LINEERR_NOMEM), Failure);
|
||
|
|
||
|
vs = temp;
|
||
|
vs->dwTotalSize = vs->dwNeededSize;
|
||
|
}
|
||
|
|
||
|
lpCommID = (LPCOMMID) ((LPSTR)vs + vs->dwStringOffset);
|
||
|
// lstrcpy(globals->szDeviceName, cid->szDeviceName);
|
||
|
globals->hComm = lpCommID->hComm;
|
||
|
|
||
|
Failure:
|
||
|
if (vs)
|
||
|
GlobalFreePtr(vs);
|
||
|
return (lResult);
|
||
|
}
|
||
|
|
||
|
/* dialCloseCommHandle - make sure com port is closed */
|
||
|
|
||
|
/* NOTE: As per the docs for the "comm/datamodem" device class,
|
||
|
the handle to the com port returned by lineGetID() MUST be explictly
|
||
|
closed using CloseHandle() or you will not be able to to open this
|
||
|
line again!
|
||
|
*/
|
||
|
|
||
|
#undef DPF_MODNAME
|
||
|
#define DPF_MODNAME "dialCloseCommHandle"
|
||
|
|
||
|
LINERESULT dialCloseCommHandle(LPDPDIAL globals)
|
||
|
{
|
||
|
HANDLE hCom;
|
||
|
|
||
|
// make sure the com port globals are available
|
||
|
if (globals->lpComPort)
|
||
|
{
|
||
|
// get handle to com port
|
||
|
hCom = globals->lpComPort->GetHandle(globals->lpComPort);
|
||
|
|
||
|
// make sure its closed down
|
||
|
if (hCom)
|
||
|
{
|
||
|
globals->lpComPort->Shutdown(globals->lpComPort);
|
||
|
CloseHandle(hCom);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return (SUCCESS);
|
||
|
}
|
||
|
|
||
|
/* dialTranslateAddress - wrapper for lineTranslateAddress */
|
||
|
|
||
|
#undef DPF_MODNAME
|
||
|
#define DPF_MODNAME "dialTranslateAddress"
|
||
|
|
||
|
LINERESULT dialTranslateAddress(LPDPDIAL globals, DWORD dwDeviceID, DWORD dwAPIVersion,
|
||
|
LPCSTR lpszDialAddress,
|
||
|
LPLINETRANSLATEOUTPUT *lpLineTranslateOutputRet)
|
||
|
{
|
||
|
LPLINETRANSLATEOUTPUT lpLineTranslateOutput;
|
||
|
LPVOID lpTemp;
|
||
|
LINERESULT lResult;
|
||
|
|
||
|
// create a buffer for translate caps
|
||
|
lpLineTranslateOutput = (LPLINETRANSLATEOUTPUT) GlobalAllocPtr(GHND, sizeof(LINETRANSLATEOUTPUT));
|
||
|
FAILWITHACTION(lpLineTranslateOutput == NULL, lResult = LINEERROR(LINEERR_NOMEM), Failure);
|
||
|
lpLineTranslateOutput->dwTotalSize = sizeof(LINETRANSLATEOUTPUT);
|
||
|
|
||
|
while (TRUE)
|
||
|
{
|
||
|
// translate address
|
||
|
lResult = lineTranslateAddress(globals->hLineApp, dwDeviceID, dwAPIVersion,
|
||
|
lpszDialAddress, 0, LINETRANSLATEOPTION_CANCELCALLWAITING,
|
||
|
lpLineTranslateOutput);
|
||
|
|
||
|
if (lResult == SUCCESS)
|
||
|
{
|
||
|
// make sure there is enough space
|
||
|
if (lpLineTranslateOutput->dwNeededSize <= lpLineTranslateOutput->dwTotalSize)
|
||
|
break; // there is enough space, so exit
|
||
|
}
|
||
|
else if (lResult != LINEERR_STRUCTURETOOSMALL)
|
||
|
{
|
||
|
LINEERROR(lResult);
|
||
|
goto Failure;
|
||
|
}
|
||
|
|
||
|
// reallocate buffer if not big enough */
|
||
|
|
||
|
lpTemp = GlobalReAllocPtr(lpLineTranslateOutput, lpLineTranslateOutput->dwNeededSize, 0);
|
||
|
FAILWITHACTION(lpTemp == NULL, lResult = LINEERROR(LINEERR_NOMEM), Failure);
|
||
|
|
||
|
lpLineTranslateOutput = lpTemp;
|
||
|
lpLineTranslateOutput->dwTotalSize = lpLineTranslateOutput->dwNeededSize;
|
||
|
}
|
||
|
|
||
|
*lpLineTranslateOutputRet = lpLineTranslateOutput;
|
||
|
return (SUCCESS);
|
||
|
|
||
|
Failure:
|
||
|
if (lpLineTranslateOutput)
|
||
|
GlobalFreePtr(lpLineTranslateOutput);
|
||
|
return (lResult);
|
||
|
}
|
||
|
|
||
|
LINERESULT dialTranslateDialog(LPDPDIAL globals, HWND hWnd,
|
||
|
DWORD dwDeviceID, LPTSTR szPhoneNumber)
|
||
|
{
|
||
|
LINERESULT lResult;
|
||
|
|
||
|
lResult = lineTranslateDialog(globals->hLineApp, dwDeviceID,
|
||
|
TAPIVERSION, hWnd, szPhoneNumber);
|
||
|
|
||
|
return (lResult);
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// FUNCTION: void dialFillModemComboBox(HWND)
|
||
|
//
|
||
|
// PURPOSE: Fills the modem control with the available line devices.
|
||
|
//
|
||
|
// PARAMETERS:
|
||
|
// hwndDlg - handle to the current "Dial" dialog
|
||
|
//
|
||
|
// RETURN VALUE:
|
||
|
// none
|
||
|
//
|
||
|
// COMMENTS:
|
||
|
//
|
||
|
// This function enumerates through all the TAPI line devices and
|
||
|
// queries each for the device name. The device name is then put into
|
||
|
// the 'TAPI Line' control. These device names are kept in order rather
|
||
|
// than sorted. This allows "Dial" to know which device ID the user
|
||
|
// selected just by the knowing the index of the selected string.
|
||
|
//
|
||
|
// There are default values if there isn't a device name, if there is
|
||
|
// an error on the device, or if the device name is an empty string.
|
||
|
// The device name is also checked to make sure it is null terminated.
|
||
|
//
|
||
|
// Note that a Legacy API Version is negotiated. Since the fields in
|
||
|
// the LINEDEVCAPS structure that we are interested in haven't moved, we
|
||
|
// can negotiate a lower API Version than this sample is designed for
|
||
|
// and still be able to access the necessary structure members.
|
||
|
//
|
||
|
// The first line that is usable by TapiComm is selected as the 'default'
|
||
|
// line. Also note that if there was a previously selected line, this
|
||
|
// remains the default line. This would likely only occur if this
|
||
|
// function is called after the dialog has initialized once; for example,
|
||
|
// if a new line is added.
|
||
|
//
|
||
|
//
|
||
|
|
||
|
LINERESULT dialGetModemName(LPDPDIAL globals, DWORD dwDeviceID,
|
||
|
LPSTR lpszModemName, DWORD dwModemNameSize)
|
||
|
{
|
||
|
LPLINEDEVCAPS lpLineDevCaps = NULL;
|
||
|
LPSTR lpszLineName;
|
||
|
LINEEXTENSIONID lineExtensionID; // Will be set to 0 to indicate no known extensions
|
||
|
DWORD dwAPIVersion; // api version
|
||
|
DWORD dwStrSize;
|
||
|
LINERESULT lResult;
|
||
|
|
||
|
/* negotiate API version for each line */
|
||
|
lResult = lineNegotiateAPIVersion(globals->hLineApp, dwDeviceID,
|
||
|
TAPIVERSION, TAPIVERSION,
|
||
|
&dwAPIVersion, &lineExtensionID);
|
||
|
if LINEERROR(lResult)
|
||
|
goto FAILURE;
|
||
|
|
||
|
lResult = dialGetDevCaps(globals, dwDeviceID, dwAPIVersion, &lpLineDevCaps);
|
||
|
if LINEERROR(lResult)
|
||
|
goto FAILURE;
|
||
|
|
||
|
if ((lpLineDevCaps->dwLineNameSize) &&
|
||
|
(lpLineDevCaps->dwLineNameOffset) &&
|
||
|
(lpLineDevCaps->dwStringFormat == STRINGFORMAT_ASCII))
|
||
|
{
|
||
|
// This is the name of the device.
|
||
|
lpszLineName = ((char *) lpLineDevCaps) + lpLineDevCaps->dwLineNameOffset;
|
||
|
|
||
|
if (lpszLineName[0] != '\0')
|
||
|
{
|
||
|
// Reverse indented to make this fit
|
||
|
|
||
|
// Make sure the device name is null terminated.
|
||
|
if (lpszLineName[lpLineDevCaps->dwLineNameSize -1] != '\0')
|
||
|
{
|
||
|
// If the device name is not null terminated, null
|
||
|
// terminate it. Yes, this looses the end character.
|
||
|
// Its a bug in the service provider.
|
||
|
lpszLineName[lpLineDevCaps->dwLineNameSize-1] = '\0';
|
||
|
DPF(0, "Device name for device 0x%lx is not null terminated.", dwDeviceID);
|
||
|
}
|
||
|
}
|
||
|
else // Line name started with a NULL.
|
||
|
{
|
||
|
lResult = LINEERR_OPERATIONFAILED;
|
||
|
goto FAILURE;
|
||
|
}
|
||
|
}
|
||
|
else // DevCaps doesn't have a valid line name. Unnamed.
|
||
|
{
|
||
|
lResult = LINEERR_OPERATIONFAILED;
|
||
|
goto FAILURE;
|
||
|
}
|
||
|
|
||
|
// return modem name (make sure it fits)
|
||
|
dwStrSize = strlen(lpszLineName) + 1;
|
||
|
if (dwStrSize <= dwModemNameSize)
|
||
|
CopyMemory(lpszModemName, lpszLineName, dwStrSize);
|
||
|
else
|
||
|
{
|
||
|
CopyMemory(lpszModemName, lpszLineName, dwModemNameSize - 1);
|
||
|
lpszModemName[dwModemNameSize - 1] = '\0';
|
||
|
}
|
||
|
|
||
|
FAILURE:
|
||
|
if (lpLineDevCaps)
|
||
|
GlobalFreePtr(lpLineDevCaps);
|
||
|
|
||
|
return (lResult);
|
||
|
}
|
||
|
|
||
|
LINERESULT dialGetModemList(LPDPDIAL globals, BOOL bAnsi, LPVOID *lplpData, LPDWORD lpdwDataSize)
|
||
|
{
|
||
|
DWORD dwDeviceID;
|
||
|
CHAR szModemName[MAXSTRINGSIZE];
|
||
|
LPBYTE lpData;
|
||
|
DWORD dwDataSize, dwStrBytes, dwStrLen;
|
||
|
LINERESULT lResult;
|
||
|
|
||
|
// make space for all possible strings plus terminating null
|
||
|
lpData = (LPBYTE) GlobalAllocPtr(GHND, globals->dwNumLines * MAXSTRINGSIZE * sizeof(WCHAR) + sizeof(WCHAR));
|
||
|
FAILWITHACTION(lpData == NULL, lResult = LINEERR_NOMEM, Failure);
|
||
|
|
||
|
dwDataSize = 0;
|
||
|
for (dwDeviceID = 0; dwDeviceID < globals->dwNumLines; dwDeviceID ++)
|
||
|
{
|
||
|
lResult = dialGetModemName(globals, dwDeviceID, szModemName, MAXSTRINGSIZE);
|
||
|
if LINEERROR(lResult)
|
||
|
continue;
|
||
|
|
||
|
if (bAnsi)
|
||
|
{
|
||
|
dwStrBytes = (lstrlen(szModemName) + 1) * sizeof(CHAR);
|
||
|
memcpy(lpData + dwDataSize, szModemName, dwStrBytes);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// NOTE: AnsiToWide returns the character count INCLUDING the terminating null character
|
||
|
dwStrLen = AnsiToWide((LPWSTR) (lpData + dwDataSize), szModemName, MAXSTRINGSIZE * sizeof(WCHAR));
|
||
|
dwStrBytes = dwStrLen * sizeof(WCHAR);
|
||
|
}
|
||
|
|
||
|
dwDataSize += dwStrBytes;
|
||
|
}
|
||
|
|
||
|
// put a null at end of list to terminate it
|
||
|
if (bAnsi)
|
||
|
{
|
||
|
*(lpData + dwDataSize) = 0;
|
||
|
dwDataSize += sizeof(CHAR);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
*((LPWSTR) (lpData + dwDataSize)) = 0;
|
||
|
dwDataSize += sizeof(WCHAR);
|
||
|
}
|
||
|
|
||
|
// return buffer pointer and size
|
||
|
*lplpData = lpData;
|
||
|
*lpdwDataSize = dwDataSize;
|
||
|
|
||
|
return (SUCCESS);
|
||
|
|
||
|
Failure:
|
||
|
return (lResult);
|
||
|
}
|
||
|
|
||
|
void dialFillModemComboBox(LPDPDIAL globals, HWND hwndDlg, int item, DWORD dwDefaultDevice)
|
||
|
{
|
||
|
DWORD dwDeviceID;
|
||
|
CHAR szModemName[MAXSTRINGSIZE];
|
||
|
LINERESULT lResult;
|
||
|
|
||
|
|
||
|
for (dwDeviceID = 0; dwDeviceID < globals->dwNumLines; dwDeviceID ++)
|
||
|
{
|
||
|
//
|
||
|
// Attempt to get the modem name. If this fails, don't add the modem
|
||
|
// to the dialog.
|
||
|
//
|
||
|
lResult = dialGetModemName(globals, dwDeviceID, szModemName, MAXSTRINGSIZE);
|
||
|
if ( LINEERROR(lResult) == FALSE )
|
||
|
{
|
||
|
//
|
||
|
// This line appears to be usable, put the device name into the
|
||
|
// dialog control and associate the TAPI modem ID with it
|
||
|
//
|
||
|
lResult = (DWORD) SendDlgItemMessage(hwndDlg, item,
|
||
|
CB_ADDSTRING, 0, (LPARAM) szModemName);
|
||
|
|
||
|
if ( lResult != CB_ERRSPACE )
|
||
|
{
|
||
|
DWORD_PTR TempReturn;
|
||
|
|
||
|
|
||
|
//
|
||
|
// We've managed to get this entry into the control, make sure
|
||
|
// we associate the proper TAPI modem ID with this item. This
|
||
|
// should never fail.
|
||
|
//
|
||
|
TempReturn = SendDlgItemMessage( hwndDlg, item, CB_SETITEMDATA, lResult, dwDeviceID );
|
||
|
DDASSERT( TempReturn != CB_ERR );
|
||
|
|
||
|
// If this line is usable and we don't have a default initial
|
||
|
// line yet, make this the initial line.
|
||
|
if (dwDefaultDevice == MAXDWORD)
|
||
|
dwDefaultDevice = lResult;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (dwDefaultDevice == MAXDWORD)
|
||
|
dwDefaultDevice = 0;
|
||
|
|
||
|
// Set the initial default line
|
||
|
SendDlgItemMessage(hwndDlg, item,
|
||
|
CB_SETCURSEL, dwDefaultDevice, 0);
|
||
|
}
|
||
|
|
||
|
LRESULT dialGetDeviceIDFromName(LPDPDIAL globals, LPCSTR szTargetName, DWORD *lpdwDeviceID)
|
||
|
{
|
||
|
DWORD dwDeviceID;
|
||
|
CHAR szModemName[MAXSTRINGSIZE];
|
||
|
LINERESULT lResult;
|
||
|
|
||
|
for (dwDeviceID = 0; dwDeviceID < globals->dwNumLines; dwDeviceID ++)
|
||
|
{
|
||
|
lResult = dialGetModemName(globals, dwDeviceID, szModemName, MAXSTRINGSIZE);
|
||
|
if LINEERROR(lResult)
|
||
|
continue;
|
||
|
|
||
|
if (strcmp(szModemName, szTargetName) == 0)
|
||
|
{
|
||
|
*lpdwDeviceID = dwDeviceID;
|
||
|
return (SUCCESS);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return (LINEERR_OPERATIONFAILED);
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// FUNCTION: void dialFillLocationComboBox(HWND)
|
||
|
//
|
||
|
// PURPOSE: Fills the control with the available calling from locations.
|
||
|
//
|
||
|
// PARAMETERS:
|
||
|
// hwndDlg - handle to the current "Dial" dialog
|
||
|
//
|
||
|
// RETURN VALUE:
|
||
|
// none
|
||
|
//
|
||
|
// COMMENTS:
|
||
|
//
|
||
|
//
|
||
|
|
||
|
void dialFillLocationComboBox(LPDPDIAL globals, HWND hwndDlg, int item, DWORD dwDefaultLocation)
|
||
|
{
|
||
|
LPLINETRANSLATECAPS lpTranslateCaps = NULL;
|
||
|
LPLINELOCATIONENTRY lpLocationEntry;
|
||
|
DWORD dwCounter;
|
||
|
LONG index;
|
||
|
LINERESULT lResult;
|
||
|
|
||
|
// get translate caps
|
||
|
lResult = dialGetTranslateCaps(globals, TAPIVERSION, &lpTranslateCaps);
|
||
|
if LINEERROR(lResult)
|
||
|
return;
|
||
|
|
||
|
// Find the location information in the TRANSLATECAPS
|
||
|
lpLocationEntry = (LPLINELOCATIONENTRY)
|
||
|
(((LPBYTE) lpTranslateCaps) + lpTranslateCaps->dwLocationListOffset);
|
||
|
|
||
|
// First empty the combobox
|
||
|
SendDlgItemMessage(hwndDlg, item, CB_RESETCONTENT, (WPARAM) 0, (LPARAM) 0);
|
||
|
|
||
|
// enumerate all the locations
|
||
|
for (dwCounter = 0; dwCounter < lpTranslateCaps->dwNumLocations; dwCounter++)
|
||
|
{
|
||
|
// Put each one into the combobox
|
||
|
index = (DWORD)SendDlgItemMessage(hwndDlg, item,
|
||
|
CB_ADDSTRING,
|
||
|
(WPARAM) 0,
|
||
|
(LPARAM) (((LPBYTE) lpTranslateCaps) +
|
||
|
lpLocationEntry[dwCounter].dwLocationNameOffset));
|
||
|
|
||
|
// Is this location the 'current' location?
|
||
|
if (lpLocationEntry[dwCounter].dwPermanentLocationID ==
|
||
|
lpTranslateCaps->dwCurrentLocationID)
|
||
|
{
|
||
|
// Set this to be the active location.
|
||
|
SendDlgItemMessage(hwndDlg, item, CB_SETCURSEL, (WPARAM) index, (LPARAM) 0);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (lpTranslateCaps)
|
||
|
GlobalFreePtr(lpTranslateCaps);
|
||
|
}
|
||
|
|
||
|
|
||
|
char gTempStr[200];
|
||
|
|
||
|
LONG lineError(LONG err, LPSTR modName, DWORD lineNum)
|
||
|
{
|
||
|
if (err)
|
||
|
DPF(0, "TAPI line error in %s at line %d : %s", modName, lineNum, GetLineErrStr(err));
|
||
|
|
||
|
return (err);
|
||
|
}
|
||
|
|
||
|
LPSTR GetCallStateStr(DWORD callState)
|
||
|
{
|
||
|
switch (callState)
|
||
|
{
|
||
|
case LINECALLSTATE_IDLE: return ("LINECALLSTATE_IDLE");
|
||
|
case LINECALLSTATE_OFFERING: return ("LINECALLSTATE_OFFERING");
|
||
|
case LINECALLSTATE_ACCEPTED: return ("LINECALLSTATE_ACCEPTED");
|
||
|
case LINECALLSTATE_DIALTONE: return ("LINECALLSTATE_DIALTONE");
|
||
|
case LINECALLSTATE_DIALING: return ("LINECALLSTATE_DIALING");
|
||
|
case LINECALLSTATE_RINGBACK: return ("LINECALLSTATE_RINGBACK");
|
||
|
case LINECALLSTATE_BUSY: return ("LINECALLSTATE_BUSY");
|
||
|
case LINECALLSTATE_SPECIALINFO: return ("LINECALLSTATE_SPECIALINFO");
|
||
|
case LINECALLSTATE_CONNECTED: return ("LINECALLSTATE_CONNECTED");
|
||
|
case LINECALLSTATE_PROCEEDING: return ("LINECALLSTATE_PROCEEDING");
|
||
|
case LINECALLSTATE_ONHOLD: return ("LINECALLSTATE_ONHOLD");
|
||
|
case LINECALLSTATE_CONFERENCED: return ("LINECALLSTATE_CONFERENCED");
|
||
|
case LINECALLSTATE_ONHOLDPENDCONF: return ("LINECALLSTATE_ONHOLDPENDCONF");
|
||
|
case LINECALLSTATE_ONHOLDPENDTRANSFER: return ("LINECALLSTATE_ONHOLDPENDTRANSFER");
|
||
|
case LINECALLSTATE_DISCONNECTED: return ("LINECALLSTATE_DISCONNECTED");
|
||
|
case LINECALLSTATE_UNKNOWN: return ("LINECALLSTATE_UNKNOWN");
|
||
|
}
|
||
|
|
||
|
wsprintf(gTempStr, "UNKNOWN CALL STATE = %lu", callState);
|
||
|
return (gTempStr);
|
||
|
}
|
||
|
|
||
|
LPSTR GetLineMsgStr(DWORD msg)
|
||
|
{
|
||
|
switch (msg)
|
||
|
{
|
||
|
case LINE_ADDRESSSTATE: return ("LINE_ADDRESSSTATE");
|
||
|
case LINE_CALLINFO: return ("LINE_CALLINFO");
|
||
|
case LINE_CALLSTATE: return ("LINE_CALLSTATE");
|
||
|
case LINE_CLOSE: return ("LINE_CLOSE");
|
||
|
case LINE_DEVSPECIFIC: return ("LINE_DEVSPECIFIC");
|
||
|
case LINE_DEVSPECIFICFEATURE: return ("LINE_DEVSPECIFICFEATURE");
|
||
|
case LINE_GATHERDIGITS: return ("LINE_GATHERDIGITS");
|
||
|
case LINE_GENERATE: return ("LINE_GENERATE");
|
||
|
case LINE_LINEDEVSTATE: return ("LINE_LINEDEVSTATE");
|
||
|
case LINE_MONITORDIGITS: return ("LINE_MONITORDIGITS");
|
||
|
case LINE_MONITORMEDIA: return ("LINE_MONITORMEDIA");
|
||
|
case LINE_MONITORTONE: return ("LINE_MONITORTONE");
|
||
|
case LINE_REPLY: return ("LINE_REPLY");
|
||
|
case LINE_REQUEST: return ("LINE_REQUEST");
|
||
|
}
|
||
|
|
||
|
wsprintf(gTempStr, "UNKNOWN LINE MESSAGE = %lu", msg);
|
||
|
return (gTempStr);
|
||
|
}
|
||
|
|
||
|
|
||
|
LPSTR GetLineErrStr(LONG err)
|
||
|
{
|
||
|
switch (err)
|
||
|
{
|
||
|
case LINEERR_ADDRESSBLOCKED: return ("LINEERR_ADDRESSBLOCKED");
|
||
|
case LINEERR_ALLOCATED: return ("LINEERR_ALLOCATED");
|
||
|
case LINEERR_BADDEVICEID: return ("LINEERR_BADDEVICEID");
|
||
|
case LINEERR_BEARERMODEUNAVAIL: return ("LINEERR_BEARERMODEUNAVAIL");
|
||
|
case LINEERR_CALLUNAVAIL: return ("LINEERR_CALLUNAVAIL");
|
||
|
case LINEERR_COMPLETIONOVERRUN: return ("LINEERR_COMPLETIONOVERRUN");
|
||
|
case LINEERR_CONFERENCEFULL: return ("LINEERR_CONFERENCEFULL");
|
||
|
case LINEERR_DIALBILLING: return ("LINEERR_DIALBILLING");
|
||
|
case LINEERR_DIALQUIET: return ("LINEERR_DIALQUIET");
|
||
|
case LINEERR_DIALDIALTONE: return ("LINEERR_DIALDIALTONE");
|
||
|
case LINEERR_DIALPROMPT: return ("LINEERR_DIALPROMPT");
|
||
|
case LINEERR_INCOMPATIBLEAPIVERSION: return ("LINEERR_INCOMPATIBLEAPIVERSION");
|
||
|
case LINEERR_INCOMPATIBLEEXTVERSION: return ("LINEERR_INCOMPATIBLEEXTVERSION");
|
||
|
case LINEERR_INIFILECORRUPT: return ("LINEERR_INIFILECORRUPT");
|
||
|
case LINEERR_INUSE: return ("LINEERR_INUSE");
|
||
|
case LINEERR_INVALADDRESS: return ("LINEERR_INVALADDRESS");
|
||
|
case LINEERR_INVALADDRESSID: return ("LINEERR_INVALADDRESSID");
|
||
|
case LINEERR_INVALADDRESSMODE: return ("LINEERR_INVALADDRESSMODE");
|
||
|
case LINEERR_INVALADDRESSSTATE: return ("LINEERR_INVALADDRESSSTATE");
|
||
|
case LINEERR_INVALAPPHANDLE: return ("LINEERR_INVALAPPHANDLE");
|
||
|
case LINEERR_INVALAPPNAME: return ("LINEERR_INVALAPPNAME");
|
||
|
case LINEERR_INVALBEARERMODE: return ("LINEERR_INVALBEARERMODE");
|
||
|
case LINEERR_INVALCALLCOMPLMODE: return ("LINEERR_INVALCALLCOMPLMODE");
|
||
|
case LINEERR_INVALCALLHANDLE: return ("LINEERR_INVALCALLHANDLE");
|
||
|
case LINEERR_INVALCALLPARAMS: return ("LINEERR_INVALCALLPARAMS");
|
||
|
case LINEERR_INVALCALLPRIVILEGE: return ("LINEERR_INVALCALLPRIVILEGE");
|
||
|
case LINEERR_INVALCALLSELECT: return ("LINEERR_INVALCALLSELECT");
|
||
|
case LINEERR_INVALCALLSTATE: return ("LINEERR_INVALCALLSTATE");
|
||
|
case LINEERR_INVALCALLSTATELIST: return ("LINEERR_INVALCALLSTATELIST");
|
||
|
case LINEERR_INVALCARD: return ("LINEERR_INVALCARD");
|
||
|
case LINEERR_INVALCOMPLETIONID: return ("LINEERR_INVALCOMPLETIONID");
|
||
|
case LINEERR_INVALCONFCALLHANDLE: return ("LINEERR_INVALCONFCALLHANDLE");
|
||
|
case LINEERR_INVALCONSULTCALLHANDLE: return ("LINEERR_INVALCONSULTCALLHANDLE");
|
||
|
case LINEERR_INVALCOUNTRYCODE: return ("LINEERR_INVALCOUNTRYCODE");
|
||
|
case LINEERR_INVALDEVICECLASS: return ("LINEERR_INVALDEVICECLASS");
|
||
|
case LINEERR_INVALDIGITLIST: return ("LINEERR_INVALDIGITLIST");
|
||
|
case LINEERR_INVALDIGITMODE: return ("LINEERR_INVALDIGITMODE");
|
||
|
case LINEERR_INVALDIGITS: return ("LINEERR_INVALDIGITS");
|
||
|
case LINEERR_INVALFEATURE: return ("LINEERR_INVALFEATURE");
|
||
|
case LINEERR_INVALGROUPID: return ("LINEERR_INVALGROUPID");
|
||
|
case LINEERR_INVALLINEHANDLE: return ("LINEERR_INVALLINEHANDLE");
|
||
|
case LINEERR_INVALLINESTATE: return ("LINEERR_INVALLINESTATE");
|
||
|
case LINEERR_INVALLOCATION: return ("LINEERR_INVALLOCATION");
|
||
|
case LINEERR_INVALMEDIALIST: return ("LINEERR_INVALMEDIALIST");
|
||
|
case LINEERR_INVALMEDIAMODE: return ("LINEERR_INVALMEDIAMODE");
|
||
|
case LINEERR_INVALMESSAGEID: return ("LINEERR_INVALMESSAGEID");
|
||
|
case LINEERR_INVALPARAM: return ("LINEERR_INVALPARAM");
|
||
|
case LINEERR_INVALPARKMODE: return ("LINEERR_INVALPARKMODE");
|
||
|
case LINEERR_INVALPOINTER: return ("LINEERR_INVALPOINTER");
|
||
|
case LINEERR_INVALPRIVSELECT: return ("LINEERR_INVALPRIVSELECT");
|
||
|
case LINEERR_INVALRATE: return ("LINEERR_INVALRATE");
|
||
|
case LINEERR_INVALREQUESTMODE: return ("LINEERR_INVALREQUESTMODE");
|
||
|
case LINEERR_INVALTERMINALID: return ("LINEERR_INVALTERMINALID");
|
||
|
case LINEERR_INVALTERMINALMODE: return ("LINEERR_INVALTERMINALMODE");
|
||
|
case LINEERR_INVALTIMEOUT: return ("LINEERR_INVALTIMEOUT");
|
||
|
case LINEERR_INVALTONE: return ("LINEERR_INVALTONE");
|
||
|
case LINEERR_INVALTONELIST: return ("LINEERR_INVALTONELIST");
|
||
|
case LINEERR_INVALTONEMODE: return ("LINEERR_INVALTONEMODE");
|
||
|
case LINEERR_INVALTRANSFERMODE: return ("LINEERR_INVALTRANSFERMODE");
|
||
|
case LINEERR_LINEMAPPERFAILED: return ("LINEERR_LINEMAPPERFAILED");
|
||
|
case LINEERR_NOCONFERENCE: return ("LINEERR_NOCONFERENCE");
|
||
|
case LINEERR_NODEVICE: return ("LINEERR_NODEVICE");
|
||
|
case LINEERR_NODRIVER: return ("LINEERR_NODRIVER");
|
||
|
case LINEERR_NOMEM: return ("LINEERR_NOMEM");
|
||
|
case LINEERR_NOMULTIPLEINSTANCE: return ("LINEERR_NOMULTIPLEINSTANCE");
|
||
|
case LINEERR_NOREQUEST: return ("LINEERR_NOREQUEST");
|
||
|
case LINEERR_NOTOWNER: return ("LINEERR_NOTOWNER");
|
||
|
case LINEERR_NOTREGISTERED: return ("LINEERR_NOTREGISTERED");
|
||
|
case LINEERR_OPERATIONFAILED: return ("LINEERR_OPERATIONFAILED");
|
||
|
case LINEERR_OPERATIONUNAVAIL: return ("LINEERR_OPERATIONUNAVAIL");
|
||
|
case LINEERR_RATEUNAVAIL: return ("LINEERR_RATEUNAVAIL");
|
||
|
case LINEERR_REINIT: return ("LINEERR_REINIT");
|
||
|
case LINEERR_RESOURCEUNAVAIL: return ("LINEERR_RESOURCEUNAVAIL");
|
||
|
case LINEERR_STRUCTURETOOSMALL: return ("LINEERR_STRUCTURETOOSMALL");
|
||
|
case LINEERR_TARGETNOTFOUND: return ("LINEERR_TARGETNOTFOUND");
|
||
|
case LINEERR_TARGETSELF: return ("LINEERR_TARGETSELF");
|
||
|
case LINEERR_UNINITIALIZED: return ("LINEERR_UNINITIALIZED");
|
||
|
case LINEERR_USERUSERINFOTOOBIG: return ("LINEERR_USERUSERINFOTOOBIG");
|
||
|
}
|
||
|
|
||
|
wsprintf(gTempStr, "UNKNOWN LINE ERROR = %ld", err);
|
||
|
return (gTempStr);
|
||
|
}
|