Leaked source code of windows server 2003
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

/* 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;
}