home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
PC Press 1997 July
/
Sezamfile97_2.iso
/
windows
/
program
/
ttychic.exe
/
NEWDIAL.C
< prev
next >
Wrap
Text File
|
1994-12-01
|
23KB
|
563 lines
#include <stdlib.h>
#include <memory.h>
#include <malloc.h>
#include "session.h"
BOOL SetupConnection();
SESSIONINFO sinfo;
/* thread control mask */
DWORD ThreadControl;
/* The dialInitialize function encapsulates the three TAPI functions (lineInitialize,
lineNegotiateAPIVersion, lineOpenrequired) to obtain
a handle to a line. Once you have a line handle you can then dial or answer
calls on that line. */
LONG dialInitialize (HINSTANCE hInst, HWND hWnd)
{
LONG lResult; /* Stores return code from TAPI calls */
MSG msg; /* Identifies a message */
DWORD tc = GetTickCount(); /* Timer */
DWORD dwLine;
LINEEXTENSIONID lineExtensionID; /* Will be set to 0 to indicate no known extensions */
/* zero out the SESSION INFO structure */
memset (&sinfo, 0, sizeof(SESSIONINFO));
/* initialize tapi */
/* hLineAPP will get loaded with the application's handle to TAPI */
/* Are SESSIONINSTANCE/NAME/WINDOW from other code?*/
/* One of the main functions of lineIntitialize is to tell TAPI the name
of the call back function it should use when sending messages to your
application. */
sinfo.lpfnCallback = LineCallBackProc;
lstrcpy (SESSIONNAME(), "Mailer");
SESSIONINSTANCE() = hInst;
SESSIONWINDOW() = hWnd;
while ((lResult = lineInitialize(&sinfo.hApp, SESSIONINSTANCE(),
(LINECALLBACK)MakeProcInstance((FARPROC)sinfo.lpfnCallback,
SESSIONINSTANCE()), SESSIONNAME(),
&sinfo.dwNumLines)) == LINEERR_REINIT) {
/* TBD - remove for Chicago */
/* multitask */
if (PeekMessage(&msg,0,0,0,PM_REMOVE)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
} /* if */
/* wait five seconds, then ask if they want to retry */
if (GetTickCount() - tc >= 5000) {
if (MessageBox(SESSIONWINDOW(),
"Telephone System Is Reinitializing - Cancel to abort",
"Error - TAPI Initialization Failed",
MB_RETRYCANCEL) == IDCANCEL)
break;
tc = GetTickCount();
} /* end if */
} /* end while */
/* error initializing telephone API */
if (lResult <0)
return lResult;
SESSIONINITIALIZED() = TRUE;
/* if no lines, bomb */
if (SESSIONNUMLINES() == 0) {
lResult = SESSIONERR_NOLINES;
goto errout;
} /* end if (no line devices found) */
sinfo.lpLineDevCaps = (LPLINEDEVCAPS) malloc (sizeof(LINEDEVCAPS)+1000);
if (!sinfo.lpLineDevCaps)
goto errout;
SESSIONDEVCAPSALLOCED() = TRUE;
/* zero out the structures */
memset (sinfo.lpLineDevCaps, 0, sizeof(LINEDEVCAPS));
/* open each line for monitoring and find one that supports LINEMEDIAMODE_DATAMODEM */
for (dwLine = 0; dwLine < SESSIONNUMLINES(); ++dwLine) {
/* negotiate API version for each line */
lResult = lineNegotiateAPIVersion(SESSIONAPPHANDLE(), dwLine, TAPIVERSION,
TAPIVERSION, &sinfo.dwAPIVersion, &lineExtensionID);
if (lResult)
goto errout;
lResult = dialGetDevCaps(dwLine);
/* if error, bomb */
if (lResult) {
goto errout;
} /* if */
/* check for supported media mode. If not datamodem, continue to next line */
if (!(sinfo.lpLineDevCaps->dwMediaModes & LINEMEDIAMODE_DATAMODEM))
continue;
/* open the line that supports data modems */
lResult = lineOpen(SESSIONAPPHANDLE(), dwLine, &sinfo.hLine, SESSIONAPIVERSION(),
0L, (DWORD) 0L, LINECALLPRIVILEGE_OWNER,
LINEMEDIAMODE_DATAMODEM, NULL);
/* if error, try next line */
if (lResult) {
continue;
} /* if */
SESSIONLINEID()= dwLine;
SESSIONLINEOPEN() = TRUE;
/* if we are here then we found a compatible line */
break;
} /* end for (each supported line) */
return 0;
errout:
if (SESSIONINITIALIZED()) {
lineShutdown (SESSIONAPPHANDLE());
SESSIONINITIALIZED() = FALSE;
}
if (SESSIONDEVCAPSALLOCED()) {
free (sinfo.lpLineDevCaps);
SESSIONDEVCAPSALLOCED() = FALSE;
}
if (SESSIONLINEOPEN()) {
lineClose (SESSIONLINEHANDLE());
SESSIONLINEOPEN() = FALSE;
}
} /* end function (dialInitialize) */
/* dialGetDevCaps - wrapper for lineGetDevCaps */
LONG dialGetDevCaps (DWORD dwLine)
{
LONG lResult;
/* get line capability info */
sinfo.lpLineDevCaps->dwTotalSize = sizeof(LINEDEVCAPS)+1000;
lResult = lineGetDevCaps(SESSIONAPPHANDLE(), dwLine,
SESSIONAPIVERSION(), 0, sinfo.lpLineDevCaps);
if (lResult)
return lResult;
/* reallocate buffer if not big enough */
while (sinfo.lpLineDevCaps->dwNeededSize > sinfo.lpLineDevCaps->dwTotalSize) {
DWORD lcbNeeded = sinfo.lpLineDevCaps->dwNeededSize;
free((LPVOID)sinfo.lpLineDevCaps);
if ((sinfo.lpLineDevCaps = (LPLINEDEVCAPS) malloc((size_t)lcbNeeded))
== NULL)
return LINEERR_NOMEM;
sinfo.lpLineDevCaps->dwTotalSize = lcbNeeded;
/* try again */
lResult = lineGetDevCaps(SESSIONAPPHANDLE(), dwLine,
SESSIONAPIVERSION(), 0, sinfo.lpLineDevCaps);
if (lResult == LINEERR_STRUCTURETOOSMALL)
continue;
else if (lResult)
return lResult;
} /* while */
return 0;
} /* end function (dialGetDevCaps) */
/* dialMakeCall - wrapper for lineMakeCall */
LONG dialMakeCall (char *szDestination)
{
LINECALLPARAMS callparams;
LONG lResult;
/* if already connected or in a pending state, do nothing */
if (SESSIONCONNECTED() || SESSIONPENDINGASYNC())
return -1;
/* zero out the structures */
memset (&callparams, 0, sizeof(LINECALLPARAMS));
/* set call parameters */
callparams.dwBearerMode = LINEBEARERMODE_VOICE;
callparams.dwMediaMode = LINEMEDIAMODE_DATAMODEM;
callparams.dwTotalSize = sizeof(LINECALLPARAMS);
lResult = lineMakeCall (SESSIONLINEHANDLE(), &sinfo.hCall, szDestination, 0, &callparams);
if (lResult<0)
return lResult;
else
SESSIONPENDINGASYNC() = lResult;
SESSIONMAKECALLINPROGRESS() = TRUE;
return 0;
} /* end function (dialMakeCall) */
/* dialDropCall - wrapper for lineDrop */
LONG dialDropCall ()
{
LONG lResult;
/* if not already connected, do nothing */
if (SESSIONCALLSTATE() == LINECALLSTATE_IDLE)
return -1;
/* close the device handle */
if (SESSIONDEVICEHANDLE())
CloseHandle (SESSIONDEVICEHANDLE());
SESSIONDEVICEHANDLE() = NULL;
lResult = lineDrop (SESSIONCALLHANDLE(), NULL, 0);
SESSIONPENDINGASYNC() = lResult;
SESSIONDROPCALLINPROGRESS() = TRUE;
/* believe it or not, lineDrop is returning 0 syncronously with Unimodem! */
if (!lResult) {
/* do what Unimodem should be doing */
LineCallBackProc((DWORD)SESSIONCALLHANDLE(), LINE_CALLSTATE,
0, LINECALLSTATE_IDLE, 0, 0);
}
return lResult;
} /* end function (dialDropCall) */
/* dialLineClose - wrapper for lineClose */
LONG dialLineClose ()
{
LONG lResult;
if (!SESSIONLINEHANDLE())
return -1;
lResult = lineClose (SESSIONLINEHANDLE());
SESSIONLINEOPEN() = FALSE;
SESSIONLINEHANDLE() = NULL;
return lResult;
} /* end function (dialLineClose) */
/* dialDeallocCall - wrapper for lineDeallocCall */
LONG dialDeallocCall ()
{
LONG lResult;
if (!SESSIONCALLHANDLE())
return -1;
lResult = lineDeallocateCall (SESSIONCALLHANDLE());
SESSIONCALLHANDLE() = NULL;
return lResult;
} /* end function (dialDeallocCall) */
/* callback function */
void FAR PASCAL LineCallBackProc(DWORD hDevice,DWORD dwMessage,
DWORD dwInstance,DWORD dwParam1,DWORD dwParam2,DWORD dwParam3)
{
COMMTIMEOUTS cto;
switch (dwMessage)
{
case LINE_LINEDEVSTATE:
break;
/* process state transition */
case LINE_CALLSTATE:
SESSIONCALLSTATE()= dwParam1;
if (SESSIONMAKECALLINPROGRESS()) {
if (SESSIONCALLHANDLE() == NULL)
SESSIONCALLHANDLE() = (HCALL) hDevice;
switch (dwParam1) {
case LINECALLSTATE_CONNECTED:
SESSIONMAKECALLINPROGRESS() = FALSE;
SESSIONCONNECTED() = TRUE;
/* get the id of the COM device connected to the modem */
SESSIONDEVICEHANDLE() = GetCommHandle(SESSIONCALLHANDLE(), SESSIONDEVICENAME());
if (SESSIONCONNECTED( ) && SESSIONDEVICEHANDLE() ) {
if (!SetupConnection())
MessageBox(NULL, "Settings failed!", "Mailer",
MB_ICONEXCLAMATION ) ;
cto.ReadIntervalTimeout = 50;
cto.ReadTotalTimeoutMultiplier = 20;
cto.ReadTotalTimeoutConstant = 200;
cto.WriteTotalTimeoutMultiplier = 20;
cto.WriteTotalTimeoutConstant = 200;
SetCommTimeouts (SESSIONDEVICEHANDLE(), &cto);}
sinfo.wOrigin = 1; /* outbound call */
return;
} /* end switch (on callstate) */
} /* end if (making a call) */
if (SESSIONANSWERCALLINPROGRESS()) {
if (SESSIONCALLHANDLE() == NULL)
SESSIONCALLHANDLE() = (HCALL) hDevice;
switch (dwParam1) {
case LINECALLSTATE_CONNECTED:
SESSIONANSWERCALLINPROGRESS() = FALSE;
SESSIONCONNECTED() = TRUE;
/* get the id of the COM device connected to the modem */
SESSIONDEVICEHANDLE() = GetCommHandle(SESSIONCALLHANDLE(), SESSIONDEVICENAME());
// if SESSIONDEVICEHANDLE() and SESSIONCONNECTED(), set new COM parameters
if (SESSIONCONNECTED( ) && SESSIONDEVICEHANDLE() ) {
/* set communication params */
if (!SetupConnection())
MessageBox( NULL, "Settings failed!", "Mailer",
MB_ICONEXCLAMATION ) ;
cto.ReadIntervalTimeout = 50;
cto.ReadTotalTimeoutMultiplier = 20;
cto.ReadTotalTimeoutConstant = 200;
cto.WriteTotalTimeoutMultiplier = 20;
cto.WriteTotalTimeoutConstant = 200;
SetCommTimeouts (SESSIONDEVICEHANDLE(), &cto);
}
sinfo.wOrigin = 2; /* inbound call */
return;
} /* end switch (on callstate) */
} /* end if (answering a call) */
switch (dwParam1) {
case LINECALLSTATE_BUSY:
case LINECALLSTATE_DISCONNECTED:
case LINECALLSTATE_IDLE:
/* bug fix for disconnected which comes after idle and Unimodem needs this to
reset correctly */
dialDropCall ();
dialDeallocCall();
//dialLineClose();
SESSIONANSWERCALLINPROGRESS() = FALSE;
SESSIONDROPCALLINPROGRESS() = FALSE;
SESSIONMAKECALLINPROGRESS() = FALSE;
SESSIONCONNECTED() = FALSE;
return;
case LINECALLSTATE_OFFERING:
/* The call is being offered, signaling the arrival
of a new call. check if we are the owner of the call, and if we are,
then answer it. */
if (dwParam3 == LINECALLPRIVILEGE_OWNER) {
if ((SESSIONPENDINGASYNC() =
lineAnswer (SESSIONCALLHANDLE() = (HCALL)hDevice, NULL, 0)) < 0) {
SESSIONCALLHANDLE() = (HCALL) NULL;
SESSIONPENDINGASYNC() = 0;
return;
}
} /* end if (we own this call) */
SESSIONANSWERCALLINPROGRESS() = TRUE;
break;
} /* end switch (on call state) */
break;
case LINE_CLOSE:
break;
case LINE_REPLY:
if (SESSIONPENDINGASYNC() != dwParam1)
break;
if (SESSIONANSWERCALLINPROGRESS()) {/* reply message for lineAnswer */
if ((LONG)dwParam2 != 0)
SESSIONANSWERCALLINPROGRESS() = FALSE;
SESSIONPENDINGASYNC() = 0;
} /* end if (answer call in progress) */
if (SESSIONMAKECALLINPROGRESS()) {/* reply message for lineMakeCall */
if ((LONG)dwParam2 != 0)
SESSIONMAKECALLINPROGRESS() = FALSE;
SESSIONPENDINGASYNC() = 0;
} /* end if (make call in progress) */
if (SESSIONDROPCALLINPROGRESS()) {
if ((LONG)dwParam2 != 0)
SESSIONDROPCALLINPROGRESS() = FALSE;
SESSIONPENDINGASYNC() = 0;
} /* end if (drop call in progress) */
break;
/* other messages that can be processed */
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 */
HANDLE GetCommHandle (HCALL htCall, char *szDeviceName)
{
CommID FAR *cid;
VARSTRING *vs;
LONG lrc;
DWORD dwSize;
vs = (VARSTRING *) malloc (sizeof(VARSTRING));
vs->dwTotalSize = sizeof(VARSTRING);
vs->dwStringFormat = STRINGFORMAT_BINARY;
do {
/* get Win32 Comm handle associated with the call - the call handle
came from TAPI after making or answering a call */
/* another Unimodem bug - should return structuretoosmall but instead returns
success with needed > total */
if ( ((lrc = lineGetID(NULL, 0L, htCall, LINECALLSELECT_CALL, vs, "comm/datamodem")) == LINEERR_STRUCTURETOOSMALL)
|| (vs->dwTotalSize < vs->dwNeededSize)) {
dwSize= (lrc==LINEERR_STRUCTURETOOSMALL) ? (1000) : (vs->dwNeededSize);
free (vs);
vs = (VARSTRING *) malloc(dwSize);
vs->dwTotalSize = dwSize;
} /* end if (need more space) */
else if (lrc < 0) {
/* handle error */
} /* end if (error getting comm device handle) */
else
break; /* success */
} while (TRUE);
cid = (CommID FAR *) ((LPSTR)vs + vs->dwStringOffset);
lstrcpy (szDeviceName, &cid->szDeviceName[0]);
return cid->hComm;
} /* end function (GetCommHandle) */
/* Reading With Polling */
DWORD ReadBytesFromModem(BYTE *abyBuffer, DWORD *pnBytes)
{
DWORD dwErrorMask; /* mask of error bits */
COMSTAT comstat; /* status structure */
DWORD nToRead; /* number of bytes to read */
*pnBytes = 0; /* zero read size */
/* get status of read and write queues */
ClearCommError (SESSIONDEVICEHANDLE(), &dwErrorMask, &comstat);
/* check error flags */
if (dwErrorMask) {
/* handle error */
return dwErrorMask;
} /* end if (error) */
/* if too many bytes to read, just read the maximum */
if (comstat.cbInQue > MAXREADSIZE)
nToRead = MAXREADSIZE;
else
nToRead = comstat.cbInQue; /* otherwise read them all */
/* if no bytes to read, return */
if (nToRead == 0)
return 0L;
/* read the bytes */
if (!ReadFile(SESSIONDEVICEHANDLE(), abyBuffer, nToRead, pnBytes, NULL)) {
return GetLastError ();
} /* end if (error reading bytes) */
return 0L;
} /* end function (ReadBytesFromModem) */
/* write a potentially large block of data to the modem */
int WriteBytesToModem(BYTE *abyByteBuffer, DWORD nToWrite)
{
DWORD dwErrorMask; /* mask of error bits */
COMSTAT comstat; /* status structure */
DWORD nActualWrite; /* actual num bytes written */
do {
/* get status TX queue */
ClearCommError (SESSIONDEVICEHANDLE(), &dwErrorMask, &comstat);
if (dwErrorMask) return -1;
/* if we are under the minimum threshold of the TX queue */
if (comstat.cbOutQue < LOWWATER) {
/* if there is room, write æem all */
if (LOWWATER+ nToWrite <= MAXTXSIZE) {
WriteFile (SESSIONDEVICEHANDLE(), abyByteBuffer, nToWrite,
&nActualWrite, NULL);
nToWrite -= nActualWrite;
(BYTE *)abyByteBuffer += nActualWrite;
} /* end if (room for all the bytes in TX buf) */
/* if too many bytes to write at once, just fill TX buf and loop */
if (LOWWATER + nToWrite > MAXTXSIZE){
WriteFile (SESSIONDEVICEHANDLE(), abyByteBuffer,
MAXTXSIZE-comstat.cbOutQue,
&nActualWrite, NULL);
nToWrite -= nActualWrite;
(BYTE *)abyByteBuffer += nActualWrite;
} /* end if (canÆt fit all the bytes in the TX queue) */
} /* end if (bytes in output queue below minimum level) */
} while (nToWrite);
return 0;
} /* end function (WriteBytesToModem) */
/* Read the file into a buffer
*/
LONG BufferFile (char *szFileName, LPBYTE *ppBuffer, LPDWORD pnFileSize)
{
DWORD dwSize;
if ((SESSIONSENDFILEHANDLE()=CreateFile (szFileName, GENERIC_READ, 0 /* no sharing */,
NULL /* default security */, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL,
NULL /* no template */)) == INVALID_HANDLE_VALUE) {
return -1;
} /* error opening file */
if ((dwSize = GetFileSize (SESSIONSENDFILEHANDLE(), NULL)) == -1) {
CloseHandle (SESSIONSENDFILEHANDLE());
return -1;
} /* end if (error getting file size) */
if ((*ppBuffer = malloc (dwSize)) == NULL) {
CloseHandle (SESSIONSENDFILEHANDLE());
return -1;
} /* end if (error allocating file buffer) */
if (!ReadFile (SESSIONSENDFILEHANDLE(), *ppBuffer, dwSize, pnFileSize, NULL)) {
CloseHandle (SESSIONSENDFILEHANDLE());
free (*ppBuffer);
return -1;
} /* end if (error reading file into buffer) */
return 0;
} /* end function (BufferFile) */