home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
HomeWare 14
/
HOMEWARE14.bin
/
windows
/
win31
/
atvsp.arj
/
ATVSP.C
< prev
next >
Wrap
C/C++ Source or Header
|
1994-03-10
|
50KB
|
1,524 lines
/******************************************************************************\
* This is a part of the Microsoft Source Code Samples.
* Copyright (C) 1993,1994 Microsoft Corporation.
* All rights reserved.
* This source code is only intended as a supplement to
* Microsoft Development Tools and/or WinHelp documentation.
\******************************************************************************/
/*
The Software provided is for your personal use only and may not be copied or distributed.
THE SOFTWARE IS PROVIDED TO YOU "AS IS" WITHOUT WARRANTY OF ANY KIND,
EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
PURPOSE. YOU ASSUME THE ENTIRE RISK AS TO THE ACCURACY AND THE USE
OF THE SOFTWARE. MICROSOFT SHALL NOT BE LIABLE FOR ANY DAMAGES
WHATSOEVER ARISING OUT OF THE USE OF OR INABILITY TO USE THE
SOFTWARE, EVEN IF MICROSOFT HAS BEEN ADVISED OF THE POSSIBILITY OF
SUCH DAMAGE.
*/
#include <windows.h>
#include <memory.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include "atvexe.h"
#include "atvsp.h"
#pragma warning (disable : 4100)
int FAR PASCAL ConfigDlgProc(HWND, UINT, WPARAM, LPARAM);
int FAR PASCAL LineConfDlgProc(HWND, UINT, WPARAM, LPARAM);
void LoadIniStrings (DWORD);
int SendModemCommand (int, const void *);
int GetModemReply(int, void *, int);
void fillDialParams (LPLINEDIALPARAMS, LPLINEDIALPARAMS);
long appCall (int msg, long param, long dwRequestID);
char *lpszCommDevArray[NUMPORTS] =
{ "COM1", "COM2", "COM3", "COM4" };
char *lpszCommSpeedArray[NUMSPEEDS] =
{ "300", "1200", "2400", "9600", "19200", "38400", "57600" };
char _based(_segname("ATVSP_TEXT")) ATV_CLASSNAME[] = "AtvspAppWinClass";
// 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_speed[] = "Speed";
char s_initstr[] = "InitString";
char s_ignore[] = "IgnoreInternalString";
char s_pulse[] = "PulseDial";
char s_linename[] = "LineName";
char s_lineaddr[] = "LineAddress";
#define MIN_DURATION 50
#define DEF_DURATION 95
#define MAX_DURATION 255
#define MIN_DIALSPEED 50
#define DEF_DIALSPEED 95
#define MAX_DIALSPEED 255
#define MIN_DIALTONE 1000
#define DEF_DIALTONE 60000
#define MAX_DIALTONE 255000
#define MIN_DIALPAUSE 0
#define DEF_DIALPAUSE 2000
#define MAX_DIALPAUSE 255000
// The global module handle
HANDLE hInst = NULL;
// Line object.
ATSPLineData line;
// Provider description string
char gszProviderInfo[PROVIDERINFOSIZE];
///////////////////////////////////////////////////////////
// The required DLL functions
///////////////////////////////////////////////////////////
int FAR PASCAL LibMain(HANDLE hInstance, WORD wDataSegment,
WORD wHeapSize, LPSTR lpszCmdLine)
{
// Under normal circumstances, this function is never called (or exported!)
DebugMsg(("Wow, this is weird! We are in LibMain!"));
if (hInst != NULL)
return FALSE;
hInst = hInstance;
return TRUE;
}
VOID FAR PASCAL __export WEP (int bSystemExit)
{
DebugMsg(("Yes, we are actually calling WEP!\r\n"));
hInst = NULL;
}
///////////////////////////////////////////////////////////
// The Service Provider Basic Configuration Routines
///////////////////////////////////////////////////////////
static appstartup = FALSE;
static atspexehwnd = 0;
#ifdef DEBUG
static BOOL initialised = FALSE;
#endif
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 !
#ifdef DEBUG
if (!initialised)
assert (dwDeviceID == INITIALIZE_NEGOTIATION);
#endif
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)
{
int res;
DebugMsg (("Entering TSPI_providerInit"));
assert (dwTSPIVersion == ATSP_VERSION);
assert (dwNumLines == 1);
assert (dwNumPhones == 0);
// launch our companion app to get an async thread
res = WinExec ("atvexe.exe", SW_SHOWMINIMIZED);
if (res <= HINSTANCE_ERROR)
{
DebugMsg (("App didn't start"));
return LINEERR_NODRIVER;
}
atspexehwnd = FindWindow(ATV_CLASSNAME,NULL);
if (atspexehwnd == NULL)
{
DebugMsg(("Failed to find the ATVEXE.EXE window"));
return FALSE;
}
else
DebugMsg(("The window handle is %ld",(LONG)atspexehwnd));
// initialise our internal structures
_fmemset (&line, 0, sizeof (ATSPLineData));
line.lpfnCompletion = lpfnCompletionProc;
line.lineID = dwLineDeviceIDBase;
line.dwMediaMode = LINEMEDIAMODE_INTERACTIVEVOICE;
line.callState = 0;
line.dpDialParams.dwDialPause = 2000;
line.dpDialParams.dwDialSpeed = DEF_DIALSPEED;
line.dpDialParams.dwDigitDuration = DEF_DURATION;
line.dpDialParams.dwWaitForDialtone = 60000;
line.bBusy = FALSE;
LoadIniStrings (dwPermanentProviderID);
#ifdef DEBUG
initialised = TRUE;
#endif
return 0;
}
LONG TSPIAPI TSPI_providerShutdown (DWORD dwTSPIVersion)
{
DebugMsg (("Entering TSPI_providerShutdown"));
// close our shadow app. We do it here as it registers with us
// and therefore our module count doesn't hit 0 so WEP isn't called
SendMessage (atspexehwnd, M_UNINSTALL, 0, 0);
atspexehwnd = 0;
return 0;
}
///////////////////////////////////////////////////////////
// The Line Specific Calls
///////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////
// NO CHANGES NEEDED!!!
///////////////////////////////////////////////////////////
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;
}
void lineDropCore (ATSPLineData *theLine)
{
// if the call is not idle, transition to idle and close the comms port
if (theLine->callState != LINECALLSTATE_IDLE &&
theLine->callState != 0)
{
// This is different from ATSP because ATVEXE handles the state transition for us.
{ ATSPLineData *myline = &line;
appCall (msgDrop, (long) myline, 0);
}
}
}
LONG TSPIAPI TSPI_lineCloseCall (HDRVCALL hdCall)
{
DebugMsg (("Entering TSPI_lineCloseCall"));
if (hdCall != (HDRVCALL) line.hdCall)
{
DebugMsg(("LINEERR_INVALCALLHANDLE"));
return LINEERR_INVALCALLHANDLE;
}
// call drop in case there is still an active call on the line
lineDropCore (&line);
line.callState = 0;
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 (_fstrcmp (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.hdCall)
return LINEERR_INVALCALLHANDLE;
// There is but a single address where a call may exist.
*lpdwAddressID = 0;
return 0;
}
LONG TSPIAPI TSPI_lineGetDevCaps (
DWORD dwDeviceID,
DWORD dwTSPIVersion,
DWORD dwExtVersion,
LPLINEDEVCAPS lpLineDevCaps)
{
int cbname = _fstrlen (line.linename) + 1;
int cbinfo = _fstrlen (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
_fmemcpy ((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
_fmemcpy((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 |
LINEMEDIAMODE_AUTOMATEDVOICE;
lpLineDevCaps->dwGenerateToneModes = LINETONEMODE_CUSTOM |
LINETONEMODE_BEEP;
lpLineDevCaps->dwGenerateToneMaxNumFreq = 2;
lpLineDevCaps->dwMonitorToneMaxNumFreq = 0;
lpLineDevCaps->dwMonitorDigitModes = LINEDIGITMODE_DTMF;
lpLineDevCaps->dwGenerateDigitModes = LINEDIGITMODE_PULSE | LINEDIGITMODE_DTMF;
lpLineDevCaps->dwRingModes = 1;
lpLineDevCaps->dwLineStates = LINEDEVSTATE_OTHER |
LINEDEVSTATE_RINGING |
LINEDEVSTATE_CONNECTED |
LINEDEVSTATE_DISCONNECTED |
LINEDEVSTATE_OPEN |
LINEDEVSTATE_CLOSE |
LINEDEVSTATE_NUMCALLS |
LINEDEVSTATE_REINIT;
lpLineDevCaps->MinDialParams.dwDialSpeed = MIN_DIALSPEED;
lpLineDevCaps->DefaultDialParams.dwDialSpeed = DEF_DIALSPEED;
lpLineDevCaps->MaxDialParams.dwDialSpeed = MAX_DIALSPEED;
lpLineDevCaps->MinDialParams.dwDigitDuration = MIN_DURATION;
lpLineDevCaps->DefaultDialParams.dwDigitDuration = DEF_DURATION;
lpLineDevCaps->MaxDialParams.dwDigitDuration = MAX_DURATION;
lpLineDevCaps->MinDialParams.dwWaitForDialtone = MIN_DIALTONE;
lpLineDevCaps->DefaultDialParams.dwWaitForDialtone = DEF_DIALTONE;
lpLineDevCaps->MaxDialParams.dwWaitForDialtone = MAX_DIALTONE;
lpLineDevCaps->MinDialParams.dwDialPause = MIN_DIALPAUSE;
lpLineDevCaps->DefaultDialParams.dwDialPause = DEF_DIALPAUSE;
lpLineDevCaps->MaxDialParams.dwDialPause = MAX_DIALPAUSE;
// we make an assumption in this sample code that a "stock"
// at modem will understand @ and W but not $ modifiers
lpLineDevCaps->dwDevCapFlags = LINEDEVCAPFLAGS_DIALQUIET |
LINEDEVCAPFLAGS_DIALDIALTONE;
return 0;
}
LONG TSPIAPI TSPI_lineGetID (
HDRVLINE hdLine,
DWORD dwAddressID,
HDRVCALL hdCall,
DWORD dwSelect,
LPVARSTRING lpDeviceID,
LPCSTR lpszDeviceClass)
{
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 (hdCall != (HDRVCALL) line.hdCall)
return LINEERR_INVALCALLHANDLE;
if (_fstrcmp (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;
}
if (_fstrcmp (lpszDeviceClass, "comm") == 0)
{
int cbport = _fstrlen (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);
_fmemcpy ((char *) lpDeviceID + sizeof (VARSTRING), line.port, cbport);
}
return 0;
}
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 CheckDestAddress (LPCSTR szAddr)
{
char ch;
int i;
for (i = 1; ch = *szAddr++; i++)
{
if (ch == '?')
return LINEERR_DIALPROMPT;
else if (ch == '$')
return LINEERR_DIALBILLING;
}
if (i > TAPIMAXDESTADDRESSSIZE)
return LINEERR_INVALPOINTER;
return 0;
}
LONG TSPIAPI TSPI_lineMakeCall (
DRV_REQUESTID dwRequestID,
HDRVLINE hdLine,
HTAPICALL htCall,
LPHDRVCALL lphdCall,
LPCSTR lpszDestAddress,
DWORD dwCountryCode,
LPLINECALLPARAMS const lpCallParams)
{
long res;
DebugMsg (("Entering TSPI_lineMakeCall"));
// check for invalid dial string (wierd chars or length)
if (lpszDestAddress && (res = CheckDestAddress (lpszDestAddress)))
return res;
if (line.callState != 0 && line.callState != LINECALLSTATE_IDLE)
return LINEERR_RESOURCEUNAVAIL;
if (lpCallParams)
{
if (lpCallParams->dwBearerMode != LINEBEARERMODE_VOICE)
return LINEERR_INVALBEARERMODE;
if (lpCallParams->dwMediaMode != LINEMEDIAMODE_INTERACTIVEVOICE)
return LINEERR_INVALMEDIAMODE;
if (lpCallParams->dwCallParamFlags &
!(LINECALLPARAMFLAGS_IDLE | LINECALLPARAMFLAGS_BLOCKID))
return LINEERR_INVALCALLPARAMS;
fillDialParams (&lpCallParams->DialParams, &line.dpDialParams);
}
// fill in fields of the call record
line.hdCall = (HDRVCALL)htCall; // We have no hdCall of our own, so we'll use TAPI's handle
line.htCall = htCall;
*lphdCall = (HDRVCALL) htCall;
if (lpszDestAddress != NULL)
_fstrcpy (line.DestAddress, lpszDestAddress);
else
line.DestAddress[0] = 0;
// finally, set off the async call in our companion app
{
ATSPLineData *myline = &line;
long res = appCall (msgMakeCall, (long) myline, dwRequestID);
if (res < 0)
return res;
else
return dwRequestID;
}
}
LONG TSPIAPI TSPI_lineSetAppSpecific (
HDRVCALL hdCall,
DWORD dwAppSpecific)
{
DebugMsg (("Entering TSPI_lineSetAppSpecific"));
if (hdCall != line.hdCall)
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) & (~LINEMEDIAMODE_AUTOMATEDVOICE)) )
{
DebugMsg(("Returning LINEERR_INVALMEDIAMODE"));
return LINEERR_INVALMEDIAMODE;
}
line.dwLineMediaModes = dwMediaModes;
return 0;
}
LONG TSPIAPI TSPI_lineSetMediaMode (
HDRVCALL hdCall,
DWORD dwMediaMode)
{
DebugMsg (("Entering TSPI_lineSetMediaMode"));
if (hdCall != (HDRVCALL) line.hdCall)
{
DebugMsg(("Invalid call handle"));
return LINEERR_INVALCALLHANDLE;
}
if (dwMediaMode && (dwMediaMode & (LINEMEDIAMODE_INTERACTIVEVOICE | LINEMEDIAMODE_AUTOMATEDVOICE) ) == 0 )
{
DebugMsg(("Invalid Media Mode"));
return LINEERR_INVALMEDIAMODE;
}
line.dwMediaMode = dwMediaMode;
return 0;
}
LONG TSPIAPI TSPI_lineSetStatusMessages (
HDRVLINE hdLine,
DWORD dwLineStates,
DWORD dwAddressStates)
{
DebugMsg (("Entering TSPI_lineSetStatusMessages"));
if (hdLine != (HDRVLINE) &line)
return LINEERR_INVALLINEHANDLE;
line.dwLineStates = dwLineStates;
line.dwAddressStates = dwAddressStates;
return 0;
}
///////////////////////////////////////////////////////////
// CHANGES NEEDED!!!
///////////////////////////////////////////////////////////
LONG TSPIAPI TSPI_lineDial (
DRV_REQUESTID dwRequestID,
HDRVCALL hdCall,
LPCSTR lpszDestAddress,
DWORD dwCountryCode)
{
LONG res;
DebugMsg (("Entering TSPI_lineDial"));
if (hdCall != (HDRVCALL) line.hdCall)
return LINEERR_INVALCALLHANDLE;
if (line.callState != LINECALLSTATE_DIALTONE &&
line.callState != LINECALLSTATE_DIALING)
return LINEERR_INVALCALLSTATE;
// check for invalid dial string (wierd chars or length)
// we can assume lpszDestAddress is a valid pointer as TAPI checks it
if (res = CheckDestAddress (lpszDestAddress))
return res;
_fstrcpy (line.DestAddress, lpszDestAddress);
// With the second parameter set to TRUE, DialAndGetState
// will take care of updating the state of the call through
// the event proc.
//BUG DialAndGetState should return error as retval
// if (DialAndGetState (&line, TRUE) == CALL_STATE_ERROR)
res = LINEERR_OPERATIONFAILED;
(*(line.lpfnCompletion)) (dwRequestID, res);
return dwRequestID;
}
LONG TSPIAPI TSPI_lineGenerateDigits (
HDRVCALL hdCall,
DWORD dwEndToEndID,
DWORD dwDigitMode,
LPCSTR lpszDigits,
DWORD dwDuration)
{
char szDigitBuf[MEDIUMBUFFER];
int res;
//BUG this could go real async in new model
//BUG in that case a new generate digits call would be required
// to kill an old call and a call with null for lpszDigits would
// kill the old digit generation without initiating a new string
DebugMsg (("Entering TSPI_lineGenerateDigits"));
if (hdCall != (HDRVCALL) line.hdCall)
return LINEERR_INVALCALLHANDLE;
if (line.callState != LINECALLSTATE_BUSY &&
line.callState != LINECALLSTATE_DIALTONE &&
line.callState != LINECALLSTATE_CONNECTED)
return LINEERR_INVALCALLSTATE;
if (dwDuration == 0)
dwDuration = line.dpDialParams.dwDigitDuration;
else if (dwDuration < MIN_DURATION)
dwDuration = MIN_DURATION;
else if (dwDuration > MAX_DURATION)
dwDuration = MAX_DURATION;
if (dwDigitMode == LINEDIGITMODE_PULSE)
wsprintf (szDigitBuf, "ATX0S6=0DP%s;X4", lpszDigits);
else
wsprintf (szDigitBuf, "ATX0S6=0S11=%luDT%s;X4", dwDuration, lpszDigits);
// We neglect to check for some errors here to speed up this
// process. It's time critical and failure is unimportant in
// most cases.
// res = SendModemCommand (line.uiCommId, szDigitBuf);
if (res >= 0) //BUG what does >0 mean ?
{
// res = GetModemReply (line.uiCommId, szDigitBuf, sizeof (szDigitBuf));
//BUG why not just send command, what's the deal with the following hangup
if (res == SERIAL_OK &&
_fstrcmp (szDigitBuf, "OK") == 0)
{
// SendModemCommand (line.uiCommId, s_hangup);
//BUG
// and send LINEGENERATE message
}
}
return LINEERR_OPERATIONFAILED;
}
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 = _fstrlen (line.lineaddr) + 1;
lpAddressCaps->dwNeededSize = sizeof (LINEADDRESSCAPS) + cbLineAddr;
if (lpAddressCaps->dwTotalSize < lpAddressCaps->dwNeededSize)
lpAddressCaps->dwUsedSize = sizeof (LINEADDRESSCAPS);
else
{
_fmemcpy((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 |
LINECALLINFOSTATE_MONITORMODES;
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_OFFERING |
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_ANSWER |
LINECALLFEATURE_DIAL |
LINECALLFEATURE_DROP |
LINECALLFEATURE_GENERATEDIGITS |
LINECALLFEATURE_GENERATETONE |
LINECALLFEATURE_MONITORDIGITS |
LINECALLFEATURE_MONITORTONES;
return 0;
}
LONG TSPIAPI TSPI_lineGetCallInfo (
HDRVCALL hdCall,
LPLINECALLINFO lpCallInfo)
{
int cbDestAddr = _fstrlen (line.DestAddress) + 1;
DebugMsg (("Entering TSPI_lineGetCallInfo"));
if (hdCall != (HDRVCALL) line.hdCall)
return LINEERR_INVALCALLHANDLE;
lpCallInfo->dwUsedSize = sizeof (LINECALLINFO);
lpCallInfo->dwNeededSize = sizeof (LINECALLINFO) + cbDestAddr;
if (lpCallInfo->dwTotalSize < lpCallInfo->dwNeededSize)
lpCallInfo->dwUsedSize = sizeof (LINECALLINFO);
else
{
_fmemcpy((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_OFFERING |
LINECALLSTATE_DIALTONE |
LINECALLSTATE_DIALING |
LINECALLSTATE_BUSY |
LINECALLSTATE_CONNECTED |
LINECALLSTATE_PROCEEDING |
LINECALLSTATE_UNKNOWN;
lpCallInfo->dwMonitorMediaModes = LINEMEDIAMODE_INTERACTIVEVOICE | LINEMEDIAMODE_AUTOMATEDVOICE;
lpCallInfo->dwOrigin = line.dwOrigin;
lpCallInfo->dwReason = LINECALLREASON_UNAVAIL;
// Bug: Caller-ID should be enabled!
lpCallInfo->dwCallerIDFlags = LINECALLPARTYID_UNAVAIL;
lpCallInfo->dwCalledIDFlags = LINECALLPARTYID_UNAVAIL;
lpCallInfo->dwConnectedIDFlags = LINECALLPARTYID_UNAVAIL;
lpCallInfo->dwRedirectionIDFlags = LINECALLPARTYID_UNAVAIL;
lpCallInfo->dwRedirectingIDFlags = LINECALLPARTYID_UNAVAIL;
lpCallInfo->DialParams = line.dpDialParams;
return 0;
}
LONG TSPIAPI TSPI_lineGetCallStatus (
HDRVCALL hdCall,
LPLINECALLSTATUS lpCallStatus)
{
DebugMsg (("Entering TSPI_lineGetCallStatus"));
if (hdCall != (HDRVCALL) line.hdCall)
return LINEERR_INVALCALLHANDLE;
lpCallStatus->dwCallState = line.callState;
switch (line.callState)
{
case LINECALLSTATE_IDLE:
case LINECALLSTATE_UNKNOWN:
break;
case LINECALLSTATE_DIALTONE:
lpCallStatus->dwCallStateMode = LINEDIALTONEMODE_UNAVAIL;
// fall thru
case LINECALLSTATE_DIALING:
lpCallStatus->dwCallFeatures = LINECALLFEATURE_DIAL |
LINECALLFEATURE_DROP |
LINECALLFEATURE_GENERATEDIGITS;
break;
case LINECALLSTATE_BUSY:
lpCallStatus->dwCallStateMode = LINEBUSYMODE_UNAVAIL;
// fall thru
case LINECALLSTATE_CONNECTED:
case LINECALLSTATE_PROCEEDING:
lpCallStatus->dwCallFeatures = LINECALLFEATURE_DROP |
LINECALLFEATURE_GENERATEDIGITS;
break;
}
return 0;
}
void fillDialParams (LPLINEDIALPARAMS source, LPLINEDIALPARAMS dest)
{
// this could also be called from lineSetCallParams
// Set the dial params if there are any.
DWORD pause = source->dwDialPause;
DWORD speed = source->dwDialSpeed;
DWORD duration = source->dwDigitDuration;
DWORD dialtone = source->dwWaitForDialtone;
if (pause == 0)
pause = DEF_DIALPAUSE;
else if (pause < MIN_DIALPAUSE)
pause = MIN_DIALPAUSE;
else if (pause > MAX_DIALPAUSE)
pause = MAX_DIALPAUSE;
if (speed == 0)
speed = DEF_DIALSPEED;
else if (speed < MIN_DIALSPEED)
speed = MIN_DIALSPEED;
else if (speed > MAX_DIALSPEED)
speed = MAX_DIALSPEED;
if (duration == 0)
duration = DEF_DURATION;
else if (duration < MIN_DURATION)
duration = MIN_DURATION;
else if (duration > MAX_DURATION)
duration = MAX_DURATION;
if (dialtone == 0)
dialtone = DEF_DIALTONE;
else if (dialtone < MIN_DIALTONE)
dialtone = MIN_DIALTONE;
else if (dialtone > MAX_DIALTONE)
dialtone = MAX_DIALTONE;
dest->dwDialPause = pause;
dest->dwDialSpeed = speed;
dest->dwDigitDuration = duration;
dest->dwWaitForDialtone = dialtone;
}
///////////////////////////////////////////////////////////
// ALREADY CHANGED!!!
///////////////////////////////////////////////////////////
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);
// Tell our companion app that we are no longer accepting anything from this line
appCall(msgClose,(LONG)(VOID FAR *)&line,0);
return 0;
}
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;
line.htCall = 0;
line.hdCall = 0;
*lphdLine = (HDRVLINE) &line;
DebugMsg(("htLine = %ld",(LONG)htLine));
// We must inform our companion app of the lineOpen, so it knows what to do with RING!
appCall(msgOpen,(LONG)(VOID FAR *)&line,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.hdCall)
return LINEERR_INVALCALLHANDLE;
lineDropCore (&line); // it was our active call
(*(line.lpfnCompletion)) (dwRequestID, 0);
return dwRequestID;
}
long appCall (int msg, long param, long dwRequestID)
{
long res;
if (atspexehwnd == 0)
{
DebugMsg (("companion app has not yet registered"));
return LINEERR_NODRIVER;
}
line.dwRequestID = dwRequestID;
res = SendMessage(atspexehwnd, msg, 0, param);
if (res < 0)
{
DebugMsg(("send message returned error: %li", res));
return res;
}
else
return dwRequestID;
}
///////////////////////////////////////////////////////////
// NEW FUNCTIONS FOR ATVSP!!!
///////////////////////////////////////////////////////////
LONG TSPIAPI TSPI_lineAnswer (
DRV_REQUESTID dwRequestID,
HDRVCALL hdCall,
LPCSTR lpsUserUserInfo,
DWORD dwSize)
{
DebugMsg(("Entering TSPI_lineAnswer"));
if (hdCall != (HDRVCALL)line.hdCall)
return LINEERR_INVALCALLHANDLE;
return appCall(msgAnswer, (LONG)(VOID FAR *)&line, dwRequestID);
}
LONG TSPIAPI TSPI_lineMonitorTones (
HDRVCALL hdCall,
DWORD dwToneListID,
LPLINEMONITORTONE const lpToneList,
DWORD dwNumEntries)
{
DebugMsg(("Entering TSPI_lineMonitorTones"));
if (hdCall != (HDRVCALL)line.hdCall)
return LINEERR_INVALCALLHANDLE;
// Note that we can only handle one tone list at a time!!!
// Since all we can detect is silence anyway, it would be silly to have more than one tone list.
if (lpToneList && dwNumEntries != 1)
{
DebugMsg(("Line Error: Invalid number of entries in ToneList"));
return LINEERR_RESOURCEUNAVAIL;
}
if (line.callState == LINECALLSTATE_IDLE)
{
DebugMsg(("Line Error: CallState = IDLE"));
return LINEERR_INVALCALLSTATE;
}
if (lpToneList == NULL)
{
if (dwToneListID != line.dwToneListID)
{
DebugMsg(("Line Error: Invalid ToneListID"));
return LINEERR_OPERATIONFAILED;
}
// We're turning off Silence Detection
line.wSilenceSensitivity = 0;
line.wSilenceDuration = 0;
return 0;
}
// Bug: The Answering Machine sends us only one frequency right now, so we comment this out!!!
// if (lpToneList->dwFrequency1 || lpToneList->dwFrequency2 || lpToneList->dwFrequency3)
// {
// DebugMsg(("Line Error: Invalid tone frequency specified"));
// return LINEERR_INVALTONE;
// }
line.dwToneListID = dwToneListID;
line.wSilenceSensitivity = 15; // Manufacturer's default for the modem
line.wSilenceDuration = (WORD)lpToneList->dwDuration / 100;
line.dwAppSpecific = lpToneList->dwAppSpecific;
return appCall(msgMonitorTones, (LONG)(VOID FAR *)&line, 0L);
}
LONG TSPIAPI TSPI_lineMonitorDigits (
HDRVCALL hdCall,
DWORD dwDigitModes)
{
DebugMsg(("Entering TSPI_lineMonitorDigits STUB"));
return 0;
}
LONG TSPIAPI TSPI_lineGenerateTone (
HDRVCALL hdCall,
DWORD dwEndToEndID,
DWORD dwToneMode,
DWORD dwDuration,
DWORD dwNumTones,
LPLINEGENERATETONE const lpTones)
{
LONG res;
DebugMsg(("Entering TSPI_lineGenerateTone"));
if (hdCall != (HDRVCALL)line.hdCall)
return LINEERR_INVALCALLHANDLE;
line.dwToneMode = dwToneMode;
line.dwDuration = dwDuration;
line.dwNumTones = dwNumTones;
line.lpTones = lpTones;
res = appCall(msgGenerateTone, (LONG)(VOID FAR *)&line, dwEndToEndID);
return (res >= 0 ? 0 : res);
}
///////////////////////////////////////////////////////////
// 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"));
LoadIniStrings (dwPermanentProviderId);
DialogBox (hInst, MAKEINTRESOURCE (IDD_CFGDLG), hwnd, ConfigDlgProc);
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"));
LoadIniStrings (dwPermanentProviderId);
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 screen
res = DialogBox (hInst, MAKEINTRESOURCE (IDD_CFGDLG), hwnd, ConfigDlgProc);
return (res ? LINEERR_OPERATIONFAILED : 0);
}
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
///////////////////////////////////////////////////////////
static BOOL StringResourcesLoaded = FALSE;
void LoadIniStrings (DWORD ppID)
{
char section[sizeof (s_providerx) + 5]; // room for 65535
if (StringResourcesLoaded)
return;
wsprintf (section, s_providerx, (int) ppID);
line.dwppID = ppID;
// user preferences come from the telephon.ini file
line.ignore = GetPrivateProfileInt (section, s_ignore, 0, s_telephon_ini);
line.pulse = GetPrivateProfileInt (section, s_pulse, 0, s_telephon_ini);
GetPrivateProfileString (section, s_port, "COM1",
line.port, sizeof (line.port), s_telephon_ini);
GetPrivateProfileString (section, s_speed, "9600",
line.speed, sizeof (line.speed), s_telephon_ini);
GetPrivateProfileString (section, s_initstr, "",
line.initstr, sizeof (line.initstr), 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));
StringResourcesLoaded = TRUE;
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]));
}
for (CurrSel = 0; CurrSel < NUMSPEEDS; CurrSel++)
{
SendDlgItemMessage(hDlg, ID_SPEED, CB_ADDSTRING,
0, (LPARAM) ((LPSTR) lpszCommSpeedArray[CurrSel]));
}
CurrSel = (int) SendDlgItemMessage (hDlg, ID_PORT, CB_FINDSTRING, 0, (LPARAM) (LPSTR) line.port);
SendDlgItemMessage (hDlg, ID_PORT, CB_SETCURSEL, CurrSel, 0);
CurrSel = (int) SendDlgItemMessage (hDlg, ID_SPEED, CB_FINDSTRING, 0, (LPARAM) (LPSTR) line.speed);
SendDlgItemMessage (hDlg, ID_SPEED, 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);
SendDlgItemMessage (hDlg, ID_INITSTR, WM_SETTEXT, 0, (LPARAM) (LPSTR) line.initstr);
SendDlgItemMessage (hDlg, ID_IGNORE, BM_SETCHECK, line.ignore, 0);
SendDlgItemMessage (hDlg, ID_PULSE, BM_SETCHECK, line.pulse, 0);
}
break;
case WM_COMMAND:
{
switch (wParam)
{
case IDOK:
{
// This code is a little brutal, it writes out all the
// (new) values when OK is pressed, even if nothing
// changed
char Buffer[20]; // for itoa of small ints
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);
// Speed
CurrSel = (int) SendDlgItemMessage (hDlg, ID_SPEED, CB_GETCURSEL, 0, 0);
SendDlgItemMessage (hDlg, ID_SPEED, CB_GETLBTEXT, CurrSel, (LPARAM) (LPSTR) line.speed);
WritePrivateProfileString (szp, s_speed, line.speed, 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);
// Initialisation String
SendDlgItemMessage (hDlg, ID_INITSTR, WM_GETTEXT,
sizeof (line.initstr), (LPARAM) (LPSTR) line.initstr);
AnsiUpper (line.initstr);
WritePrivateProfileString (szp, s_initstr, line.initstr, s_telephon_ini);
// "Don't use internal string" checkbox
line.ignore = (int) SendDlgItemMessage (hDlg, ID_IGNORE, BM_GETCHECK, 0, 0);
_itoa(line.ignore, Buffer, 10);
WritePrivateProfileString (szp, s_ignore, Buffer, s_telephon_ini);
// "Use pulse dialing"
line.pulse = (int) SendDlgItemMessage(hDlg, ID_PULSE, BM_GETCHECK, 0, 0);
_itoa(line.pulse, Buffer, 10);
WritePrivateProfileString (szp, s_pulse, Buffer, 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;
case IDHELP:
WinHelp (hDlg, HELP_FILE, HELP_CONTEXT, hidConfiguration);
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