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.
 
 
 
 
 
 

1594 lines
33 KiB

/*++ BUILD Version: 0000 // Increment this if a change has global effects
Copyright (c) 1995 Microsoft Corporation
Module Name:
pdisp.c
Abstract:
Author:
??? dd-Mmm-1995
Revision History:
--*/
#include <windows.h>
#include <memory.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include "pdisp.h"
BOOL CALLBACK __export ConfigDlgProc(HWND, UINT, WPARAM, LPARAM);
HANDLE 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";
HANDLE hInst = NULL;
ATSPLineData line;
char gszProviderInfo[255];
long
appCall(
int msg,
char *str,
long dwRequestID
);
long
lineDropCore(
ATSPLineData *theLine,
DWORD dwRequestID
);
#ifdef WIN32
BOOL
WINAPI
_CRT_INIT(
HINSTANCE hDLL,
DWORD dwReason,
LPVOID lpReserved
);
BOOL
WINAPI
DllMain(
HANDLE hDLL,
DWORD dwReason,
LPVOID lpReserved
)
{
if (!_CRT_INIT (hInst, dwReason, lpReserved))
{
OutputDebugString ("PDISP32: DllMain: _CRT_INIT() failed\n\r");
}
switch (dwReason)
{
case DLL_PROCESS_ATTACH:
hInst = hDLL;
break;
case DLL_PROCESS_DETACH:
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
break;
}
return TRUE;
}
#else
int
FAR
PASCAL
LibMain(
HANDLE hInstance,
WORD wDataSegment,
WORD wHeapSize,
LPSTR lpszCmdLine
)
{
if (hInst != NULL)
return FALSE;
hInst = hInstance;
return TRUE;
}
VOID
FAR
PASCAL
__export
WEP(
int bSystemExit
)
{
hInst = NULL;
}
#endif // WIN32
static BOOL initialised = FALSE;
//
// -------------------------- TSPI_lineXxx funcs ------------------------------
//
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;
}
/* BUGBUG needs to use new TUISPI stuff
LONG
TSPIAPI
TSPI_lineConfigDialog(
DWORD dwDeviceID,
HWND hwndOwner,
LPCSTR lpszDeviceClass
)
{
DebugMsg (("Entering TSPI_lineConfigDialog"));
if (dwDeviceID != line.lineID)
{
return LINEERR_BADDEVICEID;
}
DialogBox (hInst, MAKEINTRESOURCE (IDD_CFGDLG), hwndOwner, ConfigDlgProc);
return 0;
}
*/
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 = strlen (line.lineaddr) + 1;
lpAddressCaps->dwNeededSize = sizeof (LINEADDRESSCAPS) + cbLineAddr;
if (lpAddressCaps->dwTotalSize < lpAddressCaps->dwNeededSize)
{
lpAddressCaps->dwUsedSize = sizeof (LINEADDRESSCAPS);
}
else
{
memcpy(
(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 (strcmp (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 = strlen (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)
{
memcpy(
(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 = strlen (line.linename) + 1;
int cbinfo = strlen (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
memcpy(
(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
memcpy(
(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 hTargetProcess
)
{
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 (strcmp (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 (strcmp (lpszDeviceClass, "comm") == 0)
{
int cbport = strlen (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);
memcpy(
(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"));
if (lpszDestAddress &&
(strlen (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)
{
strcpy (line.DestAddress, lpszDestAddress);
}
else
{
line.DestAddress[0] = 0;
}
return appCall (msgMakeCall, line.DestAddress, dwRequestID);
}
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 !
// we support only one line
if (dwDeviceID == INITIALIZE_NEGOTIATION || dwDeviceID == line.lineID)
{
*lpdwTSPIVersion = 0x00010003;
if (dwLowVersion > 0x00010003 || // the app is too new for us
dwHighVersion < 0x00010003) // 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_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_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;
}
//
// ------------------------- TSPI_providerXxx funcs ---------------------------
//
LONG
TSPIAPI
TSPI_providerConfig(
HWND hwnd,
DWORD dwPermanentProviderId
)
{
DebugMsg (("Entering TSPI_providerConfig"));
if (!initialised)
{
LoadIniStrings (dwPermanentProviderId);
}
else if (dwPermanentProviderId != line.dwppID)
{
return LINEERR_NOMULTIPLEINSTANCE;
}
DialogBox (hInst, MAKEINTRESOURCE (IDD_CFGDLG), hwnd, ConfigDlgProc);
return 0;
}
LONG
TSPIAPI
TSPI_providerInit(
DWORD dwTSPIVersion,
DWORD dwPermanentProviderID,
DWORD dwLineDeviceIDBase,
DWORD dwPhoneDeviceIDBase,
DWORD dwNumLines,
DWORD dwNumPhones,
ASYNC_COMPLETION lpfnCompletionProc,
LPDWORD lpdwTSPIOptions
)
{
DebugMsg (("Entering TSPI_providerInit"));
// assert (dwTSPIVersion == ATSP_VERSION);
// assert (dwNumLines == 1);
// assert (dwNumPhones == 0);
if (initialised)
{
return LINEERR_NOMULTIPLEINSTANCE;
}
// initialise our internal structures
memset (&line, 0, sizeof (ATSPLineData));
line.lpfnCompletion = lpfnCompletionProc;
line.lineID = dwLineDeviceIDBase;
line.dwMediaMode = LINEMEDIAMODE_INTERACTIVEVOICE;
line.hcd = INVALID_HANDLE_VALUE;
LoadIniStrings (dwPermanentProviderID);
initialised = TRUE;
*lpdwTSPIOptions = LINETSPIOPTION_NONREENTRANT;
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);
//
// display the config dlg
//
if (DialogBox (hInst, MAKEINTRESOURCE (IDD_CFGDLG), hwnd, ConfigDlgProc)
== 0)
{
return 0;
}
else
{
return LINEERR_OPERATIONFAILED;
}
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"));
// BUGBUG: need to nuke the ProviderN section
return 0;
}
LONG
TSPIAPI
TSPI_providerShutdown(
DWORD dwTSPIVersion,
DWORD dwPermanentProviderID
)
{
DebugMsg (("Entering TSPI_providerShutdown"));
initialised = FALSE;
return 0;
}
//
// ------------------------ Private support routines --------------------------
//
void
LoadIniStrings(
DWORD ppID
)
{
char section[sizeof (s_providerx) + 5]; // room for 65535
wsprintf (section, s_providerx, (int) ppID);
line.dwppID = ppID;
// 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
);
// 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
__export
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;
} // switch
return TRUE;
}
#if DBG
void
CDECL
SPTrace(
LPCSTR lpszFormat,
...
)
{
#ifdef WIN32
char buf[128] = "PDISP32: ";
#else
char buf[128] = "PDISP: ";
#endif
va_list ap;
va_start(ap, lpszFormat);
#ifdef WIN32
wvsprintf (&buf[9], lpszFormat, ap);
#else
wvsprintf (&buf[7], lpszFormat, ap);
#endif
strcat (buf, "\n");
OutputDebugString (buf);
va_end(ap);
}
#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
HANDLE
SerialOpenComms(
LPSTR port,
LPSTR speed
)
{
#ifdef WIN32
HANDLE hcd = CreateFile(
port,
GENERIC_READ | GENERIC_WRITE,
0, // no sharing
NULL, // no security attrs
OPEN_EXISTING,
0, // no attrs/flags
NULL // no template file
);
if (hcd == INVALID_HANDLE_VALUE)
{
DebugMsg (("CreateFile(%s) failed, err=%ld", port, GetLastError()));
}
#else
int hcd = OpenComm (port, RXQUEUE, TXQUEUE);
#endif
if (hcd >= 0)
{
DCB dcb;
#ifdef WIN32
if (GetCommState (hcd, &dcb))
#else
if (GetCommState (hcd, &dcb) == 0)
#endif
{
memset (&dcb.BaudRate, 0, sizeof (DCB) - sizeof (dcb.DCBlength));
dcb.BaudRate = myatoi (speed);
dcb.ByteSize = 8;
dcb.fBinary = TRUE;
// dcb.fChEvt = TRUE;
dcb.XonChar = 17;
dcb.XoffChar = 19;
// dcb.EvtChar = '\n';
if (SetCommState (hcd, &dcb))
{
DebugMsg (("Opened: %s:%s", port, speed));
return hcd;
}
}
#ifdef WIN32
CloseHandle (hcd);
#else
CloseComm (hcd);
DebugMsg (("***Comm port failed to open"));
#endif
}
return INVALID_HANDLE_VALUE;
}
long
appCall(
int msg,
char *str,
long dwRequestID
)
{
long wait;
#ifdef WIN32
DWORD dwBytesWritten;
#endif
if (msg == msgMakeCall)
{
line.hcd = SerialOpenComms (line.port, "9600");
if (line.hcd == INVALID_HANDLE_VALUE)
{
return LINEERR_RESOURCEUNAVAIL;
}
else
{
char dial[255];
wsprintf (dial, "ATMH9D%s;\r", str);
#ifdef WIN32
if (WriteFile(
line.hcd,
dial,
strlen (dial),
&dwBytesWritten,
NULL
))
#else
if (WriteComm (line.hcd, dial, strlen (dial)) > 0)
#endif
{
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"));
#ifdef WIN32
return -1; // BUGBUG
#else
return GetCommError (line.hcd, NULL);
#endif
}
}
}
else // must be linedrop
{
if (line.hcd == INVALID_HANDLE_VALUE)
{
DebugMsg (("idle"));
}
else
{
wait = GetTickCount();
#ifdef WIN32
WriteFile (line.hcd, "\r", 1, &dwBytesWritten, NULL);
#else
WriteComm (line.hcd, "\r", 1);
#endif
while (GetTickCount() - wait < 250);
#ifdef WIN32
if (WriteFile (line.hcd, "ATH8\r", 6, &dwBytesWritten, NULL))
#else
if (WriteComm (line.hcd, "ATH8\r", 6) > 0)
#endif
{
DebugMsg (("Sent: %s", str));
}
else
{
DebugMsg (("failed to hang up"));
}
wait = GetTickCount();
while (GetTickCount() - wait < 250);
EscapeCommFunction (line.hcd, CLRDTR); // drop DTR
#ifdef WIN32
if (!CloseHandle (line.hcd))
#else
if (CloseComm (line.hcd))
#endif
{
DebugMsg (("Couldn't close the serial port"));
}
line.hcd = INVALID_HANDLE_VALUE;
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
lineDropCore(
ATSPLineData *theLine,
DWORD dwRequestID
)
{
// if the call is not idle, transition to idle and close the comms port
return appCall (msgDrop, 0, dwRequestID);
}