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.
3280 lines
91 KiB
3280 lines
91 KiB
/* File: D:\WACKER\cncttapi\cncttapi.c (Created: 08-Feb-1994)
|
|
*
|
|
* Copyright 1994 by Hilgraeve Inc. -- Monroe, MI
|
|
* All rights reserved
|
|
*
|
|
* $Revision: 53 $
|
|
* $Date: 7/12/02 9:06a $
|
|
*/
|
|
|
|
#define TAPI_CURRENT_VERSION 0x00010004 // cab:11/14/96 - required!
|
|
|
|
#include <tapi.h>
|
|
#include <unimodem.h>
|
|
#pragma hdrstop
|
|
|
|
//#define DEBUGSTR
|
|
|
|
#include <time.h>
|
|
|
|
#include <tdll\stdtyp.h>
|
|
#include <tdll\session.h>
|
|
#include <tdll\statusbr.h>
|
|
#include <tdll\tdll.h>
|
|
#include <tdll\misc.h>
|
|
#include <tdll\mc.h>
|
|
#include <tdll\assert.h>
|
|
#include <tdll\errorbox.h>
|
|
#include <tdll\cnct.h>
|
|
#include <tdll\globals.h>
|
|
#include <tdll\sf.h>
|
|
#include <tdll\sess_ids.h>
|
|
#include <tdll\com.h>
|
|
#include <tdll\comdev.h>
|
|
#include <tdll\com.hh>
|
|
#include <tdll\htchar.h>
|
|
#include <tdll\cloop.h>
|
|
#include <emu\emu.h>
|
|
#include <term\res.h>
|
|
#include "cncttapi.h"
|
|
#include "cncttapi.hh"
|
|
#include <tdll\XFER_MSC.HH> // XD_TYPE
|
|
#include <tdll\XFER_MSC.H> // xfrGetDisplayWindow(), xfrDoTransfer()
|
|
#include "tdll\XFDSPDLG.H" // XFR_SHUTDOWN
|
|
|
|
static int DoNewModemWizard(HWND hWnd, int iTimeout);
|
|
static int tapiReinit(const HHDRIVER hhDriver);
|
|
static int tapiReinitMessage(const HHDRIVER hhDriver);
|
|
static int DoDelayedCall(const HHDRIVER hhDriver);
|
|
|
|
const TCHAR *g_achApp = TEXT("HyperTerminal");
|
|
|
|
static HHDRIVER gbl_hhDriver; // see LINEDEVSTATE for explaination.
|
|
|
|
#if 0
|
|
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
|
* FUNCTION:
|
|
* cnctdrvEntry
|
|
*
|
|
* DESCRIPTION:
|
|
* Currently, just initializes the C-Runtime library but may be used
|
|
* for other things later.
|
|
*
|
|
* ARGUMENTS:
|
|
* hInstDll - Instance of this DLL
|
|
* fdwReason - Why this entry point is called
|
|
* lpReserved - reserved
|
|
*
|
|
* RETURNS:
|
|
* BOOL
|
|
*
|
|
*/
|
|
BOOL WINAPI cnctdrvEntry(HINSTANCE hInstDll, DWORD fdwReason, LPVOID lpReserved)
|
|
{
|
|
hInstance = hInstDll;
|
|
return _CRT_INIT(hInstDll, fdwReason, lpReserved);
|
|
}
|
|
#endif
|
|
|
|
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
|
* FUNCTION:
|
|
* cnctdrvCreate
|
|
*
|
|
* DESCRIPTION:
|
|
* Initializes the connection driver and returns a handle to the driver
|
|
* if successful.
|
|
*
|
|
* ARGUMENTS:
|
|
* hCnct - public connection handle
|
|
*
|
|
* RETURNS:
|
|
* Handle to driver if successful, else 0.
|
|
*
|
|
*/
|
|
HDRIVER WINAPI cnctdrvCreate(const HCNCT hCnct, const HSESSION hSession)
|
|
{
|
|
HHDRIVER hhDriver;
|
|
|
|
if (hCnct == 0)
|
|
{
|
|
assert(FALSE);
|
|
return 0;
|
|
}
|
|
|
|
hhDriver = malloc(sizeof(*hhDriver));
|
|
|
|
if (hhDriver == 0)
|
|
{
|
|
assert(FALSE);
|
|
return 0;
|
|
}
|
|
|
|
gbl_hhDriver = hhDriver;
|
|
memset(hhDriver, 0, sizeof(*hhDriver));
|
|
|
|
InitializeCriticalSection(&hhDriver->cs);
|
|
|
|
hhDriver->hCnct = hCnct;
|
|
hhDriver->hSession = hSession;
|
|
hhDriver->iStatus = CNCT_STATUS_FALSE;
|
|
hhDriver->dwLine = (DWORD)-1;
|
|
|
|
cnctdrvInit(hhDriver);
|
|
return (HDRIVER)hhDriver;
|
|
}
|
|
|
|
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
|
* FUNCTION:
|
|
* cnctdrvDestroy
|
|
*
|
|
* DESCRIPTION:
|
|
* Destroys a connection driver handle.
|
|
*
|
|
* ARGUMENTS:
|
|
* hhDriver - private driver handle.
|
|
*
|
|
* RETURNS:
|
|
* 0 or error code
|
|
*
|
|
*/
|
|
int WINAPI cnctdrvDestroy(const HHDRIVER hhDriver)
|
|
{
|
|
if (hhDriver == 0)
|
|
{
|
|
assert(FALSE);
|
|
return CNCT_BAD_HANDLE;
|
|
}
|
|
|
|
// Disconnect if we're connected or in the process.
|
|
// Note: cnctdrvDisconnect should terminate the thread.
|
|
|
|
cnctdrvDisconnect(hhDriver, DISCNCT_NOBEEP);
|
|
|
|
if (hhDriver->hLine)
|
|
{
|
|
lineClose(hhDriver->hLine);
|
|
memset(&hhDriver->stCallPar, 0, sizeof(hhDriver->stCallPar));
|
|
hhDriver->stCallPar.dwTotalSize = sizeof(hhDriver->stCallPar);
|
|
hhDriver->stCallPar.dwMediaMode = LINEMEDIAMODE_DATAMODEM;
|
|
hhDriver->stCallPar.dwCallParamFlags = LINECALLPARAMFLAGS_IDLE;
|
|
hhDriver->stCallPar.dwBearerMode = 0;
|
|
|
|
hhDriver->hLine = 0;
|
|
}
|
|
|
|
if (hhDriver->hLineApp)
|
|
{
|
|
LONG lLineShutdown = lineShutdown(hhDriver->hLineApp);
|
|
|
|
if (lLineShutdown == LINEERR_NOMEM)
|
|
{
|
|
//
|
|
// We are in a low memory state, so wait for a while,
|
|
// then try to shutdown the line again. REV: 5/1/2002
|
|
//
|
|
Sleep(500);
|
|
lLineShutdown = lineShutdown(hhDriver->hLineApp);
|
|
}
|
|
|
|
if (lLineShutdown != 0)
|
|
{
|
|
assert(FALSE);
|
|
}
|
|
|
|
hhDriver->hLineApp = 0;
|
|
}
|
|
|
|
if (IsWindow(hhDriver->hwndCnctDlg))
|
|
EndModelessDialog(hhDriver->hwndCnctDlg);
|
|
|
|
if (IsWindow(hhDriver->hwndTAPIWindow))
|
|
{
|
|
DestroyWindow(hhDriver->hwndTAPIWindow);
|
|
}
|
|
|
|
/* --- Cleanup --- */
|
|
|
|
DeleteCriticalSection(&hhDriver->cs);
|
|
free(hhDriver);
|
|
return 0;
|
|
}
|
|
|
|
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
|
* FUNCTION:
|
|
* cnctdrvLock
|
|
*
|
|
* DESCRIPTION:
|
|
* Locks the connection driver's critical section semaphore.
|
|
*
|
|
* ARGUMENTS:
|
|
* hhDriver - private driver handle
|
|
*
|
|
* RETURNS:
|
|
* void
|
|
*
|
|
*/
|
|
void cnctdrvLock(const HHDRIVER hhDriver)
|
|
{
|
|
EnterCriticalSection(&hhDriver->cs);
|
|
}
|
|
|
|
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
|
* FUNCTION:
|
|
* cnctdrvUnlock
|
|
*
|
|
* DESCRIPTION:
|
|
* Unlocks the connection driver's critical section semaphore.
|
|
*
|
|
* ARGUMENTS:
|
|
* hhDriver - private driver handle
|
|
*
|
|
* RETURNS:
|
|
* void
|
|
*
|
|
*/
|
|
void cnctdrvUnlock(const HHDRIVER hhDriver)
|
|
{
|
|
LeaveCriticalSection(&hhDriver->cs);
|
|
}
|
|
|
|
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
|
* FUNCTION:
|
|
* cnctdrvInit
|
|
*
|
|
* DESCRIPTION:
|
|
* Initializes the connection handle. Can be called to reinitialize
|
|
* the handle. Does an implicit disconnect.
|
|
*
|
|
* ARGUMENTS:
|
|
* hhDriver - private driver handle
|
|
*
|
|
* RETURNS:
|
|
* 0
|
|
*
|
|
*/
|
|
int WINAPI cnctdrvInit(const HHDRIVER hhDriver)
|
|
{
|
|
long lRet;
|
|
int id = 0;
|
|
int iReturn = 0;
|
|
|
|
// Make sure we're disconnected.
|
|
//
|
|
cnctdrvDisconnect(hhDriver, DISCNCT_NOBEEP);
|
|
|
|
// ----------------------------------------------------------------
|
|
// Need to shut down hLineApp and reinitialize everytime we read
|
|
// new data file so that TAPI starts out in a clean and initialized
|
|
// state. Otherwise, we might inherit values from the previous
|
|
// session.
|
|
// ----------------------------------------------------------------
|
|
if (hhDriver->hLineApp)
|
|
{
|
|
LONG lLineShutdown = lineShutdown(hhDriver->hLineApp);
|
|
|
|
if (lLineShutdown == LINEERR_NOMEM)
|
|
{
|
|
//
|
|
// We are in a low memory state, so wait for a while,
|
|
// then try to shutdown the line again. REV: 5/1/2002
|
|
//
|
|
Sleep(500);
|
|
lLineShutdown = lineShutdown(hhDriver->hLineApp);
|
|
}
|
|
|
|
if (lLineShutdown != 0)
|
|
{
|
|
assert(FALSE);
|
|
hhDriver->hLineApp = 0;
|
|
return -2;
|
|
}
|
|
}
|
|
|
|
hhDriver->hLineApp = 0;
|
|
|
|
// Try to get a new LineApp handle now.
|
|
//
|
|
lRet = lineInitialize(&hhDriver->hLineApp, glblQueryDllHinst(),
|
|
lineCallbackFunc, g_achApp, &hhDriver->dwLineCnt);
|
|
|
|
if (lRet != 0)
|
|
{
|
|
iReturn = -3;
|
|
switch (lRet)
|
|
{
|
|
case LINEERR_INIFILECORRUPT:
|
|
id = IDS_ER_TAPI_INIFILE;
|
|
break;
|
|
|
|
case LINEERR_NODRIVER:
|
|
id = IDS_ER_TAPI_NODRIVER;
|
|
break;
|
|
|
|
case LINEERR_NOMULTIPLEINSTANCE:
|
|
id = IDS_ER_TAPI_NOMULTI;
|
|
break;
|
|
|
|
#if 0 // rev:08/05/99 We are now printing the lineInitialize() error.
|
|
// rev:08/26/98 We need to make sure there was no error reported.
|
|
//
|
|
case LINEERR_INVALAPPNAME:
|
|
case LINEERR_OPERATIONFAILED:
|
|
case LINEERR_RESOURCEUNAVAIL:
|
|
case LINEERR_INVALPOINTER:
|
|
case LINEERR_REINIT:
|
|
case LINEERR_NODEVICE:
|
|
case LINEERR_NOMEM:
|
|
id = IDS_ER_CNCT_TAPIFAILED;
|
|
break;
|
|
#endif
|
|
|
|
case LINEERR_OPERATIONUNAVAIL:
|
|
//rev: 08-05-99 If TAPI has not been installed, then return a
|
|
// unique error code (since it will be handled
|
|
// differently than other TAPI errors).
|
|
//
|
|
iReturn = -4;
|
|
|
|
#if ((NT_EDITION && !NDEBUG) || !NT_EDITION)
|
|
// Run the new Modem wizard if we have not prompted before.
|
|
//
|
|
DoNewModemWizard(sessQueryHwnd(hhDriver->hSession),
|
|
sessQueryTimeout(hhDriver->hSession));
|
|
#endif // ((NT_EDITION && !NDEBUG) || !NT_EDITION)
|
|
|
|
break;
|
|
|
|
default:
|
|
id = IDS_ER_TAPI_UNKNOWN;
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Only display these errors if in Debug mode in NT_EDITION.
|
|
//
|
|
#if ((NT_EDITION && !NDEBUG) || !NT_EDITION)
|
|
if ( id )
|
|
{
|
|
TCHAR ach[256];
|
|
TCHAR achMessage[256];
|
|
|
|
LoadString(glblQueryDllHinst(), id, ach, sizeof(ach) / sizeof(TCHAR));
|
|
if (id == IDS_ER_TAPI_UNKNOWN)
|
|
{
|
|
wsprintf(achMessage, ach, lRet);
|
|
}
|
|
else
|
|
{
|
|
lstrcpy(achMessage, ach);
|
|
}
|
|
|
|
TimedMessageBox(sessQueryHwnd(hhDriver->hSession),
|
|
achMessage, NULL, MB_OK | MB_ICONSTOP,
|
|
sessQueryTimeout(hhDriver->hSession));
|
|
}
|
|
#endif //((NT_EDITION && !NDEBUG) || !NT_EDITION)
|
|
|
|
return iReturn;
|
|
}
|
|
|
|
hhDriver->iStatus = CNCT_STATUS_FALSE;
|
|
hhDriver->dwLine = (DWORD)-1;
|
|
hhDriver->dwCountryID = (DWORD)-1;
|
|
hhDriver->dwPermanentLineId = (DWORD)-1;
|
|
hhDriver->achDest[0] = TEXT('\0');
|
|
hhDriver->achAreaCode[0] = TEXT('\0');
|
|
hhDriver->achLineName[0] = TEXT('\0');
|
|
hhDriver->fUseCCAC = TRUE;
|
|
|
|
/* --- This guy will set defaults --- */
|
|
|
|
EnumerateTapiLocations(hhDriver, 0, 0);
|
|
|
|
#if defined(INCL_WINSOCK)
|
|
hhDriver->iPort = 23;
|
|
hhDriver->achDestAddr[0] = TEXT('\0');
|
|
#endif
|
|
|
|
#ifdef INCL_CALL_ANSWERING
|
|
hhDriver->fAnswering = FALSE;
|
|
hhDriver->fRestoreSettings = FALSE;
|
|
hhDriver->nSendCRLF = 0;
|
|
hhDriver->nLocalEcho = 0;
|
|
hhDriver->nAddLF = 0;
|
|
hhDriver->nEchoplex = 0;
|
|
hhDriver->pvUnregister = 0;
|
|
#endif
|
|
|
|
return iReturn;
|
|
}
|
|
|
|
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
|
* FUNCTION:
|
|
* cnctdrvLoad
|
|
*
|
|
* DESCRIPTION:
|
|
* Reads the session file to get stuff connection driver needs.
|
|
*
|
|
* ARGUMENTS:
|
|
* hhDriver - private driver handle
|
|
*
|
|
* RETURNS:
|
|
* 0=OK, else error
|
|
*
|
|
*/
|
|
int WINAPI cnctdrvLoad(const HHDRIVER hhDriver)
|
|
{
|
|
LPVARSTRING pvs;
|
|
unsigned long ul;
|
|
const SF_HANDLE sfhdl = sessQuerySysFileHdl(hhDriver->hSession);
|
|
|
|
hhDriver->dwCountryID = (DWORD)-1;
|
|
ul = sizeof(hhDriver->dwCountryID);
|
|
sfGetSessionItem(sfhdl, SFID_CNCT_CC, &ul, &hhDriver->dwCountryID);
|
|
|
|
hhDriver->achAreaCode[0] = TEXT('\0');
|
|
ul = sizeof(hhDriver->achAreaCode);
|
|
sfGetSessionItem(sfhdl, SFID_CNCT_AREA, &ul, hhDriver->achAreaCode);
|
|
|
|
hhDriver->achDest[0] = TEXT('\0');
|
|
ul = sizeof(hhDriver->achDest);
|
|
sfGetSessionItem(sfhdl, SFID_CNCT_DEST, &ul, hhDriver->achDest);
|
|
|
|
hhDriver->dwPermanentLineId = 0;
|
|
ul = sizeof(hhDriver->dwPermanentLineId);
|
|
sfGetSessionItem(sfhdl, SFID_CNCT_LINE, &ul, &hhDriver->dwPermanentLineId);
|
|
|
|
hhDriver->fUseCCAC = 1;
|
|
ul = sizeof(hhDriver->fUseCCAC);
|
|
sfGetSessionItem(sfhdl, SFID_CNCT_USECCAC, &ul, &hhDriver->fUseCCAC);
|
|
|
|
hhDriver->fRedialOnBusy = 1;
|
|
ul = sizeof(hhDriver->fRedialOnBusy);
|
|
sfGetSessionItem(sfhdl, SFID_CNCT_REDIAL, &ul, &hhDriver->fRedialOnBusy);
|
|
|
|
#if defined (INCL_WINSOCK)
|
|
hhDriver->iPort = 23;
|
|
ul = sizeof(hhDriver->iPort);
|
|
sfGetSessionItem(sfhdl, SFID_CNCT_IPPORT, &ul, &hhDriver->iPort);
|
|
|
|
hhDriver->achDestAddr[0] = TEXT('\0');
|
|
ul = sizeof(hhDriver->achDestAddr);
|
|
sfGetSessionItem(sfhdl, SFID_CNCT_IPDEST, &ul, hhDriver->achDestAddr);
|
|
#endif
|
|
|
|
hhDriver->fCarrierDetect = FALSE;
|
|
ul = sizeof(hhDriver->fCarrierDetect);
|
|
sfGetSessionItem(sfhdl, SFID_CNCT_CARRIERDETECT, &ul, &hhDriver->fCarrierDetect);
|
|
|
|
|
|
if ( IsNT() )
|
|
{
|
|
hhDriver->achComDeviceName[0] = TEXT('\0');
|
|
ul = sizeof(hhDriver->achComDeviceName);
|
|
sfGetSessionItem(sfhdl, SFID_CNCT_COMDEVICE, &ul, hhDriver->achComDeviceName);
|
|
}
|
|
|
|
// ----------------------------------------------------------------
|
|
// Need to shut down hLineApp and reinitialize everytime we read
|
|
// new data file so that TAPI starts out in a clean and initialized
|
|
// state. Otherwise, we might inherit values from the previous
|
|
// session.
|
|
// ----------------------------------------------------------------
|
|
|
|
if (hhDriver->hLineApp)
|
|
{
|
|
LONG lLineShutdown = lineShutdown(hhDriver->hLineApp);
|
|
|
|
if (lLineShutdown == LINEERR_NOMEM)
|
|
{
|
|
//
|
|
// We are in a low memory state, so wait for a while,
|
|
// then try to shutdown the line again. REV: 5/1/2002
|
|
//
|
|
Sleep(500);
|
|
lLineShutdown = lineShutdown(hhDriver->hLineApp);
|
|
}
|
|
|
|
if (lLineShutdown != 0)
|
|
{
|
|
assert(FALSE);
|
|
hhDriver->hLineApp = 0;
|
|
return -2;
|
|
}
|
|
|
|
hhDriver->hLineApp = 0;
|
|
|
|
if (lineInitialize(&hhDriver->hLineApp, glblQueryDllHinst(),
|
|
lineCallbackFunc, g_achApp, &hhDriver->dwLineCnt))
|
|
{
|
|
assert(FALSE);
|
|
return -3;
|
|
}
|
|
}
|
|
|
|
// EnumerateLines() will set the hhDriver->fMatchedPermanentLineID
|
|
// guy if it finds a match for our saved dwPermanentLineId guy
|
|
//
|
|
if ( IsNT() )
|
|
{
|
|
EnumerateLinesNT(hhDriver, 0);
|
|
}
|
|
else
|
|
{
|
|
EnumerateLines(hhDriver, 0);
|
|
}
|
|
|
|
/* --- If we saved a tapi configuration, restore it. --- */
|
|
|
|
if (sfGetSessionItem(sfhdl, SFID_CNCT_TAPICONFIG, &ul, 0) != 0)
|
|
return 0; // Ok, might not be there.
|
|
|
|
if ((pvs = malloc(ul)) == 0)
|
|
{
|
|
assert(FALSE);
|
|
return -4;
|
|
}
|
|
|
|
if (sfGetSessionItem(sfhdl, SFID_CNCT_TAPICONFIG, &ul, pvs) == 0)
|
|
{
|
|
if (hhDriver->fMatchedPermanentLineID)
|
|
{
|
|
LPVOID pv = (BYTE *)pvs + pvs->dwStringOffset;
|
|
|
|
if (lineSetDevConfig(hhDriver->dwLine, pv,
|
|
pvs->dwStringSize, DEVCLASS) != 0)
|
|
{
|
|
// This error prevented a user from even opening a session
|
|
// file if the file contained TAPI info and the user had
|
|
// never installed a modem. We modified the error that appears
|
|
// when you actually try to USE a non-existant modem so that
|
|
// we could suppress the display of this error jkh 8/3/98
|
|
#if 0
|
|
TCHAR ach[FNAME_LEN];
|
|
|
|
LoadString(glblQueryDllHinst(), IDS_OPEN_FAILED, ach,
|
|
sizeof(ach) / sizeof(TCHAR));
|
|
|
|
TimedMessageBox(sessQueryHwnd(hhDriver->hSession), ach, NULL,
|
|
MB_OK | MB_ICONINFORMATION,
|
|
sessQueryTimeout(hhDriver->hSession));
|
|
|
|
free(pvs);
|
|
pvs = NULL;
|
|
return -5;
|
|
#endif
|
|
}
|
|
}
|
|
}
|
|
|
|
free(pvs);
|
|
pvs = NULL;
|
|
return 0;
|
|
}
|
|
|
|
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
|
* FUNCTION:
|
|
* cnctdrvSave
|
|
*
|
|
* DESCRIPTION:
|
|
* Saves connection settings to the session file
|
|
*
|
|
* ARGUMENTS:
|
|
* hhDriver - private driver handle
|
|
*
|
|
* RETURNS:
|
|
* 0=OK, else error
|
|
*
|
|
*/
|
|
int WINAPI cnctdrvSave(const HHDRIVER hhDriver)
|
|
{
|
|
DWORD dwSize;
|
|
unsigned long ul;
|
|
LPVARSTRING pvs = NULL;
|
|
const SF_HANDLE sfhdl = sessQuerySysFileHdl(hhDriver->hSession);
|
|
|
|
sfPutSessionItem(sfhdl, SFID_CNCT_CC, sizeof(hhDriver->dwCountryID),
|
|
&hhDriver->dwCountryID);
|
|
|
|
sfPutSessionItem(sfhdl, SFID_CNCT_AREA,
|
|
(lstrlen(hhDriver->achAreaCode) + 1) * sizeof(TCHAR),
|
|
hhDriver->achAreaCode);
|
|
|
|
sfPutSessionItem(sfhdl, SFID_CNCT_DEST,
|
|
(lstrlen(hhDriver->achDest) + 1) * sizeof(TCHAR), hhDriver->achDest);
|
|
|
|
sfPutSessionItem(sfhdl, SFID_CNCT_LINE, sizeof(hhDriver->dwPermanentLineId),
|
|
&hhDriver->dwPermanentLineId);
|
|
|
|
sfPutSessionItem(sfhdl, SFID_CNCT_USECCAC, sizeof(hhDriver->fUseCCAC),
|
|
&hhDriver->fUseCCAC);
|
|
|
|
sfPutSessionItem(sfhdl, SFID_CNCT_REDIAL, sizeof(hhDriver->fRedialOnBusy),
|
|
&hhDriver->fRedialOnBusy);
|
|
|
|
#if defined (INCL_WINSOCK)
|
|
sfPutSessionItem(sfhdl, SFID_CNCT_IPPORT, sizeof(hhDriver->iPort),
|
|
&hhDriver->iPort);
|
|
|
|
sfPutSessionItem(sfhdl, SFID_CNCT_IPDEST,
|
|
(lstrlen(hhDriver->achDestAddr) + 1) * sizeof(TCHAR),
|
|
hhDriver->achDestAddr);
|
|
#endif
|
|
|
|
/* --- Usual lines of code to use TAPI --- */
|
|
|
|
if (hhDriver->hLineApp && hhDriver->dwLine != (DWORD)-1 &&
|
|
!IN_RANGE(hhDriver->dwPermanentLineId, DIRECT_COM1, DIRECT_COM4) &&
|
|
hhDriver->dwPermanentLineId != DIRECT_COM_DEVICE &&
|
|
hhDriver->dwPermanentLineId != DIRECT_COMWINSOCK)
|
|
{
|
|
if ((pvs = malloc(sizeof(VARSTRING))) == 0)
|
|
{
|
|
assert(FALSE);
|
|
return 0;
|
|
}
|
|
|
|
memset( pvs, 0, sizeof(VARSTRING) );
|
|
pvs->dwTotalSize = sizeof(VARSTRING);
|
|
|
|
if (lineGetDevConfig(hhDriver->dwLine, pvs, DEVCLASS) != 0)
|
|
{
|
|
assert(FALSE);
|
|
free(pvs);
|
|
pvs = NULL;
|
|
return 0;
|
|
}
|
|
|
|
if (pvs->dwNeededSize > pvs->dwTotalSize)
|
|
{
|
|
dwSize = pvs->dwNeededSize;
|
|
free(pvs);
|
|
pvs = NULL;
|
|
|
|
if ((pvs = malloc(dwSize)) == 0)
|
|
{
|
|
assert(FALSE);
|
|
return 0;
|
|
}
|
|
|
|
memset( pvs, 0, dwSize );
|
|
pvs->dwTotalSize = dwSize;
|
|
|
|
if (lineGetDevConfig(hhDriver->dwLine, pvs, DEVCLASS) != 0)
|
|
{
|
|
assert(FALSE);
|
|
free(pvs);
|
|
pvs = NULL;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
/* --- Store the whole structure --- */
|
|
|
|
ul = pvs->dwTotalSize;
|
|
sfPutSessionItem(sfhdl, SFID_CNCT_TAPICONFIG, ul, pvs);
|
|
free(pvs);
|
|
pvs = NULL;
|
|
}
|
|
|
|
if ( IsNT() && hhDriver->dwPermanentLineId == DIRECT_COM_DEVICE)
|
|
{
|
|
ul = sizeof(hhDriver->achComDeviceName);
|
|
|
|
sfPutSessionItem(sfhdl, SFID_CNCT_COMDEVICE, ul,
|
|
hhDriver->achComDeviceName);
|
|
}
|
|
|
|
sfPutSessionItem(sfhdl, SFID_CNCT_CARRIERDETECT, sizeof(hhDriver->fCarrierDetect),
|
|
&hhDriver->fCarrierDetect);
|
|
|
|
return 0;
|
|
}
|
|
|
|
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
|
* FUNCTION:
|
|
* cnctdrvQueryStatus
|
|
*
|
|
* DESCRIPTION:
|
|
* Returns the current connection status as defined in <tdll\cnct.h>
|
|
*
|
|
* ARGUMENTS:
|
|
* hhDriver - private driver handle
|
|
*
|
|
* RETURNS:
|
|
* connection status or error code
|
|
*
|
|
*/
|
|
int WINAPI cnctdrvQueryStatus(const HHDRIVER hhDriver)
|
|
{
|
|
int iStatus = CNCT_STATUS_FALSE;
|
|
|
|
if (hhDriver == 0)
|
|
{
|
|
assert(FALSE);
|
|
iStatus = CNCT_BAD_HANDLE;
|
|
}
|
|
else
|
|
{
|
|
cnctdrvLock(hhDriver);
|
|
iStatus = hhDriver->iStatus; //* hard-code for now.
|
|
cnctdrvUnlock(hhDriver);
|
|
}
|
|
|
|
return iStatus;
|
|
}
|
|
|
|
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
|
* FUNCTION:
|
|
* SetStatus
|
|
*
|
|
* DESCRIPTION:
|
|
* There's actually more to setting the connection status than just
|
|
* setting the status variable as the code below indicates. Dumb
|
|
* question: Why aren't there any locks in this code. Dumb Answer:
|
|
* This function is only called from the ConnectLoop thread context
|
|
* which has already locked things down.
|
|
*
|
|
* ARGUMENTS:
|
|
* hhDriver - private driver handle
|
|
* iStatus - new status
|
|
*
|
|
* RETURNS:
|
|
* void
|
|
*
|
|
*/
|
|
void SetStatus(const HHDRIVER hhDriver, const int iStatus)
|
|
{
|
|
HCLOOP hCLoop;
|
|
/* --- Don't do things twice --- */
|
|
|
|
const HWND hwndToolbar = sessQueryHwndToolbar(hhDriver->hSession);
|
|
|
|
cnctdrvLock(hhDriver);
|
|
|
|
if (iStatus == hhDriver->iStatus)
|
|
{
|
|
if (iStatus == CNCT_STATUS_TRUE || iStatus == CNCT_STATUS_FALSE)
|
|
{
|
|
hCLoop = sessQueryCLoopHdl(hhDriver->hSession);
|
|
if (hCLoop)
|
|
CLoopSndControl(hCLoop, CLOOP_RESUME, CLOOP_SB_CNCTDRV);
|
|
}
|
|
|
|
cnctdrvUnlock(hhDriver);
|
|
return;
|
|
}
|
|
|
|
/* --- Set the status, an exciting new adventure game --- */
|
|
|
|
switch (iStatus)
|
|
{
|
|
case CNCT_STATUS_TRUE:
|
|
hCLoop = sessQueryCLoopHdl(hhDriver->hSession);
|
|
#ifdef INCL_CALL_ANSWERING
|
|
// If we are going from answering to connected, that means
|
|
// we have answered a call. So tweak the ASCII settings so
|
|
// that they make chatting possible. - cab:11/20/96
|
|
//
|
|
if (hhDriver->fAnswering)
|
|
{
|
|
// Store old ASCII settings, and set the new ones.
|
|
//
|
|
hhDriver->nSendCRLF = CLoopGetSendCRLF(hCLoop);
|
|
hhDriver->nLocalEcho = CLoopGetLocalEcho(hCLoop);
|
|
hhDriver->nAddLF = CLoopGetAddLF(hCLoop);
|
|
hhDriver->nEchoplex = CLoopGetEchoplex(hCLoop);
|
|
|
|
CLoopSetSendCRLF(hCLoop, TRUE);
|
|
CLoopSetLocalEcho(hCLoop, TRUE);
|
|
CLoopSetAddLF(hCLoop, TRUE);
|
|
CLoopSetEchoplex(hCLoop, TRUE);
|
|
|
|
hhDriver->fRestoreSettings = TRUE;
|
|
}
|
|
#endif
|
|
hhDriver->iStatus = CNCT_STATUS_TRUE;
|
|
assert(hCLoop);
|
|
if (hCLoop)
|
|
{
|
|
CLoopRcvControl(hCLoop, CLOOP_RESUME, CLOOP_RB_CNCTDRV);
|
|
CLoopSndControl(hCLoop, CLOOP_RESUME, CLOOP_SB_CNCTDRV);
|
|
}
|
|
|
|
NotifyClient(hhDriver->hSession, EVENT_CONNECTION_OPENED, 0);
|
|
sessBeeper(hhDriver->hSession);
|
|
ToolbarEnableButton(hwndToolbar, IDM_ACTIONS_DIAL, FALSE);
|
|
ToolbarEnableButton(hwndToolbar, IDM_ACTIONS_HANGUP, TRUE);
|
|
break;
|
|
|
|
case CNCT_STATUS_CONNECTING:
|
|
hhDriver->iStatus = CNCT_STATUS_CONNECTING;
|
|
DialingMessage(hhDriver, IDS_DIAL_OFFERING); // temp
|
|
NotifyClient(hhDriver->hSession, EVENT_CONNECTION_INPROGRESS, 0);
|
|
EnableDialNow(hhDriver->hwndCnctDlg, FALSE);
|
|
ToolbarEnableButton(hwndToolbar, IDM_ACTIONS_DIAL, FALSE);
|
|
ToolbarEnableButton(hwndToolbar, IDM_ACTIONS_HANGUP, TRUE);
|
|
break;
|
|
|
|
case CNCT_STATUS_DISCONNECTING:
|
|
hhDriver->iStatus = CNCT_STATUS_DISCONNECTING;
|
|
ToolbarEnableButton(hwndToolbar, IDM_ACTIONS_DIAL, FALSE);
|
|
ToolbarEnableButton(hwndToolbar, IDM_ACTIONS_HANGUP, FALSE);
|
|
break;
|
|
|
|
case CNCT_STATUS_FALSE:
|
|
hCLoop = sessQueryCLoopHdl(hhDriver->hSession);
|
|
#ifdef INCL_CALL_ANSWERING
|
|
// Since this is called when we disconnect we need to restore
|
|
// any ASCII Settings here. - cab:11/20/96
|
|
//
|
|
if ( hhDriver->fRestoreSettings && hCLoop ) //mpt: so that we don't reference a null pointer
|
|
{
|
|
CLoopSetSendCRLF(hCLoop, hhDriver->nSendCRLF);
|
|
CLoopSetLocalEcho(hCLoop, hhDriver->nLocalEcho);
|
|
CLoopSetAddLF(hCLoop, hhDriver->nAddLF);
|
|
CLoopSetEchoplex(hCLoop, hhDriver->nEchoplex);
|
|
hhDriver->fRestoreSettings = FALSE;
|
|
}
|
|
hhDriver->fAnswering = FALSE;
|
|
#endif
|
|
hhDriver->iStatus = CNCT_STATUS_FALSE;
|
|
if (hCLoop)
|
|
{
|
|
CLoopRcvControl(hCLoop, CLOOP_RESUME, CLOOP_RB_CNCTDRV);
|
|
CLoopSndControl(hCLoop, CLOOP_RESUME, CLOOP_SB_CNCTDRV);
|
|
}
|
|
NotifyClient(hhDriver->hSession, EVENT_CONNECTION_CLOSED, 0);
|
|
EnableDialNow(hhDriver->hwndCnctDlg, TRUE);
|
|
ToolbarEnableButton(hwndToolbar, IDM_ACTIONS_DIAL, TRUE);
|
|
ToolbarEnableButton(hwndToolbar, IDM_ACTIONS_HANGUP, FALSE);
|
|
break;
|
|
|
|
case CNCT_STATUS_ANSWERING:
|
|
#ifdef INCL_CALL_ANSWERING
|
|
hhDriver->fAnswering = TRUE;
|
|
hhDriver->iStatus = CNCT_STATUS_ANSWERING;
|
|
NotifyClient(hhDriver->hSession, EVENT_CONNECTION_INPROGRESS, 0);
|
|
ToolbarEnableButton(hwndToolbar, IDM_ACTIONS_DIAL, FALSE);
|
|
ToolbarEnableButton(hwndToolbar, IDM_ACTIONS_HANGUP, TRUE);
|
|
#endif
|
|
break;
|
|
|
|
default:
|
|
assert(FALSE);
|
|
break;
|
|
}
|
|
|
|
cnctdrvUnlock(hhDriver);
|
|
|
|
/* --- Notify status bar so it can update it's display --- */
|
|
|
|
PostMessage(sessQueryHwndStatusbar(hhDriver->hSession), SBR_NTFY_REFRESH,
|
|
(WPARAM)SBR_CNCT_PART_NO, 0);
|
|
|
|
return;
|
|
}
|
|
|
|
#ifdef INCL_CALL_ANSWERING
|
|
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
|
* FUNCTION:
|
|
* WaitForCRcallback
|
|
*
|
|
* DESCRIPTION:
|
|
* This function gets registered as a callback with the cloop. Every
|
|
* character that the cloop gets, is passed back to this function. When
|
|
* this function finds a CR, it indicates that a connection has been
|
|
* established. Note that this applies only to an answer mode connection,
|
|
* in the direct connect driver.
|
|
*
|
|
* ARGUMENTS:
|
|
* ECHAR ech - The character returned from cloop.
|
|
* void *p - A void pointer passed back from cloop. This is
|
|
* the enternal connection driver handle.
|
|
*
|
|
* RETURNS:
|
|
* CLOOP_DISCARD unless the character is a CR where is returns CLOOP_KEEP.
|
|
*
|
|
* AUTHOR: C. Baumgartner, 11/20/96 (ported from HAWin32)
|
|
*/
|
|
int WaitForCRcallback(ECHAR ech, void *p)
|
|
{
|
|
int iRet = CLOOP_DISCARD; // Discard all characters except the CR.
|
|
TCHAR chC = (TCHAR) ech;
|
|
const HHDRIVER hhDriver = (HHDRIVER)p;
|
|
|
|
if (chC == TEXT('\r'))
|
|
{
|
|
CLoopUnregisterRmtInputChain(hhDriver->pvUnregister);
|
|
hhDriver->pvUnregister = 0;
|
|
|
|
// Okay, we are connected now.
|
|
//
|
|
SetStatus(hhDriver, CNCT_STATUS_TRUE);
|
|
|
|
iRet = CLOOP_KEEP;
|
|
}
|
|
|
|
return iRet;
|
|
}
|
|
|
|
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
|
* FUNCTION:
|
|
* WaitForCRinit
|
|
*
|
|
* DESCRIPTION:
|
|
* This function is called to register a new string match function
|
|
* with the cloop. It unregisters a previously registered function
|
|
* if necessary. It basically will cause us to wait for a carriage
|
|
* return.
|
|
*
|
|
* ARGUMENTS:
|
|
* HHDRIVER hhDriver - The internal connection handle.
|
|
*
|
|
* RETURNS:
|
|
* 0 if successful, otherwise -1.
|
|
*
|
|
* AUTHOR: C. Baumgartner, 11/20/96 (ported from HAWin32)
|
|
*/
|
|
static int WaitForCRinit(const HHDRIVER hhDriver)
|
|
{
|
|
const HCLOOP hCLoop = sessQueryCLoopHdl(hhDriver->hSession);
|
|
|
|
if (!hCLoop)
|
|
{
|
|
return -1;
|
|
}
|
|
|
|
// If we are already registered, unregister.
|
|
//
|
|
if (hhDriver->pvUnregister != 0)
|
|
{
|
|
CLoopUnregisterRmtInputChain(hhDriver->pvUnregister);
|
|
hhDriver->pvUnregister = 0;
|
|
}
|
|
|
|
// We need to un-block CLoop so we can look at the
|
|
// characters as they come in.
|
|
//
|
|
CLoopRcvControl(hCLoop, CLOOP_RESUME, CLOOP_RB_CNCTDRV);
|
|
|
|
// Register the match function with the cloop.
|
|
//
|
|
hhDriver->pvUnregister = CLoopRegisterRmtInputChain(hCLoop,
|
|
WaitForCRcallback, hhDriver);
|
|
|
|
if (hhDriver->pvUnregister == 0)
|
|
{
|
|
return -1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
#endif
|
|
|
|
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
|
* FUNCTION:
|
|
* cnctdrvComEvent
|
|
*
|
|
* DESCRIPTION:
|
|
* Com routines call the this to notify connection routines that some
|
|
* significant event has happened (ie. carrier lost). The connetion
|
|
* driver decides what it is interested in knowing however by
|
|
* querying the com drivers for the specific data.
|
|
*
|
|
* ARGUMENTS:
|
|
* hhDriver - private connection driver handle
|
|
* event - the com event we are being notified of
|
|
*
|
|
* RETURNS:
|
|
* 0
|
|
*
|
|
*/
|
|
int WINAPI cnctdrvComEvent(const HHDRIVER hhDriver, const enum COM_EVENTS event)
|
|
{
|
|
int iRet;
|
|
TCHAR ach[MAX_PATH];
|
|
#if defined(INCL_WINSOCK)
|
|
char achMsg[512];
|
|
#endif
|
|
HCOM hCom;
|
|
|
|
if (hhDriver == 0)
|
|
{
|
|
assert(FALSE);
|
|
return CNCT_BAD_HANDLE;
|
|
}
|
|
|
|
if (event == CONNECT)
|
|
{
|
|
#if defined (INCL_WINSOCK)
|
|
// If we are connected via Winsock, there will be some ComEvents
|
|
// that we have to handle
|
|
if (hhDriver->dwPermanentLineId == DIRECT_COMWINSOCK)
|
|
{
|
|
hCom = sessQueryComHdl(hhDriver->hSession);
|
|
iRet = ComDriverSpecial(hCom, "Query ISCONNECTED", ach, MAX_PATH);
|
|
|
|
if (iRet == COM_OK)
|
|
{
|
|
int iPortOpen = atoi(ach);
|
|
// Do we want to initiate a disconnect? Only if we're
|
|
// connected.
|
|
if (iPortOpen == COM_PORT_NOT_OPEN)
|
|
{
|
|
if (hhDriver->iStatus == CNCT_STATUS_TRUE)
|
|
{
|
|
// If we are already connected, then beep when
|
|
// we disconnect. - cab:12/06/96
|
|
//
|
|
//mpt:10-28-97 added exit upon disconnect feature
|
|
NotifyClient(hhDriver->hSession, EVENT_LOST_CONNECTION,
|
|
CNCT_LOSTCARRIER | (sessQueryExit(hhDriver->hSession) ? DISCNCT_EXIT : 0 ));
|
|
}
|
|
else if (hhDriver->iStatus == CNCT_STATUS_CONNECTING)
|
|
{
|
|
NotifyClient(hhDriver->hSession, EVENT_LOST_CONNECTION,
|
|
CNCT_LOSTCARRIER | DISCNCT_NOBEEP);
|
|
|
|
LoadString(glblQueryDllHinst(), IDS_ER_TCPIP_BADADDR, ach, MAX_PATH);
|
|
wsprintf(achMsg, ach, hhDriver->achDestAddr, hhDriver->iPort);
|
|
TimedMessageBox(sessQueryHwnd(hhDriver->hSession),
|
|
achMsg, NULL, MB_OK | MB_ICONINFORMATION,
|
|
sessQueryTimeout(hhDriver->hSession));
|
|
}
|
|
}
|
|
else if (iPortOpen == COM_PORT_OPEN)
|
|
{
|
|
SetStatus(hhDriver, CNCT_STATUS_TRUE);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
#endif // defined (INCL_WINSOCK)
|
|
if (IN_RANGE(hhDriver->dwPermanentLineId, DIRECT_COM1, DIRECT_COM4) ||
|
|
hhDriver->dwPermanentLineId == DIRECT_COM_DEVICE)
|
|
{
|
|
// Checking the status of DCD before disconnecting
|
|
// is a good idea, prevents us hanging up whenever we
|
|
// get any event while connected
|
|
// - mpt:08-26-97
|
|
hCom = sessQueryComHdl(hhDriver->hSession);
|
|
iRet = ComDriverSpecial(hCom, "Query DCD_STATUS", ach, MAX_PATH);
|
|
|
|
if (iRet == COM_OK)
|
|
{
|
|
int iPortOpen = atoi(ach);
|
|
// Do we want to initiate a disconnect? Only if we're
|
|
// connected.
|
|
if (iPortOpen == COM_PORT_NOT_OPEN)
|
|
{
|
|
if (hhDriver->iStatus == CNCT_STATUS_TRUE)
|
|
{
|
|
// If we are direct cabled, and we're connected, then
|
|
// the other end just disconnected, so disconnect now.
|
|
// - cab:11/20/96
|
|
//
|
|
// Note: We must disconnect by posting a message to
|
|
// thread one. This is because if we get here, we were
|
|
// called from the context of the com thread, which
|
|
// will not exit properly if cnctdrvDisconnect is called.
|
|
// - cab:11/21/96
|
|
//
|
|
//
|
|
// If we are already connected, then beep when
|
|
// we disconnect. - cab:12/06/96
|
|
//
|
|
//mpt:10-28-97 added exit upon disconnect feature
|
|
NotifyClient(hhDriver->hSession, EVENT_LOST_CONNECTION,
|
|
CNCT_LOSTCARRIER | (sessQueryExit(hhDriver->hSession) ? DISCNCT_EXIT : 0 ));
|
|
}
|
|
#if defined(INCL_CALL_ANSWERING)
|
|
else if (hhDriver->iStatus == CNCT_STATUS_CONNECTING ||
|
|
hhDriver->iStatus == CNCT_STATUS_ANSWERING)
|
|
#else // defined(INCL_CALL_ANSWERING)
|
|
else if (hhDriver->iStatus == CNCT_STATUS_CONNECTING)
|
|
#endif // defined(INCL_CALL_ANSWERING)
|
|
{
|
|
NotifyClient(hhDriver->hSession, EVENT_LOST_CONNECTION,
|
|
CNCT_LOSTCARRIER | DISCNCT_NOBEEP);
|
|
|
|
LoadString(glblQueryDllHinst(), IDS_ER_CNCT_PORTFAILED, ach, MAX_PATH);
|
|
wsprintf(achMsg, ach, hhDriver->achComDeviceName);
|
|
TimedMessageBox(sessQueryHwnd(hhDriver->hSession),
|
|
achMsg, NULL, MB_OK | MB_ICONINFORMATION,
|
|
sessQueryTimeout(hhDriver->hSession));
|
|
}
|
|
}
|
|
else if (iPortOpen == COM_PORT_OPEN &&
|
|
hhDriver->iStatus != CNCT_STATUS_ANSWERING)
|
|
{
|
|
SetStatus(hhDriver, CNCT_STATUS_TRUE);
|
|
}
|
|
}
|
|
#if defined(INCL_CALL_ANSWERING)
|
|
if (hhDriver->iStatus == CNCT_STATUS_ANSWERING)
|
|
{
|
|
// If we are a direct cabled connection, and we are waiting
|
|
// for a call, connect when we see a carriage return.
|
|
//
|
|
WaitForCRinit(hhDriver);
|
|
}
|
|
#endif // defined(INCL_CALL_ANSWERING)
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
|
* FUNCTION:
|
|
* DoAnswerCall
|
|
*
|
|
* DESCRIPTION:
|
|
* Sets up TAPI to answer the next data modem call.
|
|
*
|
|
* ARGUMENTS:
|
|
* hhDriver - private driver handle
|
|
*
|
|
* RETURNS:
|
|
* 0 or error
|
|
*
|
|
* AUTHOR: C. Baumgartner, 11/25/96 (ported from HAWin32)
|
|
*/
|
|
int DoAnswerCall(const HHDRIVER hhDriver)
|
|
{
|
|
TCHAR ach[256];
|
|
|
|
// Believe it or not, this is all one has to do to setup and
|
|
// answer a call. Quite a contrast to placing a call.
|
|
//
|
|
if (TRAP(lineOpen(hhDriver->hLineApp, hhDriver->dwLine, &hhDriver->hLine,
|
|
hhDriver->dwAPIVersion, 0, (DWORD_PTR)hhDriver, LINECALLPRIVILEGE_OWNER,
|
|
LINEMEDIAMODE_DATAMODEM, 0)) != 0)
|
|
{
|
|
assert(0);
|
|
LoadString(glblQueryDllHinst(), IDS_ER_CNCT_TAPIFAILED, ach, sizeof(ach) / sizeof(TCHAR));
|
|
TimedMessageBox(sessQueryHwnd(hhDriver->hSession), ach, NULL,
|
|
MB_OK | MB_ICONINFORMATION | MB_TASKMODAL,
|
|
sessQueryTimeout(hhDriver->hSession));
|
|
return -1;
|
|
}
|
|
|
|
// The the line app priority for compliance with TAPI specifications.
|
|
// mrw:9/18/96
|
|
//
|
|
LoadString(glblQueryDllHinst(), IDS_GNRL_APPNAME, ach, sizeof(ach) / sizeof(TCHAR));
|
|
TRAP(lineSetAppPriority(ach, LINEMEDIAMODE_DATAMODEM, 0, 0, 0, 1));
|
|
|
|
// Set line notifications we want to receive
|
|
//
|
|
TRAP(lineSetStatusMessages(hhDriver->hLine, LINEDEVSTATE_RINGING, 0));
|
|
|
|
SetStatus(hhDriver, CNCT_STATUS_ANSWERING);
|
|
return 0;
|
|
}
|
|
|
|
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
|
* FUNCTION:
|
|
* DoMakeCall
|
|
*
|
|
* DESCRIPTION:
|
|
* Performs the neccessary TAPI rituals to place an outbound call.
|
|
*
|
|
* ARGUMENTS:
|
|
* hhDriver - private driver handle
|
|
* uFlags - connection flags
|
|
*
|
|
* RETURNS:
|
|
* 0 or error
|
|
*
|
|
* AUTHOR: C. Baumgartner, 11/25/96 (ported from cnctdrvConnect)
|
|
*/
|
|
int DoMakeCall(const HHDRIVER hhDriver, const unsigned int uFlags)
|
|
{
|
|
unsigned int uidErr = 0;
|
|
int iRet = 0;
|
|
LINEDEVSTATUS stLnDevStat;
|
|
TCHAR ach[256];
|
|
BOOL msgFlag = FALSE;
|
|
|
|
tapiReinit(hhDriver);
|
|
|
|
//
|
|
// Set the line settings.
|
|
//
|
|
if (cncttapiSetLineConfig(hhDriver->dwLine, sessQueryComHdl(hhDriver->hSession)) != 0)
|
|
{
|
|
assert(0);
|
|
uidErr = IDS_ER_CNCT_TAPIFAILED;
|
|
iRet = -1;
|
|
msgFlag = TRUE;
|
|
goto ERROR_EXIT;
|
|
}
|
|
|
|
/* --- Open the line, pass driver handle for data reference --- */
|
|
|
|
if (TRAP(lineOpen(hhDriver->hLineApp, hhDriver->dwLine,
|
|
&hhDriver->hLine, hhDriver->dwAPIVersion, 0, (DWORD_PTR)hhDriver,
|
|
LINECALLPRIVILEGE_NONE, 0, 0)) != 0)
|
|
{
|
|
assert(0);
|
|
uidErr = IDS_ER_CNCT_TAPIFAILED;
|
|
iRet = -1;
|
|
msgFlag = TRUE;
|
|
goto ERROR_EXIT;
|
|
}
|
|
|
|
/* --- Set line notifications we want to receive, mrw,2/28/95 --- */
|
|
|
|
TRAP(lineSetStatusMessages(hhDriver->hLine,
|
|
LINEDEVSTATE_INSERVICE | LINEDEVSTATE_OUTOFSERVICE, 0));
|
|
|
|
/* --- Check if our device is in service, mrw,2/28/95 --- */
|
|
|
|
stLnDevStat.dwTotalSize = sizeof(stLnDevStat);
|
|
TRAP(lineGetLineDevStatus(hhDriver->hLine, &stLnDevStat));
|
|
|
|
if ((stLnDevStat.dwDevStatusFlags & LINEDEVSTATUSFLAGS_INSERVICE) == 0)
|
|
{
|
|
if (DialogBoxParam(glblQueryDllHinst(),
|
|
MAKEINTRESOURCE(IDD_CNCT_PCMCIA),
|
|
sessQueryHwnd(hhDriver->hSession), PCMCIADlg,
|
|
(LPARAM)hhDriver) == FALSE)
|
|
{
|
|
iRet = -2;
|
|
goto ERROR_EXIT;
|
|
}
|
|
}
|
|
|
|
/* --- Launch the dialing dialog, or go right into passthrough mode. --- */
|
|
|
|
if ((uFlags & CNCT_PORTONLY) == 0)
|
|
{
|
|
if (!IsWindow(hhDriver->hwndCnctDlg))
|
|
{
|
|
hhDriver->hwndCnctDlg = DoModelessDialog(glblQueryDllHinst(),
|
|
MAKEINTRESOURCE(IDD_DIALING), sessQueryHwnd(hhDriver->hSession),
|
|
DialingDlg, (LPARAM)hhDriver);
|
|
}
|
|
}
|
|
|
|
/* --- Make the call (oooh, how exciting!) --- */
|
|
|
|
memset(&hhDriver->stCallPar, 0, sizeof(hhDriver->stCallPar));
|
|
hhDriver->stCallPar.dwTotalSize = sizeof(hhDriver->stCallPar);
|
|
hhDriver->stCallPar.dwMediaMode = LINEMEDIAMODE_DATAMODEM;
|
|
hhDriver->stCallPar.dwCallParamFlags = LINECALLPARAMFLAGS_IDLE;
|
|
|
|
if (uFlags & CNCT_PORTONLY)
|
|
hhDriver->stCallPar.dwBearerMode = LINEBEARERMODE_PASSTHROUGH;
|
|
|
|
if ((hhDriver->lMakeCallId = lineMakeCall(hhDriver->hLine,
|
|
&hhDriver->hCall, hhDriver->achDialableDest,
|
|
hhDriver->dwCountryCode, &hhDriver->stCallPar)) < 0)
|
|
{
|
|
#if defined(_DEBUG)
|
|
char ach[50];
|
|
wsprintf(ach, "lineMakeCall returned %x", hhDriver->lMakeCallId);
|
|
MessageBox (0, ach, "debug", MB_OK);
|
|
#endif
|
|
|
|
switch (hhDriver->lMakeCallId)
|
|
{
|
|
case LINEERR_BEARERMODEUNAVAIL:
|
|
case LINEERR_INVALBEARERMODE:
|
|
uidErr = IDS_ER_CNCT_PASSTHROUGH;
|
|
iRet = -6;
|
|
msgFlag = TRUE;
|
|
goto ERROR_EXIT;
|
|
|
|
case LINEERR_RESOURCEUNAVAIL:
|
|
case LINEERR_CALLUNAVAIL:
|
|
uidErr = IDS_ER_CNCT_CALLUNAVAIL;
|
|
iRet = -3;
|
|
msgFlag = TRUE;
|
|
goto ERROR_EXIT;
|
|
|
|
case LINEERR_DIALDIALTONE:
|
|
case LINEERR_DIALPROMPT:
|
|
if (DoDelayedCall(hhDriver) != 0)
|
|
{
|
|
iRet = -4;
|
|
msgFlag = TRUE;
|
|
goto ERROR_EXIT;
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
iRet = -5;
|
|
msgFlag = TRUE;
|
|
goto ERROR_EXIT;
|
|
}
|
|
}
|
|
|
|
SetStatus(hhDriver, CNCT_STATUS_CONNECTING);
|
|
return 0;
|
|
|
|
/* --- Error exit --- */
|
|
|
|
ERROR_EXIT:
|
|
|
|
// Change this so that the dialog is destroyed before the
|
|
// error message is displayed. Otherwise, the timer that
|
|
// handled redials continued to pump a redial message once
|
|
// every second, causing HT to go into a very nasty loop. mpt 02SEP98
|
|
|
|
if (IsWindow(hhDriver->hwndCnctDlg))
|
|
{
|
|
EndModelessDialog(hhDriver->hwndCnctDlg);
|
|
hhDriver->hwndCnctDlg = 0;
|
|
}
|
|
|
|
if ( msgFlag )
|
|
{
|
|
LoadString(glblQueryDllHinst(), uidErr, ach, sizeof(ach) / sizeof(TCHAR));
|
|
|
|
TimedMessageBox(sessQueryHwnd(hhDriver->hSession), ach, NULL,
|
|
MB_OK | MB_ICONINFORMATION | MB_TASKMODAL,
|
|
sessQueryTimeout(hhDriver->hSession));
|
|
}
|
|
|
|
return iRet;
|
|
}
|
|
|
|
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
|
* FUNCTION:
|
|
* cnctdrvConnect
|
|
*
|
|
* DESCRIPTION:
|
|
* Attempts to dial the modem.
|
|
*
|
|
* ARGUMENTS:
|
|
* hhDriver - private driver handle
|
|
* uFlags - connection flags
|
|
*
|
|
* RETURNS:
|
|
* 0 or error
|
|
*
|
|
*/
|
|
int WINAPI cnctdrvConnect(const HHDRIVER hhDriver, const unsigned int uFlags)
|
|
{
|
|
TCHAR ach[FNAME_LEN];
|
|
#if defined(INCL_WINSOCK)
|
|
//
|
|
// MAX_IP_ADDR_LEN+11+1 = buffer size of hhDriver->achDestAddr +
|
|
// settings string "SET IPADDR=" + 1 for the terminating NULL
|
|
// character. REV 09/20/2000
|
|
//
|
|
TCHAR szInstruct[MAX_IP_ADDR_LEN+11+1]; // Used only for WinSock
|
|
TCHAR szResult[MAX_IP_ADDR_LEN+11+1]; // Used only for WinSock
|
|
int iNumChars;
|
|
#endif //defined (INCL_WINSOCK)
|
|
TCHAR achNewCnct[FNAME_LEN];
|
|
TCHAR achCom[MAX_PATH];
|
|
BOOL fGetNewName = FALSE;
|
|
HICON hIcon;
|
|
HCOM hCom;
|
|
int hIconId;
|
|
int fFlag;
|
|
unsigned int uidErr = IDS_ER_CNCT_TAPIFAILED;
|
|
|
|
if (hhDriver == 0)
|
|
{
|
|
assert(FALSE);
|
|
return CNCT_BAD_HANDLE;
|
|
}
|
|
|
|
/* --- Makes for easier referencing --- */
|
|
|
|
hCom = sessQueryComHdl(hhDriver->hSession);
|
|
|
|
/* --- Check to see we're not already connected --- */
|
|
|
|
if (cnctdrvQueryStatus(hhDriver) != CNCT_STATUS_FALSE)
|
|
return CNCT_ERROR;
|
|
|
|
// JMH 05-29-96 This is needed to prevent CLoop from processing
|
|
// activity on the terminal window while TAPI is connecting.
|
|
//
|
|
CLoopRcvControl(sessQueryCLoopHdl(hhDriver->hSession),
|
|
CLOOP_SUSPEND,
|
|
CLOOP_RB_CNCTDRV);
|
|
CLoopSndControl(sessQueryCLoopHdl(hhDriver->hSession),
|
|
CLOOP_SUSPEND,
|
|
CLOOP_SB_CNCTDRV);
|
|
|
|
/* --- Just on the off chance we still have an open line --- */
|
|
|
|
if (hhDriver->hLineApp && hhDriver->hLine)
|
|
{
|
|
lineClose(hhDriver->hLine);
|
|
memset(&hhDriver->stCallPar, 0, sizeof(hhDriver->stCallPar));
|
|
hhDriver->stCallPar.dwTotalSize = sizeof(hhDriver->stCallPar);
|
|
hhDriver->stCallPar.dwMediaMode = LINEMEDIAMODE_DATAMODEM;
|
|
hhDriver->stCallPar.dwCallParamFlags = LINECALLPARAMFLAGS_IDLE;
|
|
hhDriver->stCallPar.dwBearerMode = 0;
|
|
hhDriver->hLine = 0;
|
|
}
|
|
|
|
if (hhDriver->hLineApp && hhDriver->dwLineCnt == 0 &&
|
|
(uFlags & CNCT_PORTONLY) == 0)
|
|
{
|
|
DoNewModemWizard(sessQueryHwnd(hhDriver->hSession),
|
|
sessQueryTimeout(hhDriver->hSession));
|
|
}
|
|
|
|
/* --- Ask for new session name only if needed --- */
|
|
|
|
sessQueryName(hhDriver->hSession, ach, sizeof(ach));
|
|
|
|
achNewCnct[0] = TEXT('\0');
|
|
LoadString(glblQueryDllHinst(), IDS_GNRL_NEW_CNCT, achNewCnct,
|
|
sizeof(achNewCnct) / sizeof(TCHAR));
|
|
|
|
if (ach[0] == TEXT('\0') || lstrcmp(achNewCnct, ach) == 0)
|
|
{
|
|
// This can only happen if the user double-clicks on the term.exe or
|
|
// there is no session name given on the command line.
|
|
// In this case give the "New Connection" name to the session.
|
|
//
|
|
sessSetName(hhDriver->hSession, achNewCnct);
|
|
|
|
if (!(uFlags & CNCT_PORTONLY))
|
|
fGetNewName = TRUE;
|
|
}
|
|
else if (uFlags & CNCT_NEW)
|
|
{
|
|
// This can only happen if the user selects 'File | New Connection'
|
|
// from the menus.
|
|
//
|
|
sessSetName(hhDriver->hSession, achNewCnct);
|
|
sessSetIsNewSession(hhDriver->hSession, TRUE);
|
|
}
|
|
#if defined (INCL_WINSOCK)
|
|
else if (uFlags & CNCT_WINSOCK)
|
|
{
|
|
//
|
|
// Make sure we don't overwrite the buffer. If the string
|
|
// is too long, then truncate to the hhDriver->achDestAddr
|
|
// size of MAX_AP_ADDR_LEN. REV 09/20/2000
|
|
//
|
|
StrCharCopyN(hhDriver->achDestAddr, ach, MAX_IP_ADDR_LEN);
|
|
hhDriver->achDestAddr[MAX_IP_ADDR_LEN - 1] = TEXT('\0');
|
|
hhDriver->dwPermanentLineId = DIRECT_COMWINSOCK;
|
|
}
|
|
#endif // defined (INCL_WINSOCK)
|
|
|
|
if (fGetNewName || (uFlags & CNCT_NEW))
|
|
{
|
|
if (DialogBoxParam(glblQueryDllHinst(), MAKEINTRESOURCE(IDD_NEWCONNECTION),
|
|
sessQueryHwnd(hhDriver->hSession), NewConnectionDlg,
|
|
(LPARAM)hhDriver->hSession) == FALSE)
|
|
{
|
|
if (uFlags & CNCT_NEW)
|
|
{
|
|
sessQueryOldName(hhDriver->hSession, ach, sizeof(ach));
|
|
sessSetName(hhDriver->hSession, ach);
|
|
sessSetIsNewSession(hhDriver->hSession, FALSE);
|
|
}
|
|
goto ERROR_EXIT;
|
|
}
|
|
else
|
|
{
|
|
if (uFlags & CNCT_NEW)
|
|
{
|
|
sessQueryName(hhDriver->hSession, ach, sizeof(ach));
|
|
hIcon = sessQueryIcon(hhDriver->hSession);
|
|
hIconId = sessQueryIconID(hhDriver->hSession);
|
|
|
|
ReinitializeSessionHandle(hhDriver->hSession, FALSE);
|
|
CLoopSndControl(sessQueryCLoopHdl(hhDriver->hSession),
|
|
CLOOP_SUSPEND,
|
|
CLOOP_SB_CNCTDRV);
|
|
|
|
sessSetName(hhDriver->hSession, ach);
|
|
sessSetIconID(hhDriver->hSession, hIconId);
|
|
}
|
|
}
|
|
}
|
|
|
|
/* --- Load the Standard Com drivers --- */
|
|
|
|
ComLoadStdcomDriver(hCom);
|
|
|
|
// There are a bunch of conditions that can trigger the
|
|
// phone dialog.
|
|
//
|
|
fFlag = FALSE;
|
|
|
|
// If no phone number, bring up new phone dialog here
|
|
// Unless we have a direct to com port selected
|
|
//
|
|
// Don't display the dialog if we are answering, because
|
|
// we don't need a phone number. - cab:11/19/96
|
|
//
|
|
|
|
if (!IN_RANGE(hhDriver->dwPermanentLineId, DIRECT_COM1, DIRECT_COM4) &&
|
|
hhDriver->dwPermanentLineId != DIRECT_COM_DEVICE &&
|
|
!(uFlags & (CNCT_PORTONLY | CNCT_ANSWER)))
|
|
{
|
|
#ifdef INCL_WINSOCK
|
|
// If the driver is WinSock, then check for a
|
|
// destination IP address. - cab:11/19/96
|
|
//
|
|
if (hhDriver->dwPermanentLineId == DIRECT_COMWINSOCK &&
|
|
hhDriver->achDestAddr[0] == TEXT('\0'))
|
|
{
|
|
fFlag = TRUE;
|
|
}
|
|
#endif // defined (INCL_WINSOCK)
|
|
// If the driver isn't WinSock, then we must be using
|
|
// TAPI, so check for a destination phone number. - cab:11/19/96
|
|
//
|
|
if (hhDriver->dwPermanentLineId != DIRECT_COMWINSOCK &&
|
|
(hhDriver->achDest[0] == TEXT('\0') ||
|
|
hhDriver->achDialableDest[0] == TEXT('\0') ||
|
|
hhDriver->achCanonicalDest[0] == TEXT('\0')))
|
|
{
|
|
fFlag = TRUE;
|
|
}
|
|
}
|
|
|
|
// New connections trigger this dialog
|
|
//
|
|
if (uFlags & CNCT_NEW)
|
|
fFlag = TRUE;
|
|
|
|
// If the modem/port we saved no longer exists
|
|
//
|
|
//if (!hhDriver->fMatchedPermanentLineID)
|
|
// fFlag = TRUE;
|
|
|
|
// Note: Passing the property sheet page here because property
|
|
// sheets use same code and don't have access directly
|
|
// to the private driver handle. Upper wacker will have
|
|
// to address the problem differently - mrw.
|
|
|
|
if (fFlag)
|
|
{
|
|
PROPSHEETPAGE psp;
|
|
|
|
// Before you go and critize this goto target come talk to
|
|
// me. There are enough things going on here that a goto
|
|
// is warranted in my humble opinion. - mrw
|
|
|
|
NEWPHONEDLG:
|
|
|
|
psp.lParam = (LPARAM)hhDriver->hSession;
|
|
|
|
if (DialogBoxParam(glblQueryDllHinst(),
|
|
MAKEINTRESOURCE(IDD_CNCT_NEWPHONE),
|
|
sessQueryHwnd(hhDriver->hSession), NewPhoneDlg,
|
|
(LPARAM)&psp) == FALSE)
|
|
{
|
|
goto ERROR_EXIT;
|
|
}
|
|
else if (IN_RANGE(hhDriver->dwPermanentLineId, DIRECT_COM1, DIRECT_COM4) ||
|
|
(IsNT() && hhDriver->dwPermanentLineId == DIRECT_COM_DEVICE))
|
|
{
|
|
//
|
|
// See if the "Configure..." button has already been clicked
|
|
// and the ComDeviceDialog() function has already been called
|
|
// for this COM device.
|
|
//
|
|
TCHAR szPortName[MAX_PATH];
|
|
|
|
ComGetPortName(hCom, szPortName, MAX_PATH);
|
|
|
|
if (StrCharCmp(szPortName, hhDriver->achComDeviceName) != 0 )
|
|
{
|
|
/* --- Bring up the port configure dialog --- */
|
|
if (hhDriver->dwPermanentLineId == DIRECT_COM_DEVICE)
|
|
{
|
|
ComSetPortName(hCom, hhDriver->achComDeviceName);
|
|
}
|
|
else
|
|
{
|
|
wsprintf(ach, TEXT("COM%d"),
|
|
hhDriver->dwPermanentLineId - DIRECT_COM1 + 1);
|
|
ComSetPortName(hCom, ach);
|
|
}
|
|
|
|
//
|
|
// Get the current defaults for the serial port.
|
|
//
|
|
if (ComDriverSpecial(hCom, "GET Defaults", NULL, 0) != COM_OK)
|
|
{
|
|
if (ComDeviceDialog(hCom, sessQueryHwnd(hhDriver->hSession))
|
|
!= COM_OK)
|
|
{
|
|
goto ERROR_EXIT;
|
|
}
|
|
}
|
|
|
|
if (ComDeviceDialog(hCom, sessQueryHwnd(hhDriver->hSession))
|
|
!= COM_OK)
|
|
{
|
|
// User canceled
|
|
// --jcm 3-2-95
|
|
//return CNCT_BAD_HANDLE;
|
|
}
|
|
}
|
|
}
|
|
#if defined(INCL_WINSOCK) // mrw:3/5/96
|
|
else if (hhDriver->dwPermanentLineId == DIRECT_COMWINSOCK)
|
|
{
|
|
if (hhDriver->achDestAddr[0] == TEXT('\0'))
|
|
{
|
|
LoadString(glblQueryDllHinst(), IDS_ER_TCPIP_MISSING_ADDR,
|
|
ach, sizeof(ach) / sizeof(TCHAR));
|
|
|
|
TimedMessageBox(sessQueryHwnd(hhDriver->hSession), ach, NULL,
|
|
MB_OK | MB_ICONINFORMATION,
|
|
sessQueryTimeout(hhDriver->hSession));
|
|
|
|
goto NEWPHONEDLG;
|
|
}
|
|
}
|
|
#endif
|
|
else
|
|
{
|
|
// mrw: Check that we have valid data.
|
|
//
|
|
if (hhDriver->achDest[0] == TEXT('\0'))
|
|
{
|
|
LoadString(glblQueryDllHinst(), IDS_ER_CNCT_BADADDRESS, ach,
|
|
sizeof(ach) / sizeof(TCHAR));
|
|
|
|
TimedMessageBox(sessQueryHwnd(hhDriver->hSession), ach, NULL,
|
|
MB_OK | MB_ICONINFORMATION,
|
|
sessQueryTimeout(hhDriver->hSession));
|
|
|
|
// goto ERROR_EXIT; // mrw:3/5/96
|
|
goto NEWPHONEDLG; // mrw:3/5/96
|
|
}
|
|
}
|
|
}
|
|
|
|
/* --- Enumerate lines, picks default (set in hhDriver->dwLine) --- */
|
|
|
|
if ( IsNT() )
|
|
{
|
|
if (EnumerateLinesNT(hhDriver, 0) != 0)
|
|
{
|
|
assert(FALSE);
|
|
goto MSG_EXIT;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (EnumerateLines(hhDriver, 0) != 0)
|
|
{
|
|
assert(FALSE);
|
|
goto MSG_EXIT;
|
|
}
|
|
}
|
|
|
|
|
|
/* --- If we don't match any TAPI lines, go back to new phone --- */
|
|
|
|
if (hhDriver->dwLine == (DWORD)-1)
|
|
{
|
|
//
|
|
// If this is not a modem (it is a COM port), then display the modem
|
|
// wizard, otherwise just go back to the new phone. REV: 11/1/2001
|
|
//
|
|
if (!IN_RANGE(hhDriver->dwPermanentLineId, DIRECT_COM1, DIRECT_COM4) &&
|
|
hhDriver->dwPermanentLineId != DIRECT_COM_DEVICE )
|
|
{
|
|
DoNewModemWizard(sessQueryHwnd(hhDriver->hSession),
|
|
sessQueryTimeout(hhDriver->hSession));
|
|
}
|
|
|
|
goto NEWPHONEDLG;
|
|
}
|
|
|
|
/* --- Redraw window now so dialogs don't overlap ---- */
|
|
|
|
UpdateWindow(sessQueryHwnd(hhDriver->hSession));
|
|
|
|
/* --- Check if we're doing a direct connect or using passthrough mode --- */
|
|
|
|
if (IsNT() && hhDriver->dwPermanentLineId == DIRECT_COM_DEVICE)
|
|
{
|
|
int iActivatePortReturn = IDS_ER_CNCT_PORTFAILED;
|
|
if (TRAP(ComSetPortName(hCom, hhDriver->achComDeviceName)) != COM_OK ||
|
|
(iActivatePortReturn = TRAP(ComActivatePort(hCom, 0))) != COM_OK)
|
|
{
|
|
if (iActivatePortReturn == COM_PORT_IN_USE)
|
|
{
|
|
LoadString(glblQueryDllHinst(), IDS_ER_CNCT_CALLUNAVAIL,
|
|
ach, sizeof(ach) / sizeof(TCHAR));
|
|
}
|
|
else
|
|
{
|
|
LoadString(glblQueryDllHinst(), IDS_ER_CNCT_PORTFAILED,
|
|
achNewCnct, sizeof(achNewCnct) / sizeof(TCHAR));
|
|
|
|
wsprintf(ach, achNewCnct, hhDriver->achComDeviceName);
|
|
}
|
|
|
|
TimedMessageBox(sessQueryHwnd(hhDriver->hSession), ach, NULL,
|
|
MB_OK | MB_ICONINFORMATION,
|
|
sessQueryTimeout(hhDriver->hSession));
|
|
|
|
return -1;
|
|
}
|
|
else
|
|
{
|
|
if (uFlags & CNCT_ANSWER)
|
|
{
|
|
SetStatus(hhDriver, CNCT_STATUS_ANSWERING);
|
|
}
|
|
else
|
|
{
|
|
SetStatus(hhDriver, CNCT_STATUS_CONNECTING);
|
|
}
|
|
}
|
|
|
|
//
|
|
// Allow PASSTHROUGH on serial ports as well so that the session
|
|
// will not be disconnected with loss of carrier. REV: 11/6/2001
|
|
//
|
|
if (uFlags & CNCT_PORTONLY)
|
|
{
|
|
hhDriver->stCallPar.dwBearerMode = LINEBEARERMODE_PASSTHROUGH;
|
|
}
|
|
|
|
cnctdrvComEvent(hhDriver, CONNECT);
|
|
|
|
return COM_OK;
|
|
}
|
|
else if (IN_RANGE(hhDriver->dwPermanentLineId, DIRECT_COM1, DIRECT_COM4))
|
|
{
|
|
int iActivatePortReturn = IDS_ER_CNCT_PORTFAILED;
|
|
wsprintf(achCom, TEXT("COM%d"), hhDriver->dwPermanentLineId -
|
|
DIRECT_COM1 + 1);
|
|
|
|
if (TRAP(ComSetPortName(hCom, achCom)) != COM_OK ||
|
|
(iActivatePortReturn = TRAP(ComActivatePort(hCom, 0))) != COM_OK)
|
|
{
|
|
if (iActivatePortReturn == COM_PORT_IN_USE)
|
|
{
|
|
LoadString(glblQueryDllHinst(), IDS_ER_CNCT_CALLUNAVAIL,
|
|
ach, sizeof(ach) / sizeof(TCHAR));
|
|
}
|
|
else
|
|
{
|
|
LoadString(glblQueryDllHinst(), IDS_ER_CNCT_PORTFAILED,
|
|
achNewCnct, sizeof(achNewCnct) / sizeof(TCHAR));
|
|
|
|
wsprintf(ach, achNewCnct, achCom);
|
|
}
|
|
|
|
TimedMessageBox(sessQueryHwnd(hhDriver->hSession), ach, NULL,
|
|
MB_OK | MB_ICONINFORMATION,
|
|
sessQueryTimeout(hhDriver->hSession));
|
|
|
|
return -1;
|
|
}
|
|
|
|
else
|
|
{
|
|
if (uFlags & CNCT_ANSWER)
|
|
{
|
|
SetStatus(hhDriver, CNCT_STATUS_ANSWERING);
|
|
}
|
|
else
|
|
{
|
|
SetStatus(hhDriver, CNCT_STATUS_CONNECTING);
|
|
}
|
|
}
|
|
|
|
//
|
|
// Allow PASSTHROUGH on serial ports as well so that the session
|
|
// will not be disconnected with loss of carrier. REV: 11/6/2001
|
|
//
|
|
if (uFlags & CNCT_PORTONLY)
|
|
{
|
|
hhDriver->stCallPar.dwBearerMode = LINEBEARERMODE_PASSTHROUGH;
|
|
}
|
|
|
|
cnctdrvComEvent(hhDriver, CONNECT);
|
|
|
|
return COM_OK;
|
|
}
|
|
#if defined(INCL_WINSOCK)
|
|
else if (hhDriver->dwPermanentLineId == DIRECT_COMWINSOCK)
|
|
{
|
|
int iPort;
|
|
|
|
/* --- Load the Winsock Com drivers --- */
|
|
ComLoadWinsockDriver(hCom);
|
|
|
|
// Baud rate, etc. are meaningless for TCP/IP connections
|
|
//
|
|
ComSetAutoDetect(hCom, FALSE);
|
|
iPort = sessQueryTelnetPort(hhDriver->hSession);
|
|
if (iPort != 0)
|
|
hhDriver->iPort = iPort;
|
|
PostMessage(sessQueryHwndStatusbar(hhDriver->hSession),
|
|
SBR_NTFY_REFRESH, (WPARAM)SBR_COM_PART_NO, 0);
|
|
|
|
#if 0 //DEADWOOD:jmh 3/24/97 Yes, we really want auto-detection, even in telnet!
|
|
// Auto-detection of emulator type is redundant, since we tell
|
|
// the telnet host what type we want. Seems like ANSI is the
|
|
// most likely choice.
|
|
hEmu = sessQueryEmuHdl(hhDriver->hSession);
|
|
if (emuQueryEmulatorId(hEmu) == EMU_AUTO)
|
|
{
|
|
emuLoad(hEmu, EMU_VT100);
|
|
#if defined(INCL_USER_DEFINED_BACKSPACE_AND_TELNET_TERMINAL_ID)
|
|
// Make sure the telnet terminal id is correct. - cab:11/18/96
|
|
//
|
|
emuLoadDefaultTelnetId(hEmu);
|
|
#endif // defined(INCL_USER_DEFINED_BACKSPACE_AND_TELNET_TERMINAL_ID)
|
|
PostMessage(sessQueryHwndStatusbar(hhDriver->hSession),
|
|
SBR_NTFY_REFRESH, (WPARAM)SBR_EMU_PART_NO, 0);
|
|
}
|
|
#endif // 0
|
|
|
|
#if defined(INCL_CALL_ANSWERING)
|
|
if (uFlags & CNCT_ANSWER)
|
|
{
|
|
wsprintf(szInstruct, "SET ANSWER=1");
|
|
}
|
|
else
|
|
{
|
|
wsprintf(szInstruct, "SET ANSWER=0");
|
|
}
|
|
ComDriverSpecial(hCom, szInstruct, szResult, sizeof(szResult) / sizeof(TCHAR));
|
|
#endif // defined(INCL_CALL_ANSWERING)
|
|
/* --- Do ComDriverSpecial calls to send the IP address & port number
|
|
to the comm driver */
|
|
|
|
//
|
|
// Make sure we don't overwrite the buffer. If the string
|
|
// is too long, then truncate to the hhDriver->achDestAddr
|
|
// size of MAX_AP_ADDR_LEN. REV 09/20/2000
|
|
//
|
|
StrCharCopyN(szInstruct, TEXT("SET IPADDR="), sizeof(szInstruct) / sizeof(TCHAR));
|
|
iNumChars = StrCharGetStrLength(szInstruct);
|
|
StrCharCopyN(&szInstruct[iNumChars], hhDriver->achDestAddr,
|
|
sizeof(szInstruct)/sizeof(TCHAR) - iNumChars);
|
|
|
|
//
|
|
// Make sure the string is null terminated.
|
|
//
|
|
szInstruct[sizeof(szInstruct)/sizeof(TCHAR) - 1]=TEXT('\0');
|
|
ComDriverSpecial(hCom, szInstruct, szResult,
|
|
sizeof(szResult) / sizeof(TCHAR));
|
|
|
|
wsprintf(szInstruct, "SET PORTNUM=%ld", hhDriver->iPort);
|
|
ComDriverSpecial(hCom, szInstruct,
|
|
szResult, sizeof(szResult) / sizeof(TCHAR));
|
|
|
|
#if defined(INCL_CALL_ANSWERING)
|
|
if (uFlags & CNCT_ANSWER)
|
|
{
|
|
SetStatus(hhDriver, CNCT_STATUS_ANSWERING);
|
|
}
|
|
else
|
|
{
|
|
SetStatus(hhDriver, CNCT_STATUS_CONNECTING);
|
|
}
|
|
#else // defined(INCL_CALL_ANSWERING)
|
|
SetStatus(hhDriver, CNCT_STATUS_CONNECTING);
|
|
#endif // defined(INCL_CALL_ANSWERING)
|
|
|
|
/* --- Activate the port ---*/
|
|
if (ComActivatePort(hCom, 0) != COM_OK)
|
|
{
|
|
LoadString(glblQueryDllHinst(), IDS_ER_TCPIP_FAILURE,
|
|
achNewCnct, sizeof(achNewCnct) / sizeof(TCHAR));
|
|
|
|
TimedMessageBox(sessQueryHwnd(hhDriver->hSession), ach, NULL,
|
|
MB_OK | MB_ICONINFORMATION,
|
|
sessQueryTimeout(hhDriver->hSession));
|
|
|
|
return -1;
|
|
}
|
|
|
|
else
|
|
{
|
|
return COM_OK;
|
|
}
|
|
}
|
|
#endif // defined(INCL_WINSOCK)
|
|
|
|
/* --- Display confimation dialog if requested --- */
|
|
|
|
if ((uFlags & (CNCT_PORTONLY | CNCT_DIALNOW | CNCT_ANSWER)) == 0)
|
|
{
|
|
if (DialogBoxParam(glblQueryDllHinst(),
|
|
MAKEINTRESOURCE(IDD_CNCT_CONFIRM),
|
|
sessQueryHwnd(hhDriver->hSession), ConfirmDlg,
|
|
(LPARAM)hhDriver) == FALSE)
|
|
{
|
|
goto ERROR_EXIT;
|
|
}
|
|
}
|
|
|
|
// Either make the call or wait for a call.
|
|
//
|
|
if (uFlags & CNCT_ANSWER)
|
|
{
|
|
if (DoAnswerCall(hhDriver) != 0)
|
|
{
|
|
goto ERROR_EXIT;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (DoMakeCall(hhDriver, uFlags) != 0)
|
|
{
|
|
goto ERROR_EXIT;
|
|
}
|
|
}
|
|
|
|
ComSetAutoDetect(hCom, FALSE);
|
|
PostMessage(sessQueryHwndStatusbar(hhDriver->hSession),
|
|
SBR_NTFY_REFRESH, (WPARAM)SBR_COM_PART_NO, 0);
|
|
|
|
return 0;
|
|
|
|
/* --- Message exit --- */
|
|
|
|
MSG_EXIT:
|
|
LoadString(glblQueryDllHinst(), uidErr, ach, sizeof(ach) / sizeof(TCHAR));
|
|
|
|
TimedMessageBox(sessQueryHwnd(hhDriver->hSession), ach,
|
|
NULL, MB_OK | MB_ICONINFORMATION | MB_TASKMODAL,
|
|
sessQueryTimeout(hhDriver->hSession));
|
|
|
|
/* --- Error exit --- */
|
|
|
|
ERROR_EXIT:
|
|
if (hhDriver->hLineApp && hhDriver->hLine)
|
|
{
|
|
lineClose(hhDriver->hLine);
|
|
memset(&hhDriver->stCallPar, 0, sizeof(hhDriver->stCallPar));
|
|
hhDriver->stCallPar.dwTotalSize = sizeof(hhDriver->stCallPar);
|
|
hhDriver->stCallPar.dwMediaMode = LINEMEDIAMODE_DATAMODEM;
|
|
hhDriver->stCallPar.dwCallParamFlags = LINECALLPARAMFLAGS_IDLE;
|
|
hhDriver->stCallPar.dwBearerMode = 0;
|
|
hhDriver->hLine = 0;
|
|
}
|
|
|
|
SetStatus(hhDriver, CNCT_STATUS_FALSE);
|
|
return CNCT_ERROR;
|
|
}
|
|
|
|
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
|
* FUNCTION:
|
|
* DoDelayedCall
|
|
*
|
|
* DESCRIPTION:
|
|
* Check the section under Delayed Dialing in the programmers guide to
|
|
* TAPI. Basicly, if the service provider does not provide dialtone
|
|
* support, then we have to break of the dialable string format into
|
|
* pieces and prompt the user.
|
|
*
|
|
* ARGUMENTS:
|
|
* hhDriver - private driver handle.
|
|
*
|
|
* RETURNS:
|
|
* 0=OK, else error.
|
|
*
|
|
* AUTHOR: Mike Ward, 20-Apr-1995
|
|
*/
|
|
static int DoDelayedCall(const HHDRIVER hhDriver)
|
|
{
|
|
TCHAR ach[256];
|
|
TCHAR ach2[256];
|
|
TCHAR *pach;
|
|
long lDialRet;
|
|
|
|
#define DIAL_DELIMITERS "Ww@$?"
|
|
|
|
hhDriver->lMakeCallId = -1;
|
|
lstrcpy(ach, hhDriver->achDialableDest);
|
|
|
|
if ((pach = strtok(ach, DIAL_DELIMITERS)) == 0)
|
|
return -1;
|
|
|
|
while (pach)
|
|
{
|
|
lstrcpy(ach2, pach);
|
|
|
|
// If this is the last segment of the string, don't append the
|
|
// semicolon.
|
|
//
|
|
if ((pach = strtok(NULL, DIAL_DELIMITERS)) != 0)
|
|
lstrcat(ach2, ";");
|
|
|
|
if (hhDriver->lMakeCallId < 0)
|
|
{
|
|
// By appending a semicolon to the dialable string, we're
|
|
// telling lineMakeCall that more is on the way.
|
|
//
|
|
if ((hhDriver->lMakeCallId = lineMakeCall(hhDriver->hLine,
|
|
&hhDriver->hCall, ach2, hhDriver->dwCountryCode,
|
|
&hhDriver->stCallPar)) < 0)
|
|
{
|
|
#if defined(_DEBUG)
|
|
char ach[50];
|
|
wsprintf(ach, "DoDelayedCall returned %x", hhDriver->lMakeCallId);
|
|
MessageBox(GetFocus(), ach, "debug", MB_OK);
|
|
#endif
|
|
|
|
return -3;
|
|
}
|
|
}
|
|
|
|
else
|
|
{
|
|
// Once we have a call handle we have to use lineDial to complete
|
|
// the call.
|
|
//
|
|
if ((lDialRet = lineDial(hhDriver->hCall, ach2,
|
|
hhDriver->dwCountryCode)) < 0)
|
|
{
|
|
#if defined(_DEBUG)
|
|
char ach[50];
|
|
wsprintf(ach, "lineDial returned %x", lDialRet);
|
|
MessageBox(GetFocus(), ach, "debug", MB_OK);
|
|
#endif
|
|
|
|
return -4;
|
|
}
|
|
}
|
|
|
|
// The user has to tell us when the we can continue dialing
|
|
//
|
|
if (pach != 0)
|
|
{
|
|
LoadString(glblQueryDllHinst(), IDS_CNCT_DELAYEDDIAL, ach2,
|
|
sizeof(ach2) / sizeof(TCHAR));
|
|
|
|
if (TimedMessageBox(hhDriver->hwndCnctDlg, ach2, NULL,
|
|
MB_OKCANCEL | MB_ICONINFORMATION | MB_TASKMODAL,
|
|
sessQueryTimeout(hhDriver->hSession)) != IDOK)
|
|
{
|
|
return -4;
|
|
}
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
|
* FUNCTION:
|
|
* cnctdrvDisconnect
|
|
*
|
|
* DESCRIPTION:
|
|
* Signals a disconnect
|
|
*
|
|
* ARGUMENTS:
|
|
* hhDriver - private driver handle
|
|
* uFlags - disconnect flags
|
|
*
|
|
* RETURNS:
|
|
* 0 or error
|
|
*
|
|
*/
|
|
int WINAPI cnctdrvDisconnect(const HHDRIVER hhDriver, const unsigned int uFlags)
|
|
{
|
|
LONG lLineDropId;
|
|
#if defined(INCL_REDIAL_ON_BUSY)
|
|
HKEY hKey;
|
|
DWORD dwSize;
|
|
BYTE ab[20];
|
|
#endif
|
|
XD_TYPE* pX;
|
|
int nReturnVal = 0;
|
|
TCHAR ach[256];
|
|
|
|
if (hhDriver == 0)
|
|
{
|
|
assert(FALSE);
|
|
return CNCT_BAD_HANDLE;
|
|
}
|
|
|
|
//
|
|
// Cancel any active file transfers that are currently executing.
|
|
// REV: 02/01/2001
|
|
//
|
|
pX = (XD_TYPE*)sessQueryXferHdl(hhDriver->hSession);
|
|
|
|
if (pX != NULL && pX->hwndXfrDisplay != NULL &&
|
|
IsWindow(pX->hwndXfrDisplay) && pX->nDirection != XFER_NONE)
|
|
{
|
|
int nCancelTransfer = IDYES;
|
|
|
|
|
|
if (uFlags & CNCT_XFERABORTCONFIRM)
|
|
{
|
|
//
|
|
// Prompt to cancel the file transfer. REV: 02/16/2001
|
|
//
|
|
LoadString(glblQueryDllHinst(), IDS_ER_CNCT_ACTIVETRANSFER, ach, sizeof(ach) / sizeof(TCHAR));
|
|
|
|
nCancelTransfer = TimedMessageBox(pX->hwndXfrDisplay, ach, NULL,
|
|
MB_YESNO | MB_ICONEXCLAMATION | MB_TASKMODAL,
|
|
sessQueryTimeout(hhDriver->hSession));
|
|
|
|
}
|
|
|
|
if (nCancelTransfer == IDYES || nCancelTransfer == -1)
|
|
{
|
|
unsigned int uNewFlags = uFlags;
|
|
|
|
if (uFlags & CNCT_LOSTCARRIER)
|
|
{
|
|
//
|
|
// NOTE: We should only have to tell the XFER to abort here.
|
|
// It should not be dependent on a message to a dialog.
|
|
//
|
|
PostMessage(pX->hwndXfrDisplay, WM_COMMAND, XFER_LOST_CARRIER, 0L);
|
|
}
|
|
else if (uFlags & CNCT_XFERABORTCONFIRM)
|
|
{
|
|
//
|
|
// NOTE: We should only have to tell the XFER to abort here.
|
|
// It should not be dependent on a message to a dialog.
|
|
//
|
|
PostMessage(pX->hwndXfrDisplay, WM_COMMAND, XFR_SHUTDOWN, 0L);
|
|
}
|
|
|
|
//
|
|
// We can't exit until the file transfer exits, so post a
|
|
// message to try to disconnect again. Make sure to turn
|
|
// of the CNCT_XFERABORTCONFIRM flag as we don't want to
|
|
// prompt the kill the transfer again.
|
|
//
|
|
uNewFlags &= ~CNCT_XFERABORTCONFIRM;
|
|
|
|
//
|
|
// We must post a message to disconnect because we are
|
|
// waiting for the file transfer to cancel. We have to
|
|
// post a message otherwise we will get into a deadlock
|
|
// situation. This is not the best way to accomplish
|
|
// this as we may be posting a lot of messages to the
|
|
// session window and there is a potential for the
|
|
// file transfer to not respond quickly causing the
|
|
// disconnect to loop. Eventually, the file transfer
|
|
// will cancel, or will timeout and cancel, so we will
|
|
// not get into an endless loop. REV: 06/22/2001
|
|
//
|
|
|
|
//
|
|
// Wait half a second before posting this message so we don't
|
|
// flood ourselves with disconnect messages. REV: 4/25/2002
|
|
//
|
|
Sleep(500);
|
|
PostDisconnect(hhDriver, uNewFlags);
|
|
}
|
|
|
|
//
|
|
// Return an status that the current file transfer must be
|
|
// canceled (or is in the process of being canceled). We
|
|
// cannot disconnect until the transfer is complete.
|
|
//
|
|
return XFR_SHUTDOWN;
|
|
}
|
|
|
|
#ifdef INCL_CALL_ANSWERING
|
|
// Unregister our cloop callback.
|
|
//
|
|
if (hhDriver->pvUnregister)
|
|
{
|
|
CLoopUnregisterRmtInputChain(hhDriver->pvUnregister);
|
|
hhDriver->pvUnregister = 0;
|
|
}
|
|
#endif
|
|
|
|
ComDeactivatePort(sessQueryComHdl(hhDriver->hSession));
|
|
|
|
if (hhDriver->hCall)
|
|
{
|
|
SetStatus(hhDriver, CNCT_STATUS_DISCONNECTING);
|
|
|
|
if ((lLineDropId = lineDrop(hhDriver->hCall, 0, 0)) < 0)
|
|
assert(FALSE);
|
|
|
|
hhDriver->hCall = 0;
|
|
|
|
// If the drop is completing asychronously, save the flags and
|
|
// wait for the call status to go idle.
|
|
//
|
|
if (lLineDropId > 0)
|
|
{
|
|
hhDriver->uDiscnctFlags = uFlags;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
SetStatus(hhDriver, CNCT_STATUS_FALSE);
|
|
|
|
if ((uFlags & DISCNCT_NOBEEP) == 0)
|
|
sessBeeper(hhDriver->hSession);
|
|
|
|
//mpt:10-28-97 added exit upon disconnect feature
|
|
if ((uFlags & DISCNCT_EXIT))
|
|
PostMessage(sessQueryHwnd(hhDriver->hSession), WM_CLOSE, 0, 0);
|
|
|
|
if (hhDriver->hLine)
|
|
{
|
|
lineClose(hhDriver->hLine);
|
|
memset(&hhDriver->stCallPar, 0, sizeof(hhDriver->stCallPar));
|
|
hhDriver->stCallPar.dwTotalSize = sizeof(hhDriver->stCallPar);
|
|
hhDriver->stCallPar.dwMediaMode = LINEMEDIAMODE_DATAMODEM;
|
|
hhDriver->stCallPar.dwCallParamFlags = LINECALLPARAMFLAGS_IDLE;
|
|
hhDriver->stCallPar.dwBearerMode = 0;
|
|
hhDriver->hLine = 0;
|
|
}
|
|
|
|
if (uFlags & CNCT_DIALNOW)
|
|
{
|
|
#if defined(INCL_REDIAL_ON_BUSY)
|
|
if (hhDriver->fRedialOnBusy && hhDriver->iRedialCnt > 0)
|
|
{
|
|
hhDriver->uDiscnctFlags = uFlags;
|
|
hhDriver->iRedialSecsRemaining = 2;
|
|
|
|
if (RegOpenKeyEx(HKEY_LOCAL_MACHINE,
|
|
"SOFTWARE\\Microsoft\\HyperTerminal\\TimeToRedial", 0, KEY_READ,
|
|
&hKey) == ERROR_SUCCESS)
|
|
{
|
|
dwSize = sizeof(ab);
|
|
|
|
if (RegQueryValueEx(hKey, "", 0, 0, ab, &dwSize) == ERROR_SUCCESS)
|
|
hhDriver->iRedialSecsRemaining = atoi(ab);
|
|
|
|
RegCloseKey(hKey);
|
|
}
|
|
|
|
SetTimer(hhDriver->hwndCnctDlg, 1, 1000, 0);
|
|
}
|
|
|
|
else
|
|
{
|
|
PostMessage(sessQueryHwnd(hhDriver->hSession), WM_CNCT_DIALNOW,
|
|
uFlags, 0);
|
|
}
|
|
|
|
#else
|
|
PostMessage(sessQueryHwnd(hhDriver->hSession), WM_CNCT_DIALNOW,
|
|
uFlags, 0);
|
|
#endif
|
|
}
|
|
|
|
else
|
|
{
|
|
// If we're not auto redialing, reset the dial count. - mrw:10/10/95
|
|
//
|
|
hhDriver->iRedialCnt = 0;
|
|
}
|
|
|
|
return nReturnVal;
|
|
}
|
|
|
|
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
|
* FUNCTION:
|
|
* lineCallbackFunc
|
|
*
|
|
* DESCRIPTION:
|
|
* Function TAPI calls to handle asynchronous events
|
|
*
|
|
* ARGUMENTS:
|
|
* see TAPI.H
|
|
*
|
|
* RETURNS:
|
|
* void
|
|
*
|
|
*/
|
|
void CALLBACK lineCallbackFunc(DWORD hDevice, DWORD dwMsg, DWORD_PTR dwCallback,
|
|
DWORD_PTR dwParm1, DWORD_PTR dwParm2, DWORD_PTR dwParm3)
|
|
{
|
|
const HHDRIVER hhDriver = (HHDRIVER)dwCallback;
|
|
int id;
|
|
unsigned int uFlags;
|
|
|
|
#if 0
|
|
{
|
|
char ach[256];
|
|
wsprintf(ach,"%x %x", dwMsg, dwParm1);
|
|
MessageBox(NULL, ach, "debug", MB_OK);
|
|
}
|
|
#endif
|
|
|
|
switch (dwMsg)
|
|
{
|
|
case LINE_REPLY:
|
|
if ((LONG)dwParm1 == hhDriver->lMakeCallId)
|
|
{
|
|
hhDriver->lMakeCallId = 0;
|
|
|
|
if ((LONG)dwParm2 != 0) // zero indicates success
|
|
{
|
|
switch (dwParm2)
|
|
{
|
|
case LINEERR_CALLUNAVAIL:
|
|
id = IDS_DIAL_NODIALTONE;
|
|
break;
|
|
|
|
default:
|
|
id = IDS_DIAL_DISCONNECTED;
|
|
break;
|
|
}
|
|
|
|
cnctdrvDisconnect(hhDriver, 0);
|
|
DialingMessage(hhDriver, id);
|
|
}
|
|
}
|
|
break;
|
|
|
|
case LINE_LINEDEVSTATE:
|
|
DbgOutStr("LINEDEVSTATE_DISCONNECTED 0x%x\r\n", dwParm1, 0, 0, 0, 0);
|
|
|
|
switch (dwParm1)
|
|
{
|
|
case PHONESTATE_CAPSCHANGE:
|
|
//
|
|
// If we are currently disconnected, then reset.
|
|
//
|
|
if (hhDriver != NULL && hhDriver->iStatus != CNCT_STATUS_FALSE)
|
|
break;
|
|
|
|
case LINEDEVSTATE_REINIT:
|
|
case PHONESTATE_REINIT:
|
|
if (hhDriver == 0)
|
|
{
|
|
// Until we open a line, we don't have a driver handle
|
|
// since we can't pass one during lineInitialize().
|
|
// This turns out to be a good time to reinit if we get
|
|
// notified to do so however, so it has use.
|
|
//
|
|
if (tapiReinit(gbl_hhDriver) != 0)
|
|
tapiReinitMessage(gbl_hhDriver);
|
|
}
|
|
|
|
else
|
|
{
|
|
tapiReinitMessage(hhDriver);
|
|
}
|
|
break;
|
|
|
|
case LINEDEVSTATE_INSERVICE:
|
|
// If we are showing our PCMCIA dialog prompting the user
|
|
// to insert the card, we post a message to dismiss the
|
|
// dialog once they insert it. - mrw,2/28/95
|
|
//
|
|
if (IsWindow(hhDriver->hwndPCMCIA))
|
|
{
|
|
PostMessage(hhDriver->hwndPCMCIA, WM_COMMAND,
|
|
MAKEWPARAM(IDOK, 0), (LPARAM)hhDriver->hwndPCMCIA);
|
|
}
|
|
break;
|
|
|
|
case LINEDEVSTATE_OUTOFSERVICE:
|
|
// Means they yanked the PCMCIA card - mrw,2/28/95
|
|
//
|
|
cnctdrvDisconnect(hhDriver, 0);
|
|
break;
|
|
|
|
case LINEDEVSTATE_RINGING:
|
|
// When the current ring count (as told by dwParam3) equals
|
|
// or exceeds the rings to answer on then we'll do the answer
|
|
// using the hhdriver->hCall handle we cached during the
|
|
// LINECALLSTATE_BURNTOFFERING notification. - rjk. 07-31-96
|
|
//
|
|
if ((hhDriver->lMakeCallId = lineAnswer(hhDriver->hCall,0,0)) >= 0)
|
|
{
|
|
SetStatus(hhDriver, CNCT_STATUS_CONNECTING);
|
|
}
|
|
break;
|
|
|
|
case LINEDEVSTATE_CLOSE:
|
|
case PHONESTATE_DISCONNECTED:
|
|
//
|
|
// Another application has disconnected this device. REV: 04/27/2001
|
|
//
|
|
uFlags = CNCT_DIALNOW | CNCT_NOCONFIRM;
|
|
id = IDS_DIAL_DISCONNECTED;
|
|
PostDisconnect(hhDriver, uFlags);
|
|
DialingMessage(hhDriver, id);
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
break; // case LINE_LINEDEVSTATE
|
|
|
|
case LINE_CREATE: // Sent when new modem is added
|
|
assert(0); // So I know it happened
|
|
|
|
// A remote possibilility exists that if two modems were created
|
|
// back to back, that the LINE_CREATE's would come out of order.
|
|
// T. Nixon suggests that we bump the line count by the dwParm1
|
|
// parameter plus one only when it is greater than or equal to
|
|
// the current line count. - mrw
|
|
//
|
|
if (dwParm1 >= gbl_hhDriver->dwLineCnt)
|
|
gbl_hhDriver->dwLineCnt = (DWORD)(dwParm1 + 1);
|
|
|
|
break;
|
|
|
|
case LINE_CALLSTATE:
|
|
DbgOutStr("LINECALLSTATE 0x%x\r\n", dwParm1, 0, 0, 0, 0);
|
|
switch ((LONG)dwParm1)
|
|
{
|
|
case LINECALLSTATE_OFFERING:
|
|
DialingMessage(hhDriver, IDS_DIAL_OFFERING);
|
|
// Windows sends us this message only one time while receiving
|
|
// a call and that is on the very first ring. See the code
|
|
// that responds to the LINEDEVSTATE_RINGING to see how the call
|
|
// gets answered. - rjk. 07-31-96
|
|
//
|
|
hhDriver->hCall = (HCALL)hDevice;
|
|
break;
|
|
|
|
case LINECALLSTATE_DIALTONE:
|
|
DialingMessage(hhDriver, IDS_DIAL_DIALTONE);
|
|
break;
|
|
|
|
case LINECALLSTATE_DIALING:
|
|
DialingMessage(hhDriver, IDS_DIAL_DIALING);
|
|
break;
|
|
|
|
case LINECALLSTATE_RINGBACK:
|
|
DialingMessage(hhDriver, IDS_DIAL_RINGBACK);
|
|
break;
|
|
|
|
case LINECALLSTATE_BUSY:
|
|
DialingMessage(hhDriver, IDS_DIAL_BUSY);
|
|
EnableDialNow(hhDriver->hwndCnctDlg, TRUE);
|
|
uFlags = DISCNCT_NOBEEP;
|
|
|
|
#if defined(INCL_REDIAL_ON_BUSY)
|
|
if (hhDriver->fRedialOnBusy && hhDriver->iRedialCnt++ < REDIAL_MAX)
|
|
uFlags = CNCT_DIALNOW | CNCT_NOCONFIRM | DISCNCT_NOBEEP;
|
|
#endif
|
|
|
|
PostDisconnect(hhDriver, uFlags);
|
|
break;
|
|
|
|
case LINECALLSTATE_CONNECTED:
|
|
DialingMessage(hhDriver, IDS_DIAL_CONNECTED);
|
|
|
|
if (Handoff(hhDriver) != 0)
|
|
{
|
|
PostDisconnect(hhDriver, 0);
|
|
}
|
|
else
|
|
{
|
|
if (IsWindow(hhDriver->hwndCnctDlg))
|
|
{
|
|
// Closes the dialing dialog
|
|
PostMessage(hhDriver->hwndCnctDlg, WM_USER+0x100, 0, 0);
|
|
}
|
|
SetStatus(hhDriver, CNCT_STATUS_TRUE);
|
|
}
|
|
|
|
break;
|
|
|
|
case LINECALLSTATE_DISCONNECTED:
|
|
DbgOutStr("LINECALLSTATE_DISCONNECTED 0x%x\r\n", dwParm2, 0, 0, 0, 0);
|
|
uFlags = 0;
|
|
|
|
if (dwParm2 & LINEDISCONNECTMODE_BUSY)
|
|
{
|
|
id = IDS_DIAL_BUSY;
|
|
|
|
#if defined(INCL_REDIAL_ON_BUSY)
|
|
if (hhDriver->fRedialOnBusy &&
|
|
hhDriver->iRedialCnt++ < REDIAL_MAX)
|
|
{
|
|
// Wait to let slower phone systems catchup - mrw 2/29/96
|
|
//
|
|
uFlags |= CNCT_DIALNOW|CNCT_NOCONFIRM|DISCNCT_NOBEEP;
|
|
}
|
|
#endif
|
|
}
|
|
|
|
else if (dwParm2 & LINEDISCONNECTMODE_NOANSWER)
|
|
id = IDS_DIAL_NOANSWER;
|
|
|
|
else if (dwParm2 & LINEDISCONNECTMODE_NODIALTONE)
|
|
id = IDS_DIAL_NODIALTONE;
|
|
|
|
else
|
|
{
|
|
id = IDS_DIAL_DISCONNECTED;
|
|
//mpt:10-28-97 added exit upon disconnect feature
|
|
uFlags |= ( sessQueryExit(hhDriver->hSession) ? DISCNCT_EXIT : 0 );
|
|
}
|
|
|
|
PostDisconnect(hhDriver, uFlags);
|
|
DialingMessage(hhDriver, id);
|
|
break;
|
|
|
|
case LINECALLSTATE_IDLE:
|
|
cnctdrvDisconnect(hhDriver, hhDriver->uDiscnctFlags);
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
|
* FUNCTION:
|
|
* Handoff
|
|
*
|
|
* DESCRIPTION:
|
|
* Hands TAPI's com handle to the Wacker's com routines.
|
|
*
|
|
* ARGUMENTS:
|
|
* hhDriver - private driver handle
|
|
*
|
|
* RETURNS:
|
|
* 0=OK
|
|
*
|
|
*/
|
|
int Handoff(const HHDRIVER hhDriver)
|
|
{
|
|
LPVARSTRING pVarstr;
|
|
HANDLE hdl;
|
|
DWORD dwSize;
|
|
int i;
|
|
|
|
pVarstr = malloc(sizeof(VARSTRING));
|
|
|
|
if (pVarstr == 0)
|
|
{
|
|
assert(FALSE);
|
|
return 1;
|
|
}
|
|
|
|
memset( pVarstr, 0, sizeof(VARSTRING) );
|
|
pVarstr->dwTotalSize = sizeof(VARSTRING);
|
|
|
|
if (lineGetID(hhDriver->hLine, hhDriver->dwLine, hhDriver->hCall,
|
|
LINECALLSELECT_CALL, pVarstr, DEVCLASS) != 0)
|
|
{
|
|
assert(FALSE);
|
|
free(pVarstr);
|
|
pVarstr = NULL;
|
|
return 2;
|
|
}
|
|
|
|
if (pVarstr->dwNeededSize > pVarstr->dwTotalSize)
|
|
{
|
|
dwSize = pVarstr->dwNeededSize;
|
|
free(pVarstr);
|
|
pVarstr = NULL;
|
|
pVarstr = malloc(dwSize);
|
|
|
|
if (pVarstr == 0)
|
|
{
|
|
assert(FALSE);
|
|
return 3;
|
|
}
|
|
|
|
memset( pVarstr, 0, dwSize );
|
|
pVarstr->dwTotalSize = dwSize;
|
|
|
|
if (TRAP(lineGetID(hhDriver->hLine, hhDriver->dwLine, hhDriver->hCall,
|
|
LINECALLSELECT_CALL, pVarstr, DEVCLASS)) != 0)
|
|
{
|
|
assert(FALSE);
|
|
free(pVarstr);
|
|
pVarstr = NULL;
|
|
return 4;
|
|
}
|
|
}
|
|
|
|
if (pVarstr->dwStringSize == 0)
|
|
{
|
|
assert(FALSE);
|
|
free(pVarstr);
|
|
pVarstr = NULL;
|
|
return 5;
|
|
}
|
|
|
|
hdl = *(HANDLE *)((BYTE *)pVarstr + pVarstr->dwStringOffset);
|
|
|
|
// Set comm buffers to 32K
|
|
//
|
|
if (SetupComm(hdl, 32768, 32768) == FALSE)
|
|
{
|
|
DWORD dwLastError = GetLastError();
|
|
assert(0);
|
|
}
|
|
|
|
if ((i = ComActivatePort(sessQueryComHdl(hhDriver->hSession),
|
|
(DWORD_PTR)hdl)) != COM_OK)
|
|
{
|
|
#if !defined(NDEBUG)
|
|
char ach[256];
|
|
wsprintf(ach, "hdl=%x, i=%d", hdl, i);
|
|
MessageBox(NULL, ach, "debug", MB_OK);
|
|
#endif
|
|
|
|
assert(FALSE);
|
|
free(pVarstr);
|
|
pVarstr = NULL;
|
|
return 6;
|
|
}
|
|
|
|
if(pVarstr)
|
|
{
|
|
free(pVarstr);
|
|
pVarstr = NULL;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
|
* FUNCTION:
|
|
* PostDisconnect
|
|
*
|
|
* DESCRIPTION:
|
|
* Work around to TAPI bug that does not allow us to call lineShutDown()
|
|
* from with the TAPI callback
|
|
*
|
|
* ARGUMENTS:
|
|
* hhDriver - private driver handle
|
|
*
|
|
* RETURNS:
|
|
* void
|
|
*
|
|
*/
|
|
void PostDisconnect(const HHDRIVER hhDriver, const unsigned int uFlags)
|
|
{
|
|
PostMessage(sessQueryHwnd(hhDriver->hSession), WM_DISCONNECT,
|
|
uFlags, 0);
|
|
|
|
return;
|
|
}
|
|
|
|
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
|
* FUNCTION:
|
|
* tapiReinitMessage
|
|
*
|
|
* DESCRIPTION:
|
|
* Displays a messagebox showing TAPI needs to be reinitialized.
|
|
*
|
|
* ARGUMENTS:
|
|
* hhDriver - private driver handle
|
|
*
|
|
* RETURNS:
|
|
* 0=OK, <0=error
|
|
*
|
|
*/
|
|
static int tapiReinitMessage(const HHDRIVER hhDriver)
|
|
{
|
|
TCHAR ach[512], achTitle[256];
|
|
|
|
if (hhDriver == 0)
|
|
{
|
|
assert(FALSE);
|
|
return -1;
|
|
}
|
|
|
|
LoadString(glblQueryDllHinst(), IDS_ER_TAPI_REINIT, ach, sizeof(ach) / sizeof(TCHAR));
|
|
|
|
LoadString(glblQueryDllHinst(), IDS_ER_TAPI_REINIT2, achTitle,
|
|
sizeof(achTitle) / sizeof(TCHAR));
|
|
|
|
lstrcat(ach, achTitle);
|
|
|
|
TimedMessageBox(sessQueryHwnd(hhDriver->hSession), ach, NULL,
|
|
MB_OK | MB_ICONINFORMATION | MB_TASKMODAL,
|
|
sessQueryTimeout(hhDriver->hSession));
|
|
|
|
return 0;
|
|
}
|
|
|
|
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
|
* FUNCTION:
|
|
* tapiReinit
|
|
*
|
|
* DESCRIPTION:
|
|
* Attempts to reinit tapi.
|
|
*
|
|
* ARGUMENTS:
|
|
* hhDriver - private driver handle
|
|
*
|
|
* RETURNS:
|
|
* 0=OK,else error
|
|
*
|
|
*/
|
|
static int tapiReinit(const HHDRIVER hhDriver)
|
|
{
|
|
int i;
|
|
LPVARSTRING pvs = 0;
|
|
DWORD dwSize;
|
|
const SF_HANDLE sfhdl = sessQuerySysFileHdl(hhDriver->hSession);
|
|
|
|
if (hhDriver == 0)
|
|
{
|
|
assert(FALSE);
|
|
return -1;
|
|
}
|
|
|
|
if (hhDriver->hLineApp)
|
|
{
|
|
/* --- Get current config so we can restore it --- */
|
|
|
|
if (hhDriver->dwLine != (DWORD)-1)
|
|
{
|
|
if ((pvs = malloc(sizeof(VARSTRING))) == 0)
|
|
{
|
|
assert(FALSE);
|
|
goto SHUTDOWN;
|
|
}
|
|
|
|
memset( pvs, 0, sizeof(VARSTRING) );
|
|
pvs->dwTotalSize = sizeof(VARSTRING);
|
|
|
|
if (lineGetDevConfig(hhDriver->dwLine, pvs, DEVCLASS) != 0)
|
|
{
|
|
assert(FALSE);
|
|
free(pvs);
|
|
pvs = NULL;
|
|
hhDriver->dwLine = (DWORD)-1;
|
|
goto SHUTDOWN;
|
|
}
|
|
|
|
if (pvs->dwNeededSize > pvs->dwTotalSize)
|
|
{
|
|
dwSize = pvs->dwNeededSize;
|
|
free(pvs);
|
|
pvs = NULL;
|
|
|
|
if ((pvs = malloc(dwSize)) == 0)
|
|
{
|
|
assert(FALSE);
|
|
hhDriver->dwLine = (DWORD)-1;
|
|
goto SHUTDOWN;
|
|
}
|
|
|
|
memset( pvs, 0, dwSize );
|
|
pvs->dwTotalSize = dwSize;
|
|
|
|
if (lineGetDevConfig(hhDriver->dwLine, pvs, DEVCLASS) != 0)
|
|
{
|
|
assert(FALSE);
|
|
free(pvs);
|
|
pvs = NULL;
|
|
hhDriver->dwLine = (DWORD)-1;
|
|
goto SHUTDOWN;
|
|
}
|
|
}
|
|
}
|
|
|
|
SHUTDOWN:
|
|
|
|
{
|
|
LONG lLineShutdown = lineShutdown(hhDriver->hLineApp);
|
|
|
|
if (lLineShutdown == LINEERR_NOMEM)
|
|
{
|
|
//
|
|
// We are in a low memory state, so wait for a while,
|
|
// then try to shutdown the line again. REV: 5/1/2002
|
|
//
|
|
Sleep(500);
|
|
lLineShutdown = lineShutdown(hhDriver->hLineApp);
|
|
}
|
|
|
|
if (lLineShutdown != 0)
|
|
{
|
|
assert(FALSE);
|
|
return -6;
|
|
}
|
|
}
|
|
|
|
hhDriver->hLineApp = 0;
|
|
|
|
// Wait for 10 seconds, if nothing happens, return an error
|
|
//
|
|
for (i=0 ;; ++i)
|
|
{
|
|
if (lineInitialize(&hhDriver->hLineApp, glblQueryDllHinst(),
|
|
lineCallbackFunc, g_achApp, &hhDriver->dwLineCnt) != 0)
|
|
{
|
|
if (i > 10)
|
|
{
|
|
assert(0);
|
|
return -7;
|
|
}
|
|
|
|
Sleep(1000); // sleep 1 second
|
|
continue;
|
|
}
|
|
|
|
break;
|
|
}
|
|
}
|
|
|
|
/* --- Ok, we've reintialized, put settings back now --- */
|
|
|
|
if (pvs)
|
|
{
|
|
LPVOID pv = (BYTE *)pvs + pvs->dwStringOffset;
|
|
|
|
if (lineSetDevConfig(hhDriver->dwLine, pv, pvs->dwStringSize,
|
|
DEVCLASS) != 0)
|
|
{
|
|
assert(FALSE);
|
|
free(pvs);
|
|
pvs = NULL;
|
|
return -8;
|
|
}
|
|
|
|
free(pvs);
|
|
pvs = NULL;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
|
* FUNCTION:
|
|
* cnctdrvSetDestination
|
|
*
|
|
* DESCRIPTION:
|
|
* Sets the destination (in this case phone number).
|
|
*
|
|
* ARGUMENTS:
|
|
* hhDriver - private driver handle
|
|
* ach - string to set
|
|
* cb - number of chars in ach
|
|
*
|
|
* RETURNS:
|
|
* 0=OK, <0=error
|
|
*
|
|
*/
|
|
int WINAPI cnctdrvSetDestination(const HHDRIVER hhDriver, TCHAR * const ach,
|
|
const size_t cb)
|
|
{
|
|
int len;
|
|
|
|
if (hhDriver == 0 || ach == 0 || cb == 0)
|
|
{
|
|
assert(FALSE);
|
|
return -1;
|
|
}
|
|
|
|
len = (int) min(cb, sizeof(hhDriver->achDest));
|
|
strncpy(hhDriver->achDest, ach, len);
|
|
hhDriver->achDest[len-1];
|
|
|
|
return 0;
|
|
}
|
|
|
|
/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
|
* FUNCTION:
|
|
* DoNewModemWizard
|
|
*
|
|
* DESCRIPTION:
|
|
* Calls up the new modem wizard
|
|
*
|
|
* ARGUMENTS:
|
|
* hhDriver - private driver handle
|
|
* iTimeout - The timeout length
|
|
*
|
|
* RETURNS:
|
|
* 0=OK,else error
|
|
*
|
|
*/
|
|
static int DoNewModemWizard(HWND hWnd, int iTimeout)
|
|
{
|
|
PROCESS_INFORMATION stPI;
|
|
STARTUPINFO stSI;
|
|
TCHAR ach[256];
|
|
int returnVal = 0;
|
|
|
|
// Initialize the PROCESS_INFORMATION structure for CreateProcess
|
|
//
|
|
memset( &stPI, 0, sizeof( PROCESS_INFORMATION ) );
|
|
|
|
// Initialize the STARTUPINFO structure for CreateProcess
|
|
//
|
|
memset(&stSI, 0, sizeof(stSI));
|
|
stSI.cb = sizeof(stSI);
|
|
stSI.dwFlags = STARTF_USESHOWWINDOW;
|
|
stSI.wShowWindow = SW_SHOW;
|
|
|
|
// See if we should run the New modem wizard.
|
|
//
|
|
if(mscAskWizardQuestionAgain())
|
|
{
|
|
LoadString(glblQueryDllHinst(), IDS_ER_CNCT_BADLINE, ach, sizeof(ach) / sizeof(TCHAR));
|
|
|
|
if (TimedMessageBox(hWnd, ach, NULL, MB_YESNO | MB_ICONEXCLAMATION, iTimeout) == IDYES)
|
|
{
|
|
TCHAR systemDir[MAX_PATH];
|
|
TCHAR executeString[MAX_PATH * 3];
|
|
TCHAR *pParams = TEXT("\\control.exe\" modem.cpl,,Add");
|
|
UINT numChars = 0;
|
|
|
|
TCHAR_Fill(systemDir, TEXT('\0'), MAX_PATH);
|
|
TCHAR_Fill(executeString, TEXT('\0'), MAX_PATH * 3);
|
|
numChars = GetSystemDirectory(systemDir, MAX_PATH);
|
|
|
|
if (numChars == 0 || StrCharGetStrLength(systemDir) == 0)
|
|
{
|
|
returnVal = -3;
|
|
}
|
|
else
|
|
{
|
|
if (StrCharGetStrLength(systemDir) + StrCharGetStrLength(pParams) + sizeof(TEXT("\"")) / sizeof(TCHAR) >
|
|
sizeof(executeString) / sizeof(TCHAR))
|
|
{
|
|
returnVal = -2;
|
|
}
|
|
else
|
|
{
|
|
StrCharCopyN(executeString, TEXT("\""), sizeof(executeString) / sizeof(TCHAR));
|
|
StrCharCat(executeString, systemDir);
|
|
StrCharCat(executeString, pParams);
|
|
|
|
//
|
|
// Launch the new modem wizard with the command below.
|
|
//
|
|
|
|
//if (CreateProcess(0, "rundll sysdm.cpl,InstallDevice_Rundll modem,,",
|
|
// 0, 0, 0, 0, 0, 0, &stSI, &stPI) == FALSE)
|
|
//if (CreateProcess(0, "control.exe modem.cpl,,Add",
|
|
// 0, 0, 0, 0, 0, 0, &stSI, &stPI) == FALSE)
|
|
if (CreateProcess(NULL, executeString,
|
|
NULL, NULL, FALSE, NORMAL_PRIORITY_CLASS,
|
|
NULL, systemDir, &stSI, &stPI) == FALSE)
|
|
{
|
|
#if defined(_DEBUG)
|
|
{
|
|
char ach[100];
|
|
DWORD dw = GetLastError();
|
|
|
|
wsprintf(ach,"CreateProcess (%s, %d) : %x",__FILE__,__LINE__,dw);
|
|
MessageBox(NULL, ach, "Debug", MB_OK);
|
|
}
|
|
#endif
|
|
|
|
returnVal = -1;
|
|
}
|
|
else
|
|
{
|
|
mscUpdateRegistryValue();
|
|
|
|
//
|
|
// Close the handles.
|
|
//
|
|
CloseHandle(stPI.hProcess);
|
|
CloseHandle(stPI.hThread);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return returnVal;
|
|
}
|
|
|
|
int cncttapiGetLineConfig( const DWORD dwLineId, VOID ** ppvs )
|
|
{
|
|
DWORD dwSize;
|
|
LPVARSTRING pvs = (LPVARSTRING)*ppvs;
|
|
|
|
if (pvs != NULL)
|
|
{
|
|
assert(FALSE);
|
|
free(pvs);
|
|
pvs = NULL;
|
|
}
|
|
|
|
if ((pvs = malloc(sizeof(VARSTRING))) == 0)
|
|
{
|
|
assert(FALSE);
|
|
return -3;
|
|
}
|
|
|
|
memset(pvs, 0, sizeof(VARSTRING));
|
|
pvs->dwTotalSize = sizeof(VARSTRING);
|
|
pvs->dwNeededSize = 0;
|
|
|
|
if (lineGetDevConfig(dwLineId, pvs, DEVCLASS) != 0)
|
|
{
|
|
assert(FALSE);
|
|
free(pvs);
|
|
pvs = NULL;
|
|
return -4;
|
|
}
|
|
|
|
if (pvs->dwNeededSize > pvs->dwTotalSize)
|
|
{
|
|
dwSize = pvs->dwNeededSize;
|
|
free(pvs);
|
|
pvs = NULL;
|
|
|
|
if ((pvs = malloc(dwSize)) == 0)
|
|
{
|
|
assert(FALSE);
|
|
return -5;
|
|
}
|
|
|
|
memset(pvs, 0, dwSize);
|
|
pvs->dwTotalSize = dwSize;
|
|
|
|
if (lineGetDevConfig(dwLineId, pvs, DEVCLASS) != 0)
|
|
{
|
|
assert(FALSE);
|
|
free(pvs);
|
|
pvs = NULL;
|
|
return -6;
|
|
}
|
|
}
|
|
|
|
*ppvs = (VOID *)pvs;
|
|
return 0;
|
|
}
|
|
|
|
int cncttapiSetLineConfig(const DWORD dwLineId, const HCOM hCom)
|
|
{
|
|
int retValue = 0;
|
|
LPVARSTRING pvs = NULL;
|
|
PUMDEVCFG pDevCfg = NULL;
|
|
int iBaudRate;
|
|
int iDataBits;
|
|
int iParity;
|
|
int iStopBits;
|
|
LONG lLineReturn;
|
|
|
|
retValue = cncttapiGetLineConfig( dwLineId, (VOID **) &pvs);
|
|
|
|
if (retValue != 0)
|
|
{
|
|
retValue = retValue;
|
|
}
|
|
|
|
if (retValue == 0 && pvs == NULL)
|
|
{
|
|
retValue = -7;
|
|
}
|
|
|
|
// The structure of the DevConfig block is as follows
|
|
//
|
|
// VARSTRING
|
|
// UMDEVCFGHDR
|
|
// COMMCONFIG
|
|
// MODEMSETTINGS
|
|
//
|
|
// The UMDEVCFG structure used below is defined in the
|
|
// UNIMODEM.H provided in the platform SDK (in the nih
|
|
// directory for HTPE). REV: 12/01/2000
|
|
//
|
|
if (retValue == 0)
|
|
{
|
|
pDevCfg = (UMDEVCFG *)((BYTE *)pvs + pvs->dwStringOffset);
|
|
if (pDevCfg == NULL)
|
|
{
|
|
retValue = -8;
|
|
}
|
|
}
|
|
|
|
if (retValue == 0 && (hCom == NULL || ComValidHandle(hCom) == FALSE))
|
|
{
|
|
retValue = -9;
|
|
}
|
|
|
|
//
|
|
// commconfig struct has a DCB structure we dereference for the
|
|
// com settings.
|
|
//
|
|
|
|
//
|
|
// The baud rate should be stored with the COM settings for
|
|
// TAPI devices, but we may want to use the current TAPI device
|
|
// baud rate instead. We should find a better solution for this.
|
|
// TODO:REV 05/01/2001
|
|
//
|
|
if (retValue == 0 && ComGetBaud(hCom, &iBaudRate) != COM_OK)
|
|
{
|
|
#if defined(TODO)
|
|
retValue = -10;
|
|
#endif // TODO
|
|
}
|
|
else if (retValue == 0)
|
|
{
|
|
ComSetBaud(hCom, pDevCfg->commconfig.dcb.BaudRate);
|
|
}
|
|
|
|
if (retValue == 0 && ComGetDataBits(hCom, &iDataBits) != COM_OK)
|
|
{
|
|
retValue = -11;
|
|
}
|
|
|
|
if (retValue == 0 && ComGetParity(hCom, &iParity) != COM_OK)
|
|
{
|
|
retValue = -12;
|
|
}
|
|
|
|
if (retValue == 0 && ComGetStopBits(hCom, &iStopBits) != COM_OK)
|
|
{
|
|
retValue = -13;
|
|
}
|
|
|
|
if (retValue != 0)
|
|
{
|
|
free(pvs);
|
|
pvs = NULL;
|
|
return retValue;
|
|
}
|
|
|
|
#if defined(TODO)
|
|
pDevCfg->commconfig.dcb.BaudRate = iBaudRate;
|
|
#endif // TODO
|
|
pDevCfg->commconfig.dcb.ByteSize = (BYTE)iDataBits;
|
|
pDevCfg->commconfig.dcb.Parity = (BYTE)iParity;
|
|
pDevCfg->commconfig.dcb.StopBits = (BYTE)iStopBits;
|
|
|
|
if (iDataBits != 8 && iParity != NOPARITY && iStopBits != ONESTOPBIT)
|
|
{
|
|
ComSetAutoDetect(hCom, FALSE);
|
|
}
|
|
|
|
//
|
|
// Actually set the TAPI device's COM settings.
|
|
//
|
|
lLineReturn = lineSetDevConfig(dwLineId, pDevCfg, pvs->dwStringSize, DEVCLASS);
|
|
|
|
free(pvs);
|
|
pvs = NULL;
|
|
|
|
if (lLineReturn < 0)
|
|
{
|
|
assert(FALSE);
|
|
return lLineReturn;
|
|
}
|
|
|
|
retValue = cncttapiGetLineConfig( dwLineId, (VOID **) &pvs);
|
|
|
|
if (retValue != 0)
|
|
{
|
|
retValue = retValue - 100;
|
|
}
|
|
|
|
//
|
|
// Make sure the port settings get updated.
|
|
//
|
|
retValue = ComConfigurePort(hCom);
|
|
|
|
//
|
|
// Make sure the status bar contains the correct settings.
|
|
//
|
|
PostMessage(sessQueryHwndStatusbar(hCom->hSession),
|
|
SBR_NTFY_REFRESH, (WPARAM)SBR_COM_PART_NO, 0);
|
|
|
|
if (pvs == NULL)
|
|
{
|
|
return -14;
|
|
}
|
|
|
|
// The structure of the DevConfig block is as follows
|
|
//
|
|
// VARSTRING
|
|
// UMDEVCFGHDR
|
|
// COMMCONFIG
|
|
// MODEMSETTINGS
|
|
//
|
|
// The UMDEVCFG structure used below is defined in the
|
|
// UNIMODEM.H provided in the platform SDK (in the nih
|
|
// directory for HTPE). REV: 12/01/2000
|
|
//
|
|
if (retValue == 0)
|
|
{
|
|
pDevCfg = (UMDEVCFG *)((BYTE *)pvs + pvs->dwStringOffset);
|
|
|
|
if (pDevCfg == NULL)
|
|
{
|
|
retValue = -15;
|
|
}
|
|
}
|
|
|
|
if (retValue == 0 && (
|
|
#if defined(TODO)
|
|
pDevCfg->commconfig.dcb.BaudRate != iBaudRate ||
|
|
#endif // TODO
|
|
pDevCfg->commconfig.dcb.ByteSize != iDataBits ||
|
|
pDevCfg->commconfig.dcb.Parity != iParity ||
|
|
pDevCfg->commconfig.dcb.StopBits != iStopBits))
|
|
{
|
|
|
|
//
|
|
// If this is NT and we are currently connected with
|
|
// a modem, we must disconnect and attempt to redial
|
|
// so that the COM settings are set properly for the
|
|
// modem since this can not be done once a connection
|
|
// has been made. REV: 06/05/2001
|
|
//
|
|
if (IsNT())
|
|
{
|
|
HCNCT hCnct = sessQueryCnctHdl(hCom->hSession);
|
|
if (hCnct)
|
|
{
|
|
int iStatus = cnctQueryStatus(hCnct);
|
|
|
|
if (iStatus != CNCT_STATUS_FALSE &&
|
|
iStatus != CNCT_BAD_HANDLE &&
|
|
cnctIsModemConnection(hCnct) == 1)
|
|
{
|
|
int nDisconnect = IDYES;
|
|
|
|
//
|
|
// Don't prompt if this is NT_EDITION, just do the
|
|
// disconnection quietly and attempt to reconnect.
|
|
//
|
|
#if !defined(NT_EDITION)
|
|
TCHAR ach[256];
|
|
|
|
TCHAR_Fill(ach, TEXT('\0'), sizeof(ach) / sizeof(TCHAR));
|
|
|
|
//
|
|
// Prompt to disconnect current connection due to TAPI
|
|
// device needing to be reset. REV: 05/31/2001
|
|
//
|
|
LoadString(glblQueryDllHinst(), IDS_ER_TAPI_NEEDS_RESET, ach, sizeof(ach) / sizeof(TCHAR));
|
|
|
|
nDisconnect =
|
|
TimedMessageBox(sessQueryHwnd(hCom->hSession), ach, NULL,
|
|
MB_YESNO | MB_ICONEXCLAMATION | MB_TASKMODAL,
|
|
sessQueryTimeout(hCom->hSession));
|
|
#endif //NT_EDITION
|
|
|
|
if (nDisconnect == IDYES || nDisconnect == -1)
|
|
{
|
|
retValue = -16;
|
|
}
|
|
}
|
|
} // hCnct
|
|
} // IsNT()
|
|
}
|
|
|
|
free(pvs);
|
|
pvs = NULL;
|
|
|
|
return retValue;
|
|
}
|
|
|