Windows NT 4.0 source code leak
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.
 
 
 
 
 
 

1160 lines
30 KiB

// Happy Modem Testing Service Provider
// derived from PDISP
#ifndef TESTING
#define TESTING
#endif
#define USECOMM /* for chicago windows.h */
#include <windows.h>
#include <memory.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include "hmtsp.h"
#ifdef TESTING
void FAR PASCAL LogDestAddress(LPCSTR szDestAddress);
#endif
BOOL CALLBACK ConfigDlgProc(HWND, UINT, WPARAM, LPARAM);
int SerialOpenComms (LPSTR, LPSTR);
void LoadIniStrings (DWORD);
long appCall (int, char *, long);
#define msgMakeCall 1
#define msgDrop 2
// The number of entries in the devices and speed array.
#define NUMPORTS 4
char *lpszCommDevArray[NUMPORTS] =
{ "COM1", "COM2", "COM3", "COM4" };
// Various tags in the ini file.
char s_telephon_ini[] = "telephon.ini";
char s_one[] = "1";
char s_zero[] = "0";
char s_numlines[] = "NumLines";
char s_numphones[] = "NumPhones";
char s_providerx[] = "Provider%d";
char s_port[] = "Port";
char s_linename[] = "LineName";
char s_lineaddr[] = "LineAddress";
// The global module handle
HANDLE hInst = NULL;
// Line object.
ATSPLineData line;
// Provider description string
char gszProviderInfo[255];
///////////////////////////////////////////////////////////
// The required DLL functions
///////////////////////////////////////////////////////////
int FAR PASCAL LibMain(HANDLE hInstance, WORD wDataSegment,
WORD wHeapSize, LPSTR lpszCmdLine)
{
if (hInst != NULL)
return FALSE;
hInst = hInstance;
return TRUE;
}
VOID FAR PASCAL WEP (int bSystemExit)
{
hInst = NULL;
}
///////////////////////////////////////////////////////////
// The Service Provider Basic Configuration Routines
///////////////////////////////////////////////////////////
static BOOL initialised = FALSE;
LONG TSPIAPI TSPI_lineNegotiateTSPIVersion (
DWORD dwDeviceID,
DWORD dwLowVersion,
DWORD dwHighVersion,
LPDWORD lpdwTSPIVersion)
{
DebugMsg (("Entering TSPI_lineNegotiateTSPIVersion"));
// line.lineID will contain garbage before provider_init has
// been called (ie. first time through). However, we can guarantee
// that the first call will be with INITIALIZE_NEGOTIATION and that
// is followed immediately by provider_init. This would be a problem
// if the line data structure was dynamically allocated !
if (dwDeviceID == INITIALIZE_NEGOTIATION ||
dwDeviceID == line.lineID) // we support only one line
{
*lpdwTSPIVersion = ATSP_VERSION;
if (dwLowVersion > ATSP_VERSION || // the app is too new for us
dwHighVersion < ATSP_VERSION) // we are too new for the app
return LINEERR_INCOMPATIBLEAPIVERSION;
else
return 0;
}
return LINEERR_BADDEVICEID; // The requested device doesn't exist
}
LONG TSPIAPI TSPI_providerInit (
DWORD dwTSPIVersion,
DWORD dwPermanentProviderID,
DWORD dwLineDeviceIDBase,
DWORD dwPhoneDeviceIDBase,
DWORD dwNumLines,
DWORD dwNumPhones,
ASYNC_COMPLETION lpfnCompletionProc,
LPDWORD lpdwOptions
)
{
DebugMsg (("Entering TSPI_providerInit"));
assert (dwTSPIVersion == ATSP_VERSION);
assert (dwNumLines == 1);
assert (dwNumPhones == 0);
if (initialised)
return LINEERR_NOMULTIPLEINSTANCE;
// initialise our internal structures
ZeroMemory (&line, sizeof (ATSPLineData));
line.lpfnCompletion = lpfnCompletionProc;
line.lineID = dwLineDeviceIDBase;
line.dwMediaMode = LINEMEDIAMODE_INTERACTIVEVOICE;
line.hcd = -1;
LoadIniStrings (dwPermanentProviderID);
initialised = TRUE;
return 0;
}
LONG TSPIAPI TSPI_providerShutdown (DWORD dwTSPIVersion)
{
DebugMsg (("Entering TSPI_providerShutdown"));
initialised = FALSE;
return 0;
}
///////////////////////////////////////////////////////////
// The Line Specific Calls
///////////////////////////////////////////////////////////
LONG TSPIAPI TSPI_lineConfigDialog (
DWORD dwDeviceID,
HWND hwndOwner,
LPCSTR lpszDeviceClass)
{
DebugMsg (("Entering TSPI_lineConfigDialog"));
if (dwDeviceID != line.lineID)
return LINEERR_BADDEVICEID;
#ifndef TESTING
DialogBox (hInst, MAKEINTRESOURCE (IDD_CFGDLG),
hwndOwner, ConfigDlgProc);
#endif
return 0;
}
long lineDropCore (ATSPLineData *theLine, DWORD dwRequestID)
{
// if the call is not idle, transition to idle and close the comms port
return appCall (msgDrop, 0, dwRequestID);
}
LONG TSPIAPI TSPI_lineClose (HDRVLINE hdLine)
{
DebugMsg (("Entering TSPI_lineClose"));
if (hdLine != (HDRVLINE) &line)
return LINEERR_INVALLINEHANDLE;
// call drop in case there is still an active call on the line
lineDropCore (&line, 0);
return 0;
}
LONG TSPIAPI TSPI_lineCloseCall (HDRVCALL hdCall)
{
DebugMsg (("Entering TSPI_lineCloseCall"));
if (hdCall != (HDRVCALL) line.htCall)
return LINEERR_INVALCALLHANDLE;
// call drop in case there is still an active call on the line
lineDropCore (&line, 0);
line.callState = 0;
return 0;
}
LONG TSPIAPI TSPI_lineDrop (
DRV_REQUESTID dwRequestID,
HDRVCALL hdCall,
LPCSTR lpsUserUserInfo,
DWORD dwSize)
{
// Transition a call to the IDLE state.
DebugMsg (("Entering TSPI_lineDrop"));
if (hdCall != (HDRVCALL) line.htCall)
return LINEERR_INVALCALLHANDLE;
return lineDropCore (&line, dwRequestID); // it was our active call
}
LONG TSPIAPI TSPI_lineGetAddressCaps (
DWORD dwDeviceID,
DWORD dwAddressID,
DWORD dwTSPIVersion,
DWORD dwExtVersion,
LPLINEADDRESSCAPS lpAddressCaps)
{
int cbLineAddr;
DebugMsg (("Entering TSPI_lineGetAddressCaps"));
// We support only one line and one address.
if (dwDeviceID != line.lineID)
return LINEERR_BADDEVICEID;
if (dwAddressID != 0)
return LINEERR_INVALADDRESSID;
cbLineAddr = lstrlen (line.lineaddr) + 1;
lpAddressCaps->dwNeededSize = sizeof (LINEADDRESSCAPS) + cbLineAddr;
if (lpAddressCaps->dwTotalSize < lpAddressCaps->dwNeededSize)
lpAddressCaps->dwUsedSize = sizeof (LINEADDRESSCAPS);
else
{
MoveMemory((char *) lpAddressCaps + sizeof (LINEADDRESSCAPS),
line.lineaddr, cbLineAddr);
lpAddressCaps->dwAddressSize = cbLineAddr;
lpAddressCaps->dwAddressOffset = sizeof (LINEADDRESSCAPS);
lpAddressCaps->dwUsedSize = lpAddressCaps->dwNeededSize;
}
lpAddressCaps->dwLineDeviceID = line.lineID;
lpAddressCaps->dwAddressSharing = LINEADDRESSSHARING_PRIVATE;
lpAddressCaps->dwAddressStates = LINEADDRESSSTATE_OTHER |
LINEADDRESSSTATE_INUSEZERO |
LINEADDRESSSTATE_INUSEONE |
LINEADDRESSSTATE_NUMCALLS;
lpAddressCaps->dwCallInfoStates = LINECALLINFOSTATE_OTHER |
LINECALLINFOSTATE_APPSPECIFIC |
LINECALLINFOSTATE_NUMOWNERINCR |
LINECALLINFOSTATE_NUMOWNERDECR |
LINECALLINFOSTATE_NUMMONITORS |
LINECALLINFOSTATE_DIALPARAMS;
lpAddressCaps->dwCallerIDFlags = LINECALLPARTYID_UNAVAIL;
lpAddressCaps->dwCalledIDFlags = LINECALLPARTYID_UNAVAIL;
lpAddressCaps->dwConnectedIDFlags = LINECALLPARTYID_UNAVAIL;
lpAddressCaps->dwRedirectionIDFlags = LINECALLPARTYID_UNAVAIL;
lpAddressCaps->dwRedirectingIDFlags = LINECALLPARTYID_UNAVAIL;
lpAddressCaps->dwCallStates = LINECALLSTATE_IDLE |
LINECALLSTATE_DIALTONE |
LINECALLSTATE_DIALING |
LINECALLSTATE_BUSY |
LINECALLSTATE_CONNECTED |
LINECALLSTATE_PROCEEDING |
LINECALLSTATE_UNKNOWN;
lpAddressCaps->dwDialToneModes = LINEDIALTONEMODE_UNAVAIL;
lpAddressCaps->dwBusyModes = LINEBUSYMODE_UNAVAIL;
lpAddressCaps->dwSpecialInfo = LINESPECIALINFO_UNAVAIL;
lpAddressCaps->dwDisconnectModes = LINEDISCONNECTMODE_UNKNOWN;
lpAddressCaps->dwMaxNumActiveCalls = 1;
lpAddressCaps->dwAddrCapFlags = LINEADDRCAPFLAGS_BLOCKIDDEFAULT |
LINEADDRCAPFLAGS_DIALED |
LINEADDRCAPFLAGS_PARTIALDIAL;
lpAddressCaps->dwCallFeatures = LINECALLFEATURE_DIAL |
LINECALLFEATURE_DROP;
return 0;
}
LONG TSPIAPI TSPI_lineGetAddressID (
HDRVLINE hdLine,
LPDWORD lpdwAddressID,
DWORD dwAddressMode,
LPCSTR lpsAddress,
DWORD dwSize)
{
DebugMsg (("Entering TSPI_lineGetAddressID"));
if (hdLine != (HDRVLINE) &line)
return LINEERR_INVALLINEHANDLE;
assert (dwAddressMode == LINEADDRESSMODE_DIALABLEADDR);
if (lstrcmp (line.lineaddr, lpsAddress))
return LINEERR_INVALADDRESS;
else
{
*lpdwAddressID = 0; // we support only 1 line
return 0;
}
}
LONG TSPIAPI TSPI_lineGetAddressStatus (
HDRVLINE hdLine,
DWORD dwAddressID,
LPLINEADDRESSSTATUS lpAddressStatus)
{
DebugMsg (("Entering TSPI_lineGetAddressStatus"));
if (dwAddressID)
return LINEERR_INVALADDRESSID;
lpAddressStatus->dwUsedSize =
lpAddressStatus->dwNeededSize = sizeof (LINEADDRESSSTATUS);
// if we are idle a call can be made
if (line.callState == 0) // our internal flag that line is not in use
lpAddressStatus->dwAddressFeatures = LINEADDRFEATURE_MAKECALL;
else
{
lpAddressStatus->dwNumInUse = 1;
lpAddressStatus->dwNumActiveCalls = 1;
}
return 0;
}
LONG TSPIAPI TSPI_lineGetCallAddressID (
HDRVCALL hdCall,
LPDWORD lpdwAddressID)
{
DebugMsg (("Entering TSPI_lineGetCallAddressID"));
if (hdCall != (HDRVCALL) line.htCall)
return LINEERR_INVALCALLHANDLE;
// There is but a single address where a call may exist.
*lpdwAddressID = 0;
return 0;
}
LONG TSPIAPI TSPI_lineGetCallInfo (
HDRVCALL hdCall,
LPLINECALLINFO lpCallInfo)
{
int cbDestAddr = lstrlen (line.DestAddress) + 1;
DebugMsg (("Entering TSPI_lineGetCallInfo"));
if (hdCall != (HDRVCALL) line.htCall)
return LINEERR_INVALCALLHANDLE;
lpCallInfo->dwUsedSize = sizeof (LINECALLINFO);
lpCallInfo->dwNeededSize = sizeof (LINECALLINFO) + cbDestAddr;
if (lpCallInfo->dwTotalSize >= lpCallInfo->dwNeededSize)
{
CopyMemory((char *) lpCallInfo + sizeof (LINECALLINFO),
line.DestAddress, cbDestAddr);
lpCallInfo->dwDisplayableAddressSize = cbDestAddr;
lpCallInfo->dwDisplayableAddressOffset = sizeof (LINECALLINFO);
lpCallInfo->dwUsedSize = lpCallInfo->dwNeededSize;
}
lpCallInfo->dwLineDeviceID = line.lineID;
lpCallInfo->dwBearerMode = LINEBEARERMODE_VOICE;
lpCallInfo->dwMediaMode = line.dwMediaMode;
lpCallInfo->dwAppSpecific = line.dwAppSpecific;
lpCallInfo->dwCallParamFlags = LINECALLPARAMFLAGS_IDLE |
LINECALLPARAMFLAGS_BLOCKID;
lpCallInfo->dwCallStates = LINECALLSTATE_IDLE |
LINECALLSTATE_CONNECTED;
lpCallInfo->dwOrigin = LINECALLORIGIN_OUTBOUND;
lpCallInfo->dwReason = LINECALLREASON_UNAVAIL;
lpCallInfo->dwCallerIDFlags = LINECALLPARTYID_UNAVAIL;
lpCallInfo->dwCalledIDFlags = LINECALLPARTYID_UNAVAIL;
lpCallInfo->dwConnectedIDFlags = LINECALLPARTYID_UNAVAIL;
lpCallInfo->dwRedirectionIDFlags = LINECALLPARTYID_UNAVAIL;
lpCallInfo->dwRedirectingIDFlags = LINECALLPARTYID_UNAVAIL;
return 0;
}
LONG TSPIAPI TSPI_lineGetCallStatus (
HDRVCALL hdCall,
LPLINECALLSTATUS lpCallStatus)
{
DebugMsg (("Entering TSPI_lineGetCallStatus"));
if (hdCall != (HDRVCALL) line.htCall)
return LINEERR_INVALCALLHANDLE;
lpCallStatus->dwCallState = line.callState;
if (line.callState == LINECALLSTATE_CONNECTED)
lpCallStatus->dwCallFeatures = LINECALLFEATURE_DROP;
return 0;
}
LONG TSPIAPI TSPI_lineGetDevCaps (
DWORD dwDeviceID,
DWORD dwTSPIVersion,
DWORD dwExtVersion,
LPLINEDEVCAPS lpLineDevCaps)
{
int cbname = lstrlen (line.linename) + 1;
int cbinfo = lstrlen (gszProviderInfo) + 1;
DebugMsg (("Entering TSPI_lineGetDevCaps"));
if (dwDeviceID != line.lineID)
return LINEERR_BADDEVICEID;
lpLineDevCaps->dwUsedSize = sizeof (LINEDEVCAPS);
lpLineDevCaps->dwNeededSize = sizeof (LINEDEVCAPS) + cbinfo + cbname;
if (lpLineDevCaps->dwTotalSize >= lpLineDevCaps->dwUsedSize + cbinfo)
{
// Copy in the provider info
CopyMemory ((char *)lpLineDevCaps + lpLineDevCaps->dwUsedSize,
gszProviderInfo, cbinfo);
lpLineDevCaps->dwProviderInfoSize = cbinfo;
lpLineDevCaps->dwProviderInfoOffset = lpLineDevCaps->dwUsedSize;
lpLineDevCaps->dwUsedSize += cbinfo;
}
if (lpLineDevCaps->dwTotalSize >= lpLineDevCaps->dwUsedSize + cbname)
{
// Copy in the line name
CopyMemory((char *) lpLineDevCaps + lpLineDevCaps->dwUsedSize,
line.linename, cbname);
lpLineDevCaps->dwLineNameSize = cbname;
lpLineDevCaps->dwLineNameOffset = lpLineDevCaps->dwUsedSize;
lpLineDevCaps->dwUsedSize += cbname;
}
lpLineDevCaps->dwPermanentLineID = (line.dwppID << 16) + 0;
// TAPI.DLL fills in APIVersion and ExtVersion.
lpLineDevCaps->dwNumAddresses = 1;
lpLineDevCaps->dwMaxNumActiveCalls = 1;
lpLineDevCaps->dwStringFormat = STRINGFORMAT_ASCII;
lpLineDevCaps->dwBearerModes = LINEBEARERMODE_VOICE;
lpLineDevCaps->dwMediaModes = LINEMEDIAMODE_INTERACTIVEVOICE;
return 0;
}
LONG TSPIAPI TSPI_lineGetID (
HDRVLINE hdLine,
DWORD dwAddressID,
HDRVCALL hdCall,
DWORD dwSelect,
LPVARSTRING lpDeviceID,
LPCSTR lpszDeviceClass,
HANDLE hHandle)
{
DebugMsg (("Entering TSPI_lineGetID"));
// Since we have only one device, we don't have to
// check the location of the line, address, or call.
if (hdLine != (HDRVLINE) &line)
return LINEERR_INVALLINEHANDLE;
if (lstrcmp (lpszDeviceClass, "tapi/line") == 0)
{
lpDeviceID->dwNeededSize = sizeof (VARSTRING) + sizeof (DWORD);
if (lpDeviceID->dwTotalSize >= lpDeviceID->dwNeededSize)
{
lpDeviceID->dwUsedSize = lpDeviceID->dwNeededSize;
lpDeviceID->dwStringFormat = STRINGFORMAT_BINARY;
lpDeviceID->dwStringSize = sizeof (DWORD);
lpDeviceID->dwStringOffset = sizeof (VARSTRING);
*((DWORD *) ((char *) lpDeviceID + sizeof (VARSTRING))) =
line.lineID;
}
return 0;
}
#ifdef COMMSUPPORT
if (lstrcmp (lpszDeviceClass, "comm") == 0)
{
int cbport = lstrlen (line.port) + 1;
lpDeviceID->dwNeededSize = sizeof (VARSTRING) + cbport;
if (lpDeviceID->dwTotalSize >= lpDeviceID->dwNeededSize)
{
lpDeviceID->dwUsedSize = lpDeviceID->dwNeededSize;
lpDeviceID->dwStringFormat = STRINGFORMAT_ASCII;
lpDeviceID->dwStringSize = cbport;
lpDeviceID->dwStringOffset = sizeof (VARSTRING);
CopyMemory ((char *) lpDeviceID + sizeof (VARSTRING),
line.port, cbport);
}
return 0;
}
#endif
return LINEERR_NODEVICE;
}
LONG TSPIAPI TSPI_lineGetLineDevStatus (
HDRVLINE hdLine,
LPLINEDEVSTATUS lpLineDevStatus)
{
DebugMsg (("Entering TSPI_lineGetLineDevStatus"));
if (hdLine != (HDRVLINE) &line)
return LINEERR_INVALLINEHANDLE;
lpLineDevStatus->dwUsedSize =
lpLineDevStatus->dwNeededSize = sizeof (LINEDEVSTATUS);
lpLineDevStatus->dwOpenMediaModes = line.dwLineMediaModes;
lpLineDevStatus->dwRoamMode = LINEROAMMODE_UNAVAIL;
if (line.callState == 0)
{
lpLineDevStatus->dwNumActiveCalls = 0;
lpLineDevStatus->dwLineFeatures = LINEFEATURE_MAKECALL;
}
else
{
lpLineDevStatus->dwNumActiveCalls = 1;
lpLineDevStatus->dwDevStatusFlags = LINEDEVSTATUSFLAGS_CONNECTED |
LINEDEVSTATUSFLAGS_INSERVICE;
}
return 0;
}
LONG TSPIAPI TSPI_lineGetNumAddressIDs (
HDRVLINE hdLine,
LPDWORD lpNumAddressIDs)
{
DebugMsg (("Entering TSPI_lineGetNumAddressIDs"));
if (hdLine != (HDRVLINE) &line)
return LINEERR_INVALLINEHANDLE;
*lpNumAddressIDs = 1; // We only support one address
return 0;
}
LONG TSPIAPI TSPI_lineMakeCall (
DRV_REQUESTID dwRequestID,
HDRVLINE hdLine,
HTAPICALL htCall,
LPHDRVCALL lphdCall,
LPCSTR lpszDestAddress,
DWORD dwCountryCode,
LPLINECALLPARAMS const lpCallParams)
{
DebugMsg (("Entering TSPI_lineMakeCall"));
#ifdef TESTING
LogDestAddress(lpszDestAddress);
#endif
if (lpszDestAddress &&
lstrlen (lpszDestAddress) > TAPIMAXDESTADDRESSSIZE)
return LINEERR_INVALPOINTER;
if (line.callState != 0)
return LINEERR_RESOURCEUNAVAIL;
if (lpCallParams)
{
if (lpCallParams->dwCallParamFlags &
~(LINECALLPARAMFLAGS_IDLE | LINECALLPARAMFLAGS_BLOCKID))
return LINEERR_INVALCALLPARAMS;
}
// fill in fields of the call record
line.htCall = htCall; // we have no hdcall of our own
*lphdCall = (HDRVCALL) htCall;
if (lpszDestAddress)
lstrcpy (line.DestAddress, lpszDestAddress);
else
line.DestAddress[0] = 0;
return appCall (msgMakeCall, line.DestAddress, dwRequestID);
}
long appCall (int msg, char *str, long dwRequestID)
{
#ifndef TESTING
long wait;
#endif
if (msg == msgMakeCall)
{
#ifdef TESTING
line.hcd = 1;
#else
line.hcd = SerialOpenComms (line.port, "9600");
#endif
if (line.hcd < 0)
return LINEERR_RESOURCEUNAVAIL;
else
{
char dial[255];
wsprintf (dial, "ATMH9D%s;\r", str);
#ifdef TESTING
DebugMsg (("Sent: %s", dial));
PostMessage(HWND_BROADCAST, WM_USER + 945, 0, 0);
line.callState = LINECALLSTATE_CONNECTED;
line.lpfnCompletion (dwRequestID, 0);
line.lpfnEventProc (line.htLine, line.htCall, LINE_CALLSTATE,
LINECALLSTATE_CONNECTED, 0, 0);
#else
if (WriteComm (line.hcd, dial, lstrlen (dial)) > 0)
{
DebugMsg (("Sent: %s", dial));
line.callState = LINECALLSTATE_CONNECTED;
line.lpfnCompletion (dwRequestID, 0);
line.lpfnEventProc (line.htLine, line.htCall, LINE_CALLSTATE,
LINECALLSTATE_CONNECTED, 0, 0);
}
else
{
DebugMsg (("failed to write string"));
return GetCommError (line.hcd, NULL);
}
#endif /* TESTING */
}
}
else // must be linedrop
{
if (line.hcd < 0)
DebugMsg (("idle"));
else
{
#ifndef TESTING
wait = GetTickCount();
WriteComm (line.hcd, "\r", 1);
while (GetTickCount() - wait < 250);
if (WriteComm (line.hcd, "ATH8\r", 6) > 0)
DebugMsg (("Sent: %s", str));
else
DebugMsg (("failed to hang up"));
wait = GetTickCount();
while (GetTickCount() - wait < 250);
EscapeCommFunction (line.hcd, CLRDTR); // drop DTR
if (CloseComm (line.hcd))
DebugMsg (("Couldn't close the serial port"));
#endif /* TESTING */
line.hcd = -1;
line.callState = LINECALLSTATE_IDLE;
line.lpfnEventProc (line.htLine, line.htCall, LINE_CALLSTATE,
LINECALLSTATE_IDLE, 0, 0);
}
if (dwRequestID)
line.lpfnCompletion (dwRequestID, 0);
}
return dwRequestID;
}
LONG TSPIAPI TSPI_lineOpen (
DWORD dwDeviceID,
HTAPILINE htLine,
LPHDRVLINE lphdLine,
DWORD dwTSPIVersion,
LINEEVENT lpfnEventProc)
{
DebugMsg (("Entering TSPI_lineOpen"));
if (dwDeviceID != line.lineID)
return LINEERR_BADDEVICEID;
// Since we only support outgoing calls, we
// don't open the serial port until we need to make a call
line.lpfnEventProc = lpfnEventProc;
line.htLine = htLine;
*lphdLine = (HDRVLINE) &line;
return 0;
}
LONG TSPIAPI TSPI_lineSetAppSpecific (
HDRVCALL hdCall,
DWORD dwAppSpecific)
{
DebugMsg (("Entering TSPI_lineSetAppSpecific"));
if (hdCall != (HDRVCALL) line.htCall)
return LINEERR_INVALCALLHANDLE;
line.dwAppSpecific = dwAppSpecific;
line.lpfnEventProc (line.htLine, line.htCall, LINE_CALLINFO,
LINECALLINFOSTATE_APPSPECIFIC, 0, 0);
return 0;
}
LONG TSPIAPI TSPI_lineConditionalMediaDetection (
HDRVLINE hdLine,
DWORD dwMediaModes,
LPLINECALLPARAMS const lpCallParams)
{
DebugMsg (("Entering TSPI_lineConditionalMediaDetection"));
if (hdLine != (HDRVLINE) &line)
return LINEERR_INVALLINEHANDLE;
if (dwMediaModes != LINEMEDIAMODE_INTERACTIVEVOICE)
return LINEERR_INVALMEDIAMODE;
return 0;
}
LONG TSPIAPI TSPI_lineSetDefaultMediaDetection (
HDRVLINE hdLine,
DWORD dwMediaModes)
{
DebugMsg (("Entering TSPI_lineSetDefaultMediaDetection"));
if (hdLine != (HDRVLINE) &line)
return LINEERR_INVALLINEHANDLE;
if (dwMediaModes && dwMediaModes != LINEMEDIAMODE_INTERACTIVEVOICE)
return LINEERR_INVALMEDIAMODE;
line.dwLineMediaModes = dwMediaModes;
return 0;
}
LONG TSPIAPI TSPI_lineSetMediaMode (
HDRVCALL hdCall,
DWORD dwMediaMode)
{
DebugMsg (("Entering TSPI_lineSetMediaMode"));
if (hdCall != (HDRVCALL) line.htCall)
return LINEERR_INVALCALLHANDLE;
if (dwMediaMode != LINEMEDIAMODE_INTERACTIVEVOICE)
return LINEERR_INVALMEDIAMODE;
line.dwMediaMode = dwMediaMode;
return 0;
}
///////////////////////////////////////////////////////////
// The configuration trio
///////////////////////////////////////////////////////////
// These routines are called from the control panel applet
// TAPI may not be running at this point, so one cannot assume
// we have been initialised
LONG TSPIAPI TSPI_providerConfig (HWND hwnd, DWORD dwPermanentProviderId)
{
DebugMsg (("Entering TSPI_providerConfig"));
if (!initialised)
LoadIniStrings (dwPermanentProviderId);
else if (dwPermanentProviderId != line.dwppID)
return LINEERR_NOMULTIPLEINSTANCE;
#ifndef TESTING
DialogBox (hInst, MAKEINTRESOURCE (IDD_CFGDLG), hwnd, ConfigDlgProc);
#endif
return 0;
}
LONG TSPIAPI TSPI_providerInstall (HWND hwnd, DWORD dwPermanentProviderId)
{
int res;
char szProvider[sizeof (s_providerx) + 5]; // room for 65535
DebugMsg (("Entering TSPI_providerInstall"));
if (!initialised)
LoadIniStrings (dwPermanentProviderId);
else if (dwPermanentProviderId != line.dwppID)
{
res = ID_MULTIPLE_INST;
goto error;
}
wsprintf (szProvider, s_providerx, (int) dwPermanentProviderId);
// we support 1 line and 0 phones
WritePrivateProfileString (szProvider, s_numlines, s_one, s_telephon_ini);
WritePrivateProfileString (szProvider, s_numphones, s_zero, s_telephon_ini);
// Flush the ini file cache.
WritePrivateProfileString (0, 0, 0, s_telephon_ini);
#ifndef TESTING
// display the config screen
if (DialogBox (hInst, MAKEINTRESOURCE (IDD_CFGDLG),
hwnd, ConfigDlgProc) == 0)
return 0;
else
return LINEERR_OPERATIONFAILED;
#else
return 0;
#endif
error:
{
char szerr[255];
char title[255];
LoadString (hInst, res, szerr, sizeof (szerr));
LoadString (hInst, ID_ATSP_ERROR, title, sizeof (title));
MessageBox (hwnd, szerr, title, MB_APPLMODAL | MB_ICONEXCLAMATION);
return LINEERR_OPERATIONFAILED;
}
}
LONG TSPIAPI TSPI_providerRemove (HWND hwnd, DWORD dwPermanentProviderId)
{
DebugMsg (("Entering TSPI_providerRemove"));
// The control panel removes all of our junk for us
// (and then some) when the provider is removed.
return 0;
}
///////////////////////////////////////////////////////////
// Internal support routines
///////////////////////////////////////////////////////////
void LoadIniStrings (DWORD ppID)
{
char section[sizeof (s_providerx) + 5]; // room for 65535
wsprintf (section, s_providerx, (int) ppID);
line.dwppID = ppID;
#ifdef TESTING
lstrcpy(line.port, "COM1");
lstrcpy(line.linename, "Testing SP");
lstrcpy(line.lineaddr, "");
#else
// user preferences come from the telephon.ini file
GetPrivateProfileString (section, s_port, "COM1", line.port,
sizeof (line.port), s_telephon_ini);
GetPrivateProfileString (section, s_linename, "", line.linename,
sizeof (line.linename), s_telephon_ini);
GetPrivateProfileString (section, s_lineaddr, "", line.lineaddr,
sizeof (line.lineaddr), s_telephon_ini);
#endif /* TESTING */
// the provider info string comes from the resource file
gszProviderInfo[0] = 0; // in case loadstring fails
LoadString (hInst, ID_PROVIDER_INFO, gszProviderInfo, sizeof (gszProviderInfo));
return;
}
BOOL CALLBACK
ConfigDlgProc (HWND hDlg, UINT uiMsg, WPARAM wParam, LPARAM lParam)
{
int CurrSel;
switch (uiMsg)
{
case WM_INITDIALOG:
{
for (CurrSel = 0; CurrSel < NUMPORTS; CurrSel++)
{
// List the port in the combo box.
SendDlgItemMessage (hDlg, ID_PORT, CB_ADDSTRING,
0, (LPARAM) ((LPSTR) lpszCommDevArray[CurrSel]));
}
CurrSel = (int) SendDlgItemMessage (hDlg, ID_PORT, CB_FINDSTRING,
0, (LPARAM) (LPSTR) line.port);
SendDlgItemMessage (hDlg, ID_PORT, CB_SETCURSEL, CurrSel, 0);
SendDlgItemMessage (hDlg, ID_LINENAME, WM_SETTEXT, 0,
(LPARAM) (LPSTR) line.linename);
SendDlgItemMessage (hDlg, ID_LINEADDR, WM_SETTEXT, 0,
(LPARAM) (LPSTR) line.lineaddr);
}
break;
case WM_COMMAND:
{
switch (wParam)
{
case IDOK:
{
char szp[sizeof (s_providerx) + 5]; // room for 65535
wsprintf (szp, s_providerx, (int) line.dwppID);
// Port
CurrSel = (int) SendDlgItemMessage (hDlg, ID_PORT,
CB_GETCURSEL, 0, 0);
SendDlgItemMessage (hDlg, ID_PORT, CB_GETLBTEXT, CurrSel,
(LPARAM) (LPSTR) line.port);
WritePrivateProfileString (szp, s_port, line.port, s_telephon_ini);
// Line Name
SendDlgItemMessage (hDlg, ID_LINENAME, WM_GETTEXT,
sizeof (line.linename), (LPARAM) (LPSTR) line.linename);
WritePrivateProfileString (szp, s_linename, line.linename,
s_telephon_ini);
// Line Address
SendDlgItemMessage (hDlg, ID_LINEADDR, WM_GETTEXT,
sizeof (line.lineaddr), (LPARAM) (LPSTR) line.lineaddr);
WritePrivateProfileString (szp, s_lineaddr, line.lineaddr,
s_telephon_ini);
// Flush the ini file cache
WritePrivateProfileString (0, 0, 0, s_telephon_ini);
EndDialog (hDlg, 0);
}
break;
case IDCANCEL:
EndDialog (hDlg, -1);
break;
}
}
break;
default:
return FALSE;
}
return TRUE;
}
#ifdef DEBUG
void CDECL SPTrace(LPCSTR pszFormat, ...)
{
static char szBuffer[512];
static char fmtBuffer[1024];
static char szModuleBuffer[_MAX_PATH];
static char szTemp[_MAX_PATH];
static char szFName[_MAX_FNAME];
const char* pszLocalFormat;
int nBuf, count, localCount;
va_list args;
pszLocalFormat = pszFormat;
va_start (args, pszFormat);
nBuf = wvsprintf (szBuffer, pszLocalFormat, args);
// Convert formatting to readable format.
for (count = 0, localCount = 0; count < nBuf; count++, localCount++)
{
if (szBuffer[count] == '\r')
{
fmtBuffer[localCount++] = '\\';
fmtBuffer[localCount] = 'r';
}
else if (szBuffer[count] == '\n')
{
fmtBuffer[localCount++] = '\\';
fmtBuffer[localCount] = 'n';
}
else
fmtBuffer[localCount] = szBuffer[count];
}
fmtBuffer[localCount] = '\0';
GetModuleFileName (hInst, szModuleBuffer, sizeof (szModuleBuffer));
_splitpath (szModuleBuffer, szTemp, szTemp, szFName, szTemp);
wsprintf (szBuffer, "%s: %s\n\r", (LPSTR) szFName, (LPSTR) fmtBuffer);
OutputDebugString (szBuffer);
}
#endif
UINT myatoi (LPSTR speed)
{
UINT i;
for (i = 0; *speed; speed++)
i = i * 10 + (*speed - '0');
return i;
}
#define TXQUEUE 512
#define RXQUEUE 512
int SerialOpenComms (LPSTR port, LPSTR speed)
{
#if 0
BJM-09/06/95
BJM-09/06/95
BJM-09/06/95
int hcd = OpenComm (port, RXQUEUE, TXQUEUE);
if (hcd >= 0)
{
DCB dcb;
if (GetCommState (hcd, &dcb) == 0)
{
ZeroMemory (&dcb.BaudRate, sizeof (DCB) - sizeof (dcb.Id));
dcb.BaudRate = myatoi (speed);
dcb.ByteSize = 8;
dcb.fBinary = TRUE;
// dcb.fChEvt = TRUE;
dcb.XonChar = 17;
dcb.XoffChar = 19;
// dcb.EvtChar = '\n';
if (SetCommState (&dcb) == 0)
{
DebugMsg (("Opened: %s:%s", port, speed));
return hcd;
}
}
CloseComm (hcd);
}
DebugMsg (("***Comm port failed to open"));
return -1;
BJM-09/06/95
BJM-09/06/95
#endif
}
#ifdef TESTING
//
// report last dialable address sent in to SP
//
static char gszLastDestAddress[256];
static BOOL gbLastAddressValid = 0;
void FAR PASCAL LogDestAddress(LPCSTR szDestAddress)
{
if (gbLastAddressValid == 0)
{
strncpy(gszLastDestAddress, szDestAddress, sizeof(gszLastDestAddress)-1);
gszLastDestAddress[sizeof(gszLastDestAddress)-1] = 0;
gbLastAddressValid = 1;
}
}
void FAR PASCAL GetLastDestAddress (LPSTR szLastAddrBuffer, int cb)
{
if ((szLastAddrBuffer != NULL) && (cb > 0))
{
strncpy(szLastAddrBuffer, gszLastDestAddress, cb-1);
szLastAddrBuffer[cb-1] = 0;
gbLastAddressValid = 0;
}
}
void FAR PASCAL ClearLastDestAddressBuffer()
{
gbLastAddressValid = 0;
gszLastDestAddress[0] = 0;
}
#endif /* TESTING */