Source code of Windows XP (NT5)
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.
 
 
 
 
 
 

2148 lines
58 KiB

//****************************************************************************
//
// Terminal Server CDmodem
//
//
// Copyright 1996, Citrix Systems Inc.
// Copyright (C) 1994-95 Microsft Corporation. All rights reserved.
//
// Filename: rastapi.c
//
// Revision History
//
// November 1998 updated by Qunbiao Guo for terminal server
// Mar 28 1992 Gurdeep Singh Pall Created
//
//
// Description: This file contains tapi codes for cdmodem.dll
//
//****************************************************************************
#include <nt.h>
#include <ntrtl.h>
#include <nturtl.h>
#include <windows.h>
#include <tapi.h>
#include <rasndis.h>
#include <wanioctl.h>
#include <rasman.h>
#include <raserror.h>
#include <eventlog.h>
#include <media.h>
#include <device.h>
#include <rasmxs.h>
#include <isdn.h>
#include <serial.h>
#include <stdlib.h>
#include <malloc.h>
#include <string.h>
#include "rastapi.h"
#ifdef CITRIX
#include <winstaw.h>
#include <icadd.h>
#include <icaapi.h>
#include "cdmodem.h"
#endif // CITRIX
#ifdef CITRIX
#ifdef DBG
#define DBGPRINT(_arg) DbgPrint _arg
#else
#define DBGPRINT(_arg) { }
#endif
#endif // CITRIX
#pragma warning (error:4312)
extern DWORD TotalPorts ;
extern HLINEAPP RasLine ;
extern HINSTANCE RasInstance ;
extern TapiLineInfo *RasTapiLineInfo ;
extern TapiPortControlBlock *RasPorts ;
extern TapiPortControlBlock *RasPortsEnd ;
extern HANDLE RasTapiMutex ;
extern BOOL Initialized ;
extern DWORD TapiThreadId ;
extern HANDLE TapiThreadHandle;
extern DWORD LoaderThreadId;
extern DWORD ValidPorts;
extern HANDLE ghAsyMac ;
DWORD GetInfo (TapiPortControlBlock *, BYTE *, WORD *) ;
DWORD SetInfo (TapiPortControlBlock *, RASMAN_PORTINFO *) ;
DWORD GetGenericParams (TapiPortControlBlock *, RASMAN_PORTINFO *, PWORD) ;
DWORD GetIsdnParams (TapiPortControlBlock *, RASMAN_PORTINFO * , PWORD) ;
DWORD GetX25Params (TapiPortControlBlock *, RASMAN_PORTINFO *, PWORD) ;
DWORD FillInX25Params (TapiPortControlBlock *, RASMAN_PORTINFO *) ;
DWORD FillInIsdnParams (TapiPortControlBlock *, RASMAN_PORTINFO *) ;
DWORD FillInGenericParams (TapiPortControlBlock *, RASMAN_PORTINFO *) ;
DWORD FillInUnimodemParams (TapiPortControlBlock *, RASMAN_PORTINFO *) ;
VOID SetModemParams (TapiPortControlBlock *hIOPort, LINECALLPARAMS *linecallparams) ;
DWORD InitiatePortDisconnection (TapiPortControlBlock *hIOPort) ;
TapiPortControlBlock *LookUpControlBlock (HANDLE hPort) ;
DWORD ValueToNum(RAS_PARAMS *p) ;
//* Serial APIs ************************************************************
//
//* PortEnum ---------------------------------------------------------------
//
// Function: This API returns a buffer containing a PortMediaInfo struct.
//
// Returns: SUCCESS
// ERROR_BUFFER_TOO_SMALL
// ERROR_READING_SECTIONNAME
// ERROR_READING_DEVICETYPE
// ERROR_READING_DEVICENAME
// ERROR_READING_USAGE
// ERROR_BAD_USAGE_IN_INI_FILE
//
//*
DWORD APIENTRY
PortEnum(PCDMODEM pCdModem, BYTE *pBuffer, WORD *pwSize, WORD *pwNumPorts)
{
PortMediaInfo *pinfo ;
TapiPortControlBlock *pports ;
DWORD numports = 0;
DWORD i ;
DBGPRINT(( "CDMODEM: PortEnum: Entry\n" ));
// **** Exclusion Begin ****
GetMutex (RasTapiMutex, INFINITE) ;
DBGPRINT(( "CDMODEM: PortEnum: Lock obtained\n" ));
if (!Initialized) {
HANDLE event;
LoaderThreadId = GetCurrentThreadId();
event = CreateEvent (NULL, FALSE, FALSE, NULL) ;
TapiThreadHandle = CreateThread (NULL, 5000, (LPTHREAD_START_ROUTINE) EnumerateTapiPorts,
(LPVOID) event,
0,
&TapiThreadId);
DBGPRINT(( "CDMODEM: PortEnum: waiting for ETP thread..." ));
IcaCdWaitForSingleObject (pCdModem->hStack, event, INFINITE) ;
DBGPRINT(( "complete\n" ));
if (RasLine == 0 || !ValidPorts) {
//
// Wait for the thread to go away!
//
DBGPRINT(( "CDMODEM: PortEnum: ETP didn't init waitin..." ));
IcaCdWaitForSingleObject(pCdModem->hStack, TapiThreadHandle, INFINITE);
DBGPRINT(( "complete\n" ));
CloseHandle (TapiThreadHandle) ;
// *** Exclusion End ***
FreeMutex (RasTapiMutex) ;
return ERROR_TAPI_CONFIGURATION ;
}
CloseHandle (event) ;
Initialized = TRUE ;
}
DBGPRINT(( "CDMODEM: PortEnum: TAPI init complete\n" ));
// calculate the number of valid ports
//
for (pports = RasPorts, i=0; i < TotalPorts; i++, pports++) {
if (pports->TPCB_State == PS_UNINITIALIZED)
continue ;
numports++ ;
}
if (*pwSize < numports*sizeof(PortMediaInfo)) {
*pwNumPorts = (WORD) numports ;
*pwSize = (WORD) *pwNumPorts*sizeof(PortMediaInfo) ;
// *** Exclusion End ***
FreeMutex (RasTapiMutex) ;
return ERROR_BUFFER_TOO_SMALL ;
}
*pwNumPorts = 0 ;
pinfo = (PortMediaInfo *)pBuffer ;
for (pports = RasPorts, i=0; i < TotalPorts; i++, pports++) {
if (pports->TPCB_State == PS_UNINITIALIZED)
continue ;
strcpy (pinfo->PMI_Name, pports->TPCB_Name) ;
pinfo->PMI_Usage = pports->TPCB_Usage ;
strcpy (pinfo->PMI_DeviceType, pports->TPCB_DeviceType) ;
strcpy (pinfo->PMI_DeviceName, pports->TPCB_DeviceName) ;
pinfo->PMI_LineDeviceId = pports->TPCB_Line->TLI_LineId;
pinfo->PMI_AddressId = pports->TPCB_AddressId;
pinfo++ ;
(*pwNumPorts)++ ;
}
// *** Exclusion End ***
FreeMutex (RasTapiMutex) ;
return(SUCCESS);
}
//* PortOpen ---------------------------------------------------------------
//
// Function: This API opens a COM port. It takes the port name in ASCIIZ
// form and supplies a handle to the open port. hNotify is use
// to notify the caller if the device on the port shuts down.
//
// PortOpen allocates a SerialPCB and places it at the head of
// the linked list of Serial Port Control Blocks.
//
// Returns: SUCCESS
// ERROR_PORT_NOT_CONFIGURED
// ERROR_DEVICE_NOT_READY
//
//*
DWORD APIENTRY
PortOpen(char *pszPortName, HANDLE *phIOPort, HANDLE hNotify)
{
TapiPortControlBlock *pports ;
DWORD retcode ;
DWORD i ;
// **** Exclusion Begin ****
GetMutex (RasTapiMutex, INFINITE) ;
pports = RasPorts ;
for (i=0; i < TotalPorts; i++) {
if (_stricmp(pszPortName, pports->TPCB_Name) == 0)
break ;
pports++ ;
}
if (i < TotalPorts) {
if (pports->TPCB_State == PS_UNINITIALIZED) {
// **** Exclusion END ****
FreeMutex (RasTapiMutex) ;
return ERROR_TAPI_CONFIGURATION ;
}
if (pports->TPCB_State != PS_CLOSED) {
// **** Exclusion END ****
FreeMutex (RasTapiMutex) ;
return ERROR_PORT_ALREADY_OPEN ;
}
if (pports->TPCB_Line->TLI_LineState == PS_CLOSED) { // open line
LINEDEVCAPS *linedevcaps ;
BYTE buffer[400] ;
linedevcaps = (LINEDEVCAPS *)buffer ;
linedevcaps->dwTotalSize = sizeof (buffer) ;
lineGetDevCaps (RasLine, pports->TPCB_Line->TLI_LineId, pports->TPCB_Line->NegotiatedApiVersion, pports->TPCB_Line->NegotiatedExtVersion, linedevcaps) ;
// Remove LINEMEDIAMODE_INTERACTIVEVOICE from the media mode since this mode cannot be
// used for receiving calls.
//
pports->TPCB_MediaMode = linedevcaps->dwMediaModes & ~(LINEMEDIAMODE_INTERACTIVEVOICE) ;
retcode =
lineOpen (RasLine,
pports->TPCB_Line->TLI_LineId,
&pports->TPCB_Line->TLI_LineHandle,
pports->TPCB_Line->NegotiatedApiVersion,
pports->TPCB_Line->NegotiatedExtVersion,
(ULONG) (ULONG_PTR)pports->TPCB_Line,
LINECALLPRIVILEGE_OWNER,
pports->TPCB_MediaMode,
NULL) ;
if (retcode) {
// **** Exclusion END ****
FreeMutex (RasTapiMutex) ;
return retcode ;
}
//
// Set monitoring of rings
//
lineSetStatusMessages (pports->TPCB_Line->TLI_LineHandle, LINEDEVSTATE_RINGING, 0) ;
//
// Always turn off the modem lights incase this is a modem device
//
if ((_stricmp (pports->TPCB_DeviceType, DEVICETYPE_UNIMODEM) == 0)) {
//
// unimodem struct not defined in any header
//
typedef struct _DEVCFG {
DWORD dwSize;
DWORD dwVersion;
WORD fwOptions;
WORD wWaitBong;
} DEVCFG;
#define LAUNCH_LIGHTS 8
LPVARSTRING var ;
BYTE buffer[1000] ;
DEVCFG *devcfg ;
var = (LPVARSTRING)buffer ;
var->dwTotalSize = 1000 ;
var->dwStringSize = 0 ;
lineGetDevConfig (pports->TPCB_Line->TLI_LineId, var, "comm/datamodem") ;
devcfg = (DEVCFG*) (((LPBYTE) var) + var->dwStringOffset) ;
devcfg->fwOptions &= ~LAUNCH_LIGHTS ;
lineSetDevConfig (pports->TPCB_Line->TLI_LineId, devcfg, var->dwStringSize, "comm/datamodem") ;
}
pports->TPCB_Line->TLI_LineState = PS_OPEN ;
}
// Initialize the parameters
//
pports->TPCB_Info[0][0] = '\0' ;
pports->TPCB_Info[1][0] = '\0' ;
pports->TPCB_Info[2][0] = '\0' ;
pports->TPCB_Info[3][0] = '\0' ;
pports->TPCB_Info[4][0] = '\0' ;
strcpy (pports->TPCB_Info[ISDN_CONNECTBPS_INDEX], "64000") ;
pports->TPCB_Line->TLI_OpenCount++ ;
pports->TPCB_DiscNotificationHandle = hNotify ;
// DbgPrint ("RASTAPI: TPCB_DiscNotificationHandle == %x\n", pports->TPCB_DiscNotificationHandle) ;
pports->TPCB_State = PS_OPEN ;
pports->TPCB_DisconnectReason = 0 ;
pports->TPCB_CommHandle = INVALID_HANDLE_VALUE ;
*phIOPort = (HANDLE) pports ;
// **** Exclusion END ****
FreeMutex (RasTapiMutex) ;
return(SUCCESS);
}
// **** Exclusion END ****
FreeMutex (RasTapiMutex) ;
return ERROR_PORT_NOT_CONFIGURED ;
}
//* PortClose --------------------------------------------------------------
//
// Function: This API closes the COM port for the input handle. It also
// finds the SerialPCB for the input handle, removes it from
// the linked list, and frees the memory for it
//
// Returns: SUCCESS
// Values returned by GetLastError()
//
//*
DWORD APIENTRY
PortClose (HANDLE hIOPort)
{
TapiPortControlBlock *pports = (TapiPortControlBlock *) hIOPort ;
// **** Exclusion Begin ****
GetMutex (RasTapiMutex, INFINITE) ;
pports->TPCB_Line->TLI_OpenCount-- ;
pports->TPCB_State = PS_CLOSED ;
if (pports->TPCB_DevConfig)
LocalFree (pports->TPCB_DevConfig) ;
pports->TPCB_DevConfig = NULL ;
if (pports->TPCB_Line->TLI_OpenCount == 0) {
pports->TPCB_Line->TLI_LineState = PS_CLOSED ;
lineClose (pports->TPCB_Line->TLI_LineHandle) ;
}
// **** Exclusion END ****
FreeMutex (RasTapiMutex) ;
return(SUCCESS);
}
//* PortGetInfo ------------------------------------------------------------
//
// Function: This API returns a block of information to the caller about
// the port state. This API may be called before the port is
// open in which case it will return inital default values
// instead of actual port values.
//
// hIOPort can be null in which case use portname to give information
// hIOPort may be the actual file handle or the hIOPort returned in port open.
//
// Returns: SUCCESS
//
//*
DWORD APIENTRY
PortGetInfo(HANDLE hIOPort, CHAR *pszPortName, BYTE *pBuffer, WORD *pwSize)
{
DWORD i ;
DWORD retcode = ERROR_FROM_DEVICE ;
// **** Exclusion Begin ****
GetMutex (RasTapiMutex, INFINITE) ;
// hIOPort or pszPortName must be valid:
//
for (i=0; i < TotalPorts; i++) {
if (!_stricmp(RasPorts[i].TPCB_Name, pszPortName) || (hIOPort == (HANDLE) &RasPorts[i]) || (hIOPort == RasPorts[i].TPCB_CommHandle)) {
hIOPort = (HANDLE) &RasPorts[i] ;
retcode = GetInfo ((TapiPortControlBlock *) hIOPort, pBuffer, pwSize) ;
break ;
}
}
// **** Exclusion END ****
FreeMutex (RasTapiMutex) ;
return (retcode);
}
//* PortSetInfo ------------------------------------------------------------
//
// Function: The values for most input keys are used to set the port
// parameters directly. However, the carrier BPS and the
// error conrol on flag set fields in the Serial Port Control
// Block only, and not the port.
//
// hIOPort may the port handle returned in portopen or the actual file handle.
//
// Returns: SUCCESS
// ERROR_WRONG_INFO_SPECIFIED
// Values returned by GetLastError()
//*
DWORD APIENTRY
PortSetInfo(HANDLE hIOPort, RASMAN_PORTINFO *pInfo)
{
DWORD retcode = ERROR_WRONG_INFO_SPECIFIED ;
// **** Exclusion Begin ****
GetMutex (RasTapiMutex, INFINITE) ;
if (hIOPort = LookUpControlBlock(hIOPort)) {
retcode = SetInfo ((TapiPortControlBlock *) hIOPort, pInfo) ;
}
// **** Exclusion END ****
FreeMutex (RasTapiMutex) ;
return (retcode);
}
//* PortTestSignalState ----------------------------------------------------
//
// Function: Really only has meaning if the call was active. Will return
//
// Returns: SUCCESS
// Values returned by GetLastError()
//
//*
DWORD APIENTRY
PortTestSignalState(HANDLE hPort, DWORD *pdwDeviceState)
{
BYTE buffer[200] ;
LINECALLSTATUS *pcallstatus ;
DWORD retcode = SUCCESS ;
TapiPortControlBlock *hIOPort = (TapiPortControlBlock *) hPort;
// **** Exclusion Begin ****
GetMutex (RasTapiMutex, INFINITE) ;
*pdwDeviceState = 0 ;
memset (buffer, 0, sizeof(buffer)) ;
pcallstatus = (LINECALLSTATUS *) buffer ;
pcallstatus->dwTotalSize = sizeof (buffer) ;
// First check if we have a disconnect reason stored away. if so return that.
//
if (hIOPort->TPCB_DisconnectReason) {
*pdwDeviceState = hIOPort->TPCB_DisconnectReason ;
} else if (hIOPort->TPCB_State != PS_CLOSED) {
// Only in case of CONNECTING or CONNECTED do we care how the link dropped
//
if (hIOPort->TPCB_State == PS_CONNECTING || hIOPort->TPCB_State == PS_CONNECTED) {
retcode = lineGetCallStatus (hIOPort->TPCB_CallHandle, pcallstatus) ;
if (retcode)
;
else if (pcallstatus->dwCallState == LINECALLSTATE_DISCONNECTED)
*pdwDeviceState = SS_LINKDROPPED ;
else if (pcallstatus->dwCallState == LINECALLSTATE_IDLE)
*pdwDeviceState = SS_HARDWAREFAILURE ;
else if (pcallstatus->dwCallState == LINECALLSTATE_SPECIALINFO)
*pdwDeviceState = SS_HARDWAREFAILURE ;
} else
*pdwDeviceState = SS_LINKDROPPED | SS_HARDWAREFAILURE ;
}
// **** Exclusion END ****
FreeMutex (RasTapiMutex) ;
return retcode ;
}
//* PortDisconnect ---------------------------------------------------------
//
// Function: This API is called to drop a connection and close AsyncMac.
//
// Returns: SUCCESS
// PENDING
// ERROR_PORT_NOT_OPEN
//
//*
DWORD APIENTRY
PortDisconnect(HANDLE hPort)
{
DWORD retcode = SUCCESS ;
TapiPortControlBlock *hIOPort = (TapiPortControlBlock *) hPort;
// **** Exclusion Begin ****
GetMutex (RasTapiMutex, INFINITE) ;
// DbgPrint ("PortDisconnect, state = %d\n", hIOPort->TPCB_State) ;
if ((hIOPort->TPCB_State == PS_CONNECTED) ||
(hIOPort->TPCB_State == PS_CONNECTING) ||
((hIOPort->TPCB_State == PS_LISTENING) && (hIOPort->TPCB_ListenState != LS_WAIT))) {
retcode = InitiatePortDisconnection (hIOPort) ;
// If we had saved away the device config then we restore it here.
//
if (hIOPort->TPCB_DefaultDevConfig) {
lineSetDevConfig (hIOPort->TPCB_Line->TLI_LineId, hIOPort->TPCB_DefaultDevConfig, hIOPort->TPCB_DefaultDevConfigSize, "comm/datamodem") ;
LocalFree (hIOPort->TPCB_DefaultDevConfig) ;
hIOPort->TPCB_DefaultDevConfig = NULL ;
}
} else if (hIOPort->TPCB_State == PS_LISTENING) {
hIOPort->TPCB_State = PS_OPEN ; // for LS_WAIT listen state case
retcode = SUCCESS ;
} else if (hIOPort->TPCB_State == PS_DISCONNECTING) {
retcode = PENDING ;
}
// **** Exclusion END ****
FreeMutex (RasTapiMutex) ;
return retcode ;
}
//* PortInit ---------------------------------------------------------------
//
// Function: This API re-initializes the com port after use.
//
// Returns: SUCCESS
// ERROR_PORT_NOT_CONFIGURED
// ERROR_DEVICE_NOT_READY
//
//*
DWORD APIENTRY
PortInit(HANDLE hIOPort)
{
return(SUCCESS);
}
//* PortCompressionSetInfo -------------------------------------------------
//
// Function: This API selects Asyncmac compression mode by setting
// Asyncmac's compression bits.
//
// Returns: SUCCESS
// Return code from GetLastError
//
//*
DWORD
PortCompressionSetInfo(HANDLE hIOPort)
{
return SUCCESS;
}
//* PortClearStatistics ----------------------------------------------------
//
// Function: This API is used to mark the beginning of the period for which
// statistics will be reported. The current numbers are copied
// from the MAC and stored in the Serial Port Control Block. At
// the end of the period PortGetStatistics will be called to
// compute the difference.
//
// Returns: SUCCESS
// ERROR_PORT_NOT_OPEN
//*
DWORD
PortClearStatistics(HANDLE hIOPort)
{
return SUCCESS;
}
//* PortGetStatistics ------------------------------------------------------
//
// Function: This API reports MAC statistics since the last call to
// PortClearStatistics.
//
// Returns: SUCCESS
// ERROR_PORT_NOT_OPEN
//*
DWORD
PortGetStatistics(HANDLE hIOPort, RAS_STATISTICS *pStat)
{
return(SUCCESS);
}
//* PortSetFraming -------------------------------------------------------
//
// Function: Sets the framing type with the mac
//
// Returns: SUCCESS
//
//*
DWORD APIENTRY
PortSetFraming(HANDLE hIOPort, DWORD SendFeatureBits, DWORD RecvFeatureBits,
DWORD SendBitMask, DWORD RecvBitMask)
{
return(SUCCESS);
}
//* PortGetPortState -------------------------------------------------------
//
// Function: This API is used in MS-DOS only.
//
// Returns: SUCCESS
//
//*
DWORD APIENTRY
PortGetPortState(char *pszPortName, DWORD *pdwUsage)
{
return(SUCCESS);
}
//* PortChangeCallback -----------------------------------------------------
//
// Function: This API is used in MS-DOS only.
//
// Returns: SUCCESS
//
//*
DWORD APIENTRY
PortChangeCallback(HANDLE hIOPort)
{
return(SUCCESS);
}
//* PortGetIOHandle()
//
// Function: For the given hIOPort this returns the file handle for the connection
//
// Returns: SUCCESS
//
//*
DWORD APIENTRY
PortGetIOHandle(HANDLE hPort, HANDLE *FileHandle)
{
DWORD retcode ;
TapiPortControlBlock *hIOPort = (TapiPortControlBlock *) hPort;
// **** Exclusion Begin ****
GetMutex (RasTapiMutex, INFINITE) ;
if (hIOPort->TPCB_State == PS_CONNECTED) {
*FileHandle = hIOPort->TPCB_CommHandle ;
retcode = SUCCESS ;
} else
retcode = ERROR_PORT_NOT_OPEN ;
// **** Exclusion Begin ****
FreeMutex (RasTapiMutex) ;
return retcode ;
}
//* DeviceEnum() -----------------------------------------------------------
//
// Function: Enumerates all devices in the device INF file for the
// specified DevictType.
//
// Returns: Return codes from RasDevEnumDevices
//
//*
DWORD APIENTRY
DeviceEnum (char *pszDeviceType,
WORD *pcEntries,
BYTE *pBuffer,
WORD *pwSize)
{
*pwSize = 0 ;
*pcEntries = 0 ;
return(SUCCESS);
}
//* DeviceGetInfo() --------------------------------------------------------
//
// Function: Returns a summary of current information from the InfoTable
// for the device on the port in Pcb.
//
// Returns: Return codes from GetDeviceCB, BuildOutputTable
//*
DWORD APIENTRY
DeviceGetInfo(HANDLE hPort,
char *pszDeviceType,
char *pszDeviceName,
BYTE *pInfo,
WORD *pwSize)
{
DWORD retcode ;
TapiPortControlBlock *hIOPort = LookUpControlBlock(hPort);
if (!hIOPort)
return ERROR_PORT_NOT_FOUND ;
// **** Exclusion Begin ****
GetMutex (RasTapiMutex, INFINITE) ;
retcode = GetInfo (hIOPort, pInfo, pwSize) ;
// **** Exclusion End ****
FreeMutex (RasTapiMutex) ;
return(retcode);
}
//* DeviceSetInfo() --------------------------------------------------------
//
// Function: Sets attributes in the InfoTable for the device on the
// port in Pcb.
//
// Returns: Return codes from GetDeviceCB, UpdateInfoTable
//*
DWORD APIENTRY
DeviceSetInfo(HANDLE hPort,
char *pszDeviceType,
char *pszDeviceName,
RASMAN_DEVICEINFO *pInfo)
{
DWORD retcode ;
TapiPortControlBlock *hIOPort = LookUpControlBlock(hPort);
if (!hIOPort)
return ERROR_PORT_NOT_FOUND ;
// **** Exclusion Begin ****
GetMutex (RasTapiMutex, INFINITE) ;
retcode = SetInfo (hIOPort, (RASMAN_PORTINFO*) pInfo) ;
// **** Exclusion End ****
FreeMutex (RasTapiMutex) ;
return (retcode);
}
//* DeviceConnect() --------------------------------------------------------
//
// Function: Initiates the process of connecting a device.
//
// Returns: Return codes from ConnectListen
//*
DWORD APIENTRY
DeviceConnect(HANDLE hPort,
char *pszDeviceType,
char *pszDeviceName,
HANDLE hNotifier)
{
LINECALLPARAMS *linecallparams ;
LPVARSTRING var ;
BYTE buffer [2000] ;
BYTE *nextstring ;
TapiPortControlBlock *hIOPort = LookUpControlBlock(hPort);
if (!hIOPort)
return ERROR_PORT_NOT_FOUND ;
// **** Exclusion Begin ****
GetMutex (RasTapiMutex, INFINITE) ;
// if dev config has been set for this device we should call down and set it.
//
if ((hIOPort->TPCB_DevConfig) && (_stricmp (hIOPort->TPCB_DeviceType, DEVICETYPE_UNIMODEM) == 0)) {
// Before the write this - save away the current setting for the device.
//
var = (LPVARSTRING)buffer ;
var->dwTotalSize = 2000 ;
var->dwStringSize = 0 ;
lineGetDevConfig (hIOPort->TPCB_Line->TLI_LineId, var, "comm/datamodem") ;
// Alloc mem for the returned info
//
hIOPort->TPCB_DefaultDevConfig = LocalAlloc (LPTR, var->dwStringSize) ;
if (hIOPort->TPCB_DefaultDevConfig == NULL) {
FreeMutex (RasTapiMutex) ;
return ERROR_NOT_ENOUGH_MEMORY;
}
hIOPort->TPCB_DefaultDevConfigSize = var->dwStringSize ;
memcpy (hIOPort->TPCB_DefaultDevConfig, (CHAR*)var+var->dwStringOffset, var->dwStringSize) ;
lineSetDevConfig (hIOPort->TPCB_Line->TLI_LineId, hIOPort->TPCB_DevConfig, hIOPort->TPCB_SizeOfDevConfig, "comm/datamodem") ;
}
memset (buffer, 0, sizeof(buffer)) ;
linecallparams = (LINECALLPARAMS *) buffer ;
nextstring = (buffer + sizeof (LINECALLPARAMS)) ;
linecallparams->dwTotalSize = sizeof(buffer) ;
strcpy (nextstring, hIOPort->TPCB_Address) ;
linecallparams->dwOrigAddressSize = strlen (nextstring) ;
linecallparams->dwOrigAddressOffset = (ULONG) (nextstring - buffer) ;
linecallparams->dwAddressMode = LINEADDRESSMODE_DIALABLEADDR ;
nextstring += linecallparams->dwOrigAddressSize ;
if (_stricmp (hIOPort->TPCB_DeviceType, DEVICETYPE_ISDN) == 0)
SetIsdnParams (hIOPort, linecallparams) ;
else if (_stricmp (hIOPort->TPCB_DeviceType, DEVICETYPE_X25) == 0) {
if (*hIOPort->TPCB_Info[X25_USERDATA_INDEX] != '\0') {
strcpy (nextstring, hIOPort->TPCB_Info[X25_USERDATA_INDEX]) ;
linecallparams->dwUserUserInfoSize = strlen (nextstring) ;
linecallparams->dwUserUserInfoOffset = (ULONG) (nextstring - buffer) ;
nextstring += linecallparams->dwUserUserInfoSize ;
}
if (*hIOPort->TPCB_Info[X25_FACILITIES_INDEX] != '\0') {
strcpy (nextstring, hIOPort->TPCB_Info[X25_FACILITIES_INDEX]) ;
linecallparams->dwDevSpecificSize = strlen (nextstring) ;
linecallparams->dwDevSpecificOffset = (ULONG) (nextstring - buffer) ;
nextstring += linecallparams->dwDevSpecificSize ;
}
// Diagnostic key is ignored.
} else if (_stricmp (hIOPort->TPCB_DeviceType, DEVICETYPE_UNIMODEM) == 0) {
SetModemParams (hIOPort, linecallparams) ;
}
hIOPort->TPCB_RequestId = INFINITE ; // mark request id as unused
hIOPort->TPCB_CallHandle = (HCALL) INFINITE ; // set call handle to bogus value
hIOPort->TPCB_AsyncErrorCode = SUCCESS ; // initialize
if ((hIOPort->TPCB_RequestId =
lineMakeCall (hIOPort->TPCB_Line->TLI_LineHandle, &hIOPort->TPCB_CallHandle, hIOPort->TPCB_Info[ADDRESS_INDEX], 0, linecallparams)) > 0x80000000 ) {
// **** Exclusion End ****
FreeMutex (RasTapiMutex) ;
// DbgPrint ("RASTAPI: lineMakeCall failed -> returned %x\n", hIOPort->TPCB_RequestId) ;
if (hIOPort->TPCB_RequestId == LINEERR_INUSE)
return ERROR_PORT_NOT_AVAILABLE ;
return ERROR_FROM_DEVICE ;
}
ResetEvent (hNotifier) ;
hIOPort->TPCB_ReqNotificationHandle = hNotifier ;
hIOPort->TPCB_State = PS_CONNECTING ;
hIOPort->TPCB_DisconnectReason = 0 ;
// **** Exclusion End ****
FreeMutex (RasTapiMutex) ;
return (PENDING);
}
//*
//
//
//
//
//*
VOID
SetIsdnParams (TapiPortControlBlock *hIOPort, LINECALLPARAMS *linecallparams)
{
WORD numchannels ;
WORD fallback ;
#ifndef CITRIX
// Line type
//
if (_stricmp (hIOPort->TPCB_Info[ISDN_LINETYPE_INDEX], ISDN_LINETYPE_STRING_64DATA) == 0) {
linecallparams->dwBearerMode = LINEBEARERMODE_DATA ;
linecallparams->dwMinRate = 64000 ;
linecallparams->dwMaxRate = 64000 ;
linecallparams->dwMediaMode = LINEMEDIAMODE_DIGITALDATA ;
} else if (_stricmp (hIOPort->TPCB_Info[ISDN_LINETYPE_INDEX], ISDN_LINETYPE_STRING_56DATA) == 0) {
linecallparams->dwBearerMode = LINEBEARERMODE_DATA ;
linecallparams->dwMinRate = 56000 ;
linecallparams->dwMaxRate = 56000 ;
linecallparams->dwMediaMode = LINEMEDIAMODE_DIGITALDATA ;
} else if (_stricmp (hIOPort->TPCB_Info[ISDN_LINETYPE_INDEX], ISDN_LINETYPE_STRING_56VOICE) == 0) {
linecallparams->dwBearerMode = LINEBEARERMODE_VOICE ;
linecallparams->dwMinRate = 56000 ;
linecallparams->dwMaxRate = 56000 ;
linecallparams->dwMediaMode = LINEMEDIAMODE_UNKNOWN ;
} else { // default
linecallparams->dwBearerMode = LINEBEARERMODE_DATA ;
linecallparams->dwMinRate = 64000 ;
linecallparams->dwMaxRate = 64000 ;
linecallparams->dwMediaMode = LINEMEDIAMODE_DIGITALDATA ;
}
if (hIOPort->TPCB_Info[ISDN_CHANNEL_AGG_INDEX][0] != '\0')
numchannels = atoi(hIOPort->TPCB_Info[ISDN_CHANNEL_AGG_INDEX]) ;
else
numchannels = 1 ; // default
if (hIOPort->TPCB_Info[ISDN_FALLBACK_INDEX] != '\0')
fallback = atoi(hIOPort->TPCB_Info[ISDN_FALLBACK_INDEX]) ;
else
fallback = 1 ; // default
if (fallback)
linecallparams->dwMinRate = 56000 ; // always allow the min
else
linecallparams->dwMinRate = numchannels * linecallparams->dwMaxRate ;
linecallparams->dwMaxRate = numchannels * linecallparams->dwMaxRate ;
#else // CITRIX
DBGPRINT(("CDMODEM: SetIsdnParams: ISDN not supported\n"));
ASSERT(FALSE);
#endif // CITRIX
}
//*
//
//
//
//
//*
VOID
SetModemParams (TapiPortControlBlock *hIOPort, LINECALLPARAMS *linecallparams)
{
WORD numchannels ;
WORD fallback ;
BYTE buffer[800] ;
LINEDEVCAPS *linedevcaps ;
memset (buffer, 0, sizeof(buffer)) ;
linedevcaps = (LINEDEVCAPS *)buffer ;
linedevcaps->dwTotalSize = sizeof(buffer) ;
// Get a count of all addresses across all lines
//
if (lineGetDevCaps (RasLine, hIOPort->TPCB_Line->TLI_LineId, hIOPort->TPCB_Line->NegotiatedApiVersion, hIOPort->TPCB_Line->NegotiatedExtVersion, linedevcaps))
linecallparams->dwBearerMode = LINEBEARERMODE_VOICE ; // in case of failure try the common case - modems
if (linedevcaps->dwBearerModes & LINEBEARERMODE_VOICE)
linecallparams->dwBearerMode = LINEBEARERMODE_VOICE ;
else
linecallparams->dwBearerMode = LINEBEARERMODE_DATA ;
//
// do not dial without dialtone
//
linecallparams->dwCallParamFlags |= LINECALLPARAMFLAGS_IDLE ;
linecallparams->dwMinRate = 2400 ;
linecallparams->dwMaxRate = 115200 ;
linecallparams->dwMediaMode = LINEMEDIAMODE_DATAMODEM ;
}
//* DeviceListen() ---------------------------------------------------------
//
// Function: Initiates the process of listening for a remote device
// to connect to a local device.
//
// Returns: Return codes from ConnectListen
//*
DWORD APIENTRY
DeviceListen(HANDLE hPort,
char *pszDeviceType,
char *pszDeviceName,
HANDLE hNotifier)
{
DWORD retcode ;
TapiPortControlBlock *hIOPort = LookUpControlBlock(hPort);
if (!hIOPort)
return ERROR_PORT_NOT_FOUND ;
// **** Exclusion Begin ****
GetMutex (RasTapiMutex, INFINITE) ;
// DbgPrint ("DevListen, State = %d\n", hIOPort->TPCB_State) ;
// If the state is DISCONNECTING (this could happen since rasman waits only 10 seconds
// for the lower layers to complete a disconnect request), then we have no option but
// to close and open the line.
//
if (hIOPort->TPCB_State == PS_DISCONNECTING) {
// DbgPrint ("DevListen: Hit code path where device is still disconnecting\n") ;
lineClose (hIOPort->TPCB_Line->TLI_LineHandle) ;
Sleep (30L) ; // allow a "reasonable" time to allow clean up.
retcode = lineOpen (RasLine,
hIOPort->TPCB_Line->TLI_LineId,
&hIOPort->TPCB_Line->TLI_LineHandle,
hIOPort->TPCB_Line->NegotiatedApiVersion,
hIOPort->TPCB_Line->NegotiatedExtVersion,
(ULONG) (ULONG_PTR) hIOPort->TPCB_Line,
LINECALLPRIVILEGE_OWNER,
hIOPort->TPCB_MediaMode,
NULL) ;
if (retcode) {
// **** Exclusion End ****
FreeMutex (RasTapiMutex) ;
// DbgPrint ("DevListen: lineOpen failed with %d \n", retcode) ;
return ERROR_FROM_DEVICE ;
}
//
// Set monitoring of rings
//
lineSetStatusMessages (hIOPort->TPCB_Line->TLI_LineHandle, LINEDEVSTATE_RINGING, 0) ;
}
if (hIOPort->TPCB_Line->TLI_LineState != PS_LISTENING)
hIOPort->TPCB_Line->TLI_LineState = PS_LISTENING ;
hIOPort->TPCB_State = PS_LISTENING ;
hIOPort->TPCB_ListenState = LS_WAIT ;
hIOPort->TPCB_DisconnectReason = 0 ;
ResetEvent (hNotifier) ;
hIOPort->TPCB_ReqNotificationHandle = hNotifier ;
hIOPort->TPCB_CallHandle = (HCALL)(ULONG_PTR)INVALID_HANDLE_VALUE ;
// **** Exclusion End ****
FreeMutex (RasTapiMutex) ;
return (PENDING);
}
//* DeviceDone() -----------------------------------------------------------
//
// Function: Informs the device dll that the attempt to connect or listen
// has completed.
//
// Returns: nothing
//*
VOID APIENTRY
DeviceDone(HANDLE hPort)
{
TapiPortControlBlock *hIOPort = LookUpControlBlock(hPort);
if (!hIOPort)
return ;
// **** Exclusion Begin ****
GetMutex (RasTapiMutex, INFINITE) ;
hIOPort->TPCB_ReqNotificationHandle = NULL ; // no more needed.
// **** Exclusion End ****
FreeMutex (RasTapiMutex) ;
}
//* DeviceWork() -----------------------------------------------------------
//
// Function: This function is called following DeviceConnect or
// DeviceListen to further the asynchronous process of
// connecting or listening.
//
// Returns: ERROR_DCB_NOT_FOUND
// ERROR_STATE_MACHINES_NOT_STARTED
// Return codes from DeviceStateMachine
//*
DWORD APIENTRY
DeviceWork(HANDLE hPort,
HANDLE hNotifier)
{
LINECALLSTATUS *callstatus ;
BYTE buffer [1000] ;
DWORD retcode = ERROR_FROM_DEVICE ;
TapiPortControlBlock *hIOPort = LookUpControlBlock(hPort);
if (!hIOPort)
return ERROR_PORT_NOT_FOUND ;
// **** Exclusion Begin ****
GetMutex (RasTapiMutex, INFINITE) ;
memset (buffer, 0, sizeof(buffer)) ;
callstatus = (LINECALLSTATUS *)buffer ;
callstatus->dwTotalSize = sizeof(buffer) ;
DBGPRINT(("Devicework enter with ps status: %d \n", hIOPort->TPCB_State));
if (hIOPort->TPCB_State == PS_CONNECTING) {
if (hIOPort->TPCB_AsyncErrorCode != SUCCESS) {
retcode = hIOPort->TPCB_AsyncErrorCode ;
hIOPort->TPCB_AsyncErrorCode = SUCCESS ;
} else if (lineGetCallStatus (hIOPort->TPCB_CallHandle, callstatus))
retcode = ERROR_FROM_DEVICE ;
else if (callstatus->dwCallState == LINECALLSTATE_CONNECTED) {
hIOPort->TPCB_State = PS_CONNECTED ;
retcode = SUCCESS ;
} else if (callstatus->dwCallState == LINECALLSTATE_DISCONNECTED) {
retcode = ERROR_FROM_DEVICE ;
if (callstatus->dwCallStateMode == LINEDISCONNECTMODE_BUSY)
retcode = ERROR_LINE_BUSY ;
else if (callstatus->dwCallStateMode == LINEDISCONNECTMODE_NOANSWER)
retcode = ERROR_NO_ANSWER ;
else if (callstatus->dwCallStateMode == LINEDISCONNECTMODE_CANCELLED)
retcode = ERROR_USER_DISCONNECTION;
} else if ((callstatus->dwCallState == LINECALLSTATE_SPECIALINFO) &&
(callstatus->dwCallStateMode == LINESPECIALINFO_NOCIRCUIT)) {
retcode = ERROR_NO_ACTIVE_ISDN_LINES ;
}
}
if (hIOPort->TPCB_State == PS_LISTENING) {
DBGPRINT(("DEvicework PS listning, listeining status: %d \n", hIOPort->TPCB_ListenState));
if (hIOPort->TPCB_ListenState == LS_ERROR)
retcode = ERROR_FROM_DEVICE ;
else if (hIOPort->TPCB_ListenState == LS_ACCEPT) {
hIOPort->TPCB_RequestId = lineAccept (hIOPort->TPCB_CallHandle, NULL, 0) ;
DBGPRINT(("Devicework lineAccept return status: 0x%x \n", hIOPort->TPCB_RequestId));
DBGPRINT(("Devicework: change listening status from LS_ACCEPT to LS_ANSWER \n"));
if (hIOPort->TPCB_RequestId > 0x80000000 ) // ERROR or SUCCESS
hIOPort->TPCB_ListenState = LS_ANSWER ;
else if (hIOPort->TPCB_RequestId == 0)
hIOPort->TPCB_ListenState = LS_ANSWER ;
retcode = PENDING ;
}
if (hIOPort->TPCB_ListenState == LS_ANSWER) {
hIOPort->TPCB_RequestId = lineAnswer (hIOPort->TPCB_CallHandle, NULL, 0) ;
DBGPRINT(("Devicework lineAnswer return status: 0x%x \n",
hIOPort->TPCB_RequestId));
if (hIOPort->TPCB_RequestId > 0x80000000 )
retcode = ERROR_FROM_DEVICE ;
else if (hIOPort->TPCB_RequestId)
retcode = PENDING ;
else // SUCCESS
hIOPort->TPCB_ListenState = LS_COMPLETE ;
}
if (hIOPort->TPCB_ListenState == LS_COMPLETE) {
DBGPRINT(("Devicework: LS_COMPLETE \n"));
if (hIOPort->TPCB_CallHandle == (HCALL)(ULONG_PTR)INVALID_HANDLE_VALUE) {
retcode = ERROR_FROM_DEVICE ;
} else {
hIOPort->TPCB_State = PS_CONNECTED ;
retcode = SUCCESS ; //
}
}
}
// If we have connected, then get the com port handle for use in terminal modem i/o
//
if (hIOPort->TPCB_State == PS_CONNECTED) {
VARSTRING *varstring ;
BYTE buffer [100] ;
// get the cookie to realize tapi and ndis endpoints
//
varstring = (VARSTRING *) buffer ;
varstring->dwTotalSize = sizeof(buffer) ;
// Unimodem/asyncmac linegetid returns a comm port handle. Other medias give the endpoint itself back in linegetid
// This has to do with the fact that modems/asyncmac are not a miniport.
//
if (_stricmp (hIOPort->TPCB_DeviceType, DEVICETYPE_UNIMODEM) == 0) {
if (lineGetID (hIOPort->TPCB_Line->TLI_LineHandle, hIOPort->TPCB_AddressId, hIOPort->TPCB_CallHandle, LINECALLSELECT_CALL, varstring, "comm/datamodem")) {
// **** Exclusion End ****
FreeMutex (RasTapiMutex) ;
return ERROR_FROM_DEVICE ;
}
hIOPort->TPCB_CommHandle = LongToHandle(*((DWORD *) ((BYTE *)varstring+varstring->dwStringOffset))) ;
// Initialize the port for approp. buffers
//
SetupComm (hIOPort->TPCB_CommHandle, 1514, 1514) ;
} else {
if (lineGetID (hIOPort->TPCB_Line->TLI_LineHandle, hIOPort->TPCB_AddressId, hIOPort->TPCB_CallHandle, LINECALLSELECT_CALL, varstring, "NDIS")) {
// **** Exclusion End ****
FreeMutex (RasTapiMutex) ;
return ERROR_FROM_DEVICE ;
}
hIOPort->TPCB_Endpoint = *((DWORD *) ((BYTE *)varstring+varstring->dwStringOffset)) ;
}
// DbgPrint ("L\n") ;
}
if (retcode == PENDING) {
DBGPRINT(("Devicework: Reset event \n"));
ResetEvent (hNotifier) ;
}
// **** Exclusion End ****
FreeMutex (RasTapiMutex) ;
return(retcode);
}
//* DeviceSetDevConfig()
//
// Function: Called to set an opaque blob of data to configure a device.
//
// Returns: LocalAlloc returned values.
//
DWORD
DeviceSetDevConfig (HANDLE hPort, PBYTE devconfig, DWORD sizeofdevconfig)
{
TapiPortControlBlock *hIOPort = LookUpControlBlock(hPort);
if (!hIOPort)
return ERROR_PORT_NOT_FOUND ;
if (_stricmp (hIOPort->TPCB_DeviceType, DEVICETYPE_UNIMODEM))
return SUCCESS ;
// **** Exclusion Begin ****
GetMutex (RasTapiMutex, INFINITE) ;
if (hIOPort->TPCB_DevConfig != NULL)
LocalFree (hIOPort->TPCB_DevConfig) ;
if ((hIOPort->TPCB_DevConfig = LocalAlloc(LPTR, sizeofdevconfig)) == NULL) {
// **** Exclusion End ****
FreeMutex (RasTapiMutex) ;
return(GetLastError());
}
memcpy (hIOPort->TPCB_DevConfig, devconfig, sizeofdevconfig) ;
hIOPort->TPCB_SizeOfDevConfig = sizeofdevconfig ;
// **** Exclusion End ****
FreeMutex (RasTapiMutex) ;
return (SUCCESS);
}
//* DeviceGetDevConfig()
//
// Function: Called to set an opaque blob of data to configure a device.
//
// Returns: LocalAlloc returned values.
//
DWORD
DeviceGetDevConfig (char *name, PBYTE devconfig, DWORD *sizeofdevconfig)
{
TapiPortControlBlock *hIOPort = NULL;
DWORD i ;
BYTE buffer[2000] ;
LPVARSTRING var ;
PBYTE configptr ;
DWORD configsize ;
DWORD retcode ;
// hIOPort or pszPortName must be valid:
//
for (i=0; i < TotalPorts; i++) {
if (!_stricmp(RasPorts[i].TPCB_Name, name)) {
hIOPort = (HANDLE) &RasPorts[i] ;
break ;
}
}
if (!hIOPort)
return ERROR_PORT_NOT_FOUND ;
if (_stricmp (hIOPort->TPCB_DeviceType, DEVICETYPE_UNIMODEM)) {
*sizeofdevconfig = 0 ;
return SUCCESS ;
}
// **** Exclusion Begin ****
GetMutex (RasTapiMutex, INFINITE) ;
if (hIOPort->TPCB_DevConfig != NULL) {
configptr = hIOPort->TPCB_DevConfig ;
configsize = hIOPort->TPCB_SizeOfDevConfig ;
} else {
// Make var string
//
var = (LPVARSTRING)buffer ;
var->dwTotalSize = 2000 ;
var->dwStringSize = 0 ;
lineGetDevConfig (hIOPort->TPCB_Line->TLI_LineId, var, "comm/datamodem") ;
configptr = ((CHAR *)var + var->dwStringOffset) ;
configsize = var->dwStringSize ;
}
if (*sizeofdevconfig > configsize) {
memcpy (devconfig, configptr, configsize) ;
retcode = SUCCESS ;
} else
retcode = ERROR_BUFFER_TOO_SMALL ;
*sizeofdevconfig = configsize ;
// **** Exclusion End ****
FreeMutex (RasTapiMutex) ;
return (retcode);
}
//*
//
//
//
//*
DWORD
GetInfo (TapiPortControlBlock *hIOPort, BYTE *pBuffer, WORD *pwSize)
{
if (_stricmp (hIOPort->TPCB_DeviceType, DEVICETYPE_ISDN) == 0)
GetIsdnParams (hIOPort, (RASMAN_PORTINFO *) pBuffer, pwSize) ;
else if (_stricmp (hIOPort->TPCB_DeviceType, DEVICETYPE_X25) == 0)
GetX25Params (hIOPort, (RASMAN_PORTINFO *) pBuffer, pwSize) ;
else
GetGenericParams (hIOPort, (RASMAN_PORTINFO *) pBuffer, pwSize) ;
return SUCCESS ;
}
//* SetInfo()
//
//
//
//*
DWORD
SetInfo (TapiPortControlBlock *hIOPort, RASMAN_PORTINFO *pBuffer)
{
DWORD Error;
if (_stricmp (hIOPort->TPCB_DeviceType, DEVICETYPE_UNIMODEM) == 0)
Error = FillInUnimodemParams (hIOPort, pBuffer) ;
if (_stricmp (hIOPort->TPCB_DeviceType, DEVICETYPE_ISDN) == 0)
Error = FillInIsdnParams (hIOPort, pBuffer) ;
else if (_stricmp (hIOPort->TPCB_DeviceType, DEVICETYPE_X25) == 0)
Error = FillInX25Params (hIOPort, pBuffer) ;
else
Error = FillInGenericParams (hIOPort, pBuffer) ;
return Error ;
}
//* FillInUnimodemParams()
//
// Function: We do more than fill in the params if the params are ones that are required to be set
// right then.
//
// Returns: ERROR_WRONG_INFO_SPECIFIED.
// Comm related Win32 errors
// SUCCESS.
//*
DWORD
FillInUnimodemParams (TapiPortControlBlock *hIOPort, RASMAN_PORTINFO *pInfo)
{
RAS_PARAMS *p;
WORD i;
DWORD index = 0xfefefefe ;
DCB DCB ;
#define INITIALIZED_VALUE 0xde
BYTE DCBByteSize = INITIALIZED_VALUE ;
BYTE DCBParity = INITIALIZED_VALUE ;
BYTE DCBStopBits = INITIALIZED_VALUE ;
BOOL DCBProcessingRequired = FALSE ;
for (i=0, p=pInfo->PI_Params; i<pInfo->PI_NumOfParams; i++, p++) {
if (_stricmp(p->P_Key, SER_DATABITS_KEY) == 0) {
DCBByteSize = (BYTE) ValueToNum(p);
DCBProcessingRequired = TRUE ;
} else if (_stricmp(p->P_Key, SER_PARITY_KEY) == 0) {
DCBParity = (BYTE) ValueToNum(p);
DCBProcessingRequired = TRUE ;
} else if (_stricmp(p->P_Key, SER_STOPBITS_KEY) == 0) {
DCBStopBits = (BYTE) ValueToNum(p);
DCBProcessingRequired = TRUE ;
}
//
// The fact we use ISDN_PHONENUMBER_KEY is not a bug. This is just a define.
//
else if (_stricmp(p->P_Key, ISDN_PHONENUMBER_KEY) == 0)
index = ADDRESS_INDEX ;
else if (_stricmp(p->P_Key, CONNECTBPS_KEY) == 0)
index = CONNECTBPS_INDEX ;
else
return(ERROR_WRONG_INFO_SPECIFIED);
if (index != 0xfefefefe) {
strncpy (hIOPort->TPCB_Info[index], p->P_Value.String.Data, p->P_Value.String.Length);
hIOPort->TPCB_Info[index][p->P_Value.String.Length] = '\0' ;
}
}
//
// For parameters that should be set right away - check that the port handle is still valid
// if so set the parameters.
//
if (DCBProcessingRequired && hIOPort->TPCB_CommHandle != INVALID_HANDLE_VALUE) {
//
// Get a Device Control Block with current port values
//
if (!GetCommState(hIOPort->TPCB_CommHandle, &DCB))
return(GetLastError());
if (DCBByteSize != INITIALIZED_VALUE)
DCB.ByteSize = DCBByteSize ;
if (DCBParity != INITIALIZED_VALUE)
DCB.Parity = DCBParity ;
if (DCBStopBits != INITIALIZED_VALUE)
DCB.StopBits = DCBStopBits ;
//
// Send DCB to Port
//
if (!SetCommState(hIOPort->TPCB_CommHandle, &DCB))
return(GetLastError());
}
return SUCCESS ;
}
//* FillInIsdnParams()
//
//
//
//*
DWORD
FillInIsdnParams (TapiPortControlBlock *hIOPort, RASMAN_PORTINFO *pInfo)
{
RAS_PARAMS *p;
WORD i;
DWORD index ;
DBGPRINT(("CDMODEM: FillInIsdnParams: ISDN not supported\n"));
ASSERT(FALSE);
return SUCCESS ;
}
//*
//
//
//
//*
DWORD
FillInX25Params (TapiPortControlBlock *hIOPort, RASMAN_PORTINFO *pInfo)
{
RAS_PARAMS *p;
WORD i;
DWORD index ;
#ifndef CITRIX
for (i=0, p=pInfo->PI_Params; i<pInfo->PI_NumOfParams; i++, p++) {
if (_stricmp(p->P_Key, MXS_DIAGNOSTICS_KEY) == 0)
index = X25_DIAGNOSTICS_INDEX ;
else if (_stricmp(p->P_Key, MXS_USERDATA_KEY) == 0)
index = X25_USERDATA_INDEX ;
else if (_stricmp(p->P_Key, MXS_FACILITIES_KEY) == 0)
index = X25_FACILITIES_INDEX;
else if (_stricmp(p->P_Key, MXS_X25ADDRESS_KEY) == 0)
index = ADDRESS_INDEX ;
else if (_stricmp(p->P_Key, CONNECTBPS_KEY) == 0)
index = X25_CONNECTBPS_INDEX ;
else
return(ERROR_WRONG_INFO_SPECIFIED);
strncpy (hIOPort->TPCB_Info[index], p->P_Value.String.Data, p->P_Value.String.Length);
hIOPort->TPCB_Info[index][p->P_Value.String.Length] = '\0' ;
}
strcpy (hIOPort->TPCB_Info[X25_CONNECTBPS_INDEX], "9600") ; // initialize connectbps to a
// reasonable default
#else // CITRIX
DBGPRINT(("CDMODEM: FillInX25Params: X25 not supported\n"));
ASSERT(FALSE);
#endif // CITRIX
return SUCCESS ;
}
//*
//
//
//
//*
DWORD
FillInGenericParams (TapiPortControlBlock *hIOPort, RASMAN_PORTINFO *pInfo)
{
RAS_PARAMS *p;
WORD i;
DWORD index ;
for (i=0, p=pInfo->PI_Params; i<pInfo->PI_NumOfParams; i++, p++) {
if (_stricmp(p->P_Key, ISDN_PHONENUMBER_KEY) == 0)
index = ADDRESS_INDEX ;
else if (_stricmp(p->P_Key, CONNECTBPS_KEY) == 0)
index = CONNECTBPS_INDEX ;
else
return(ERROR_WRONG_INFO_SPECIFIED);
strncpy (hIOPort->TPCB_Info[index], p->P_Value.String.Data, p->P_Value.String.Length);
hIOPort->TPCB_Info[index][p->P_Value.String.Length] = '\0' ;
}
return SUCCESS ;
}
//*
//
//
//
//*
DWORD
GetGenericParams (TapiPortControlBlock *hIOPort, RASMAN_PORTINFO *pBuffer , PWORD pwSize)
{
RAS_PARAMS *pParam;
CHAR *pValue;
WORD wAvailable ;
DWORD dwStructSize = sizeof(RASMAN_PORTINFO) + sizeof(RAS_PARAMS) * 2;
wAvailable = *pwSize;
*pwSize = (WORD) (dwStructSize + strlen (hIOPort->TPCB_Info[ADDRESS_INDEX])
+ strlen (hIOPort->TPCB_Info[CONNECTBPS_INDEX])
+ 1L) ;
if (*pwSize > wAvailable)
return(ERROR_BUFFER_TOO_SMALL);
// Fill in Buffer
((RASMAN_PORTINFO *)pBuffer)->PI_NumOfParams = 2;
pParam = ((RASMAN_PORTINFO *)pBuffer)->PI_Params;
pValue = (CHAR*)pBuffer + dwStructSize;
strcpy(pParam->P_Key, MXS_PHONENUMBER_KEY);
pParam->P_Type = String;
pParam->P_Attributes = 0;
pParam->P_Value.String.Length = strlen (hIOPort->TPCB_Info[ADDRESS_INDEX]);
pParam->P_Value.String.Data = pValue;
strcpy(pParam->P_Value.String.Data, hIOPort->TPCB_Info[ADDRESS_INDEX]);
pParam++;
strcpy(pParam->P_Key, CONNECTBPS_KEY);
pParam->P_Type = String;
pParam->P_Attributes = 0;
pParam->P_Value.String.Length = strlen (hIOPort->TPCB_Info[ISDN_CONNECTBPS_INDEX]);
pParam->P_Value.String.Data = pValue;
strcpy(pParam->P_Value.String.Data, hIOPort->TPCB_Info[ISDN_CONNECTBPS_INDEX]);
return(SUCCESS);
}
//*
//
//
//
//*
DWORD
GetIsdnParams (TapiPortControlBlock *hIOPort, RASMAN_PORTINFO *pBuffer , PWORD pwSize)
{
RAS_PARAMS *pParam;
CHAR *pValue;
WORD wAvailable ;
DWORD dwStructSize = sizeof(RASMAN_PORTINFO) + sizeof(RAS_PARAMS) * 5;
#ifndef CITRIX
wAvailable = *pwSize;
*pwSize = (WORD) (dwStructSize + strlen (hIOPort->TPCB_Info[ADDRESS_INDEX])
+ strlen (hIOPort->TPCB_Info[ISDN_LINETYPE_INDEX])
+ strlen (hIOPort->TPCB_Info[ISDN_FALLBACK_INDEX])
+ strlen (hIOPort->TPCB_Info[ISDN_COMPRESSION_INDEX])
+ strlen (hIOPort->TPCB_Info[ISDN_CHANNEL_AGG_INDEX])
+ strlen (hIOPort->TPCB_Info[ISDN_CONNECTBPS_INDEX])
+ 1L) ;
if (*pwSize > wAvailable)
return(ERROR_BUFFER_TOO_SMALL);
// Fill in Buffer
((RASMAN_PORTINFO *)pBuffer)->PI_NumOfParams = 6;
pParam = ((RASMAN_PORTINFO *)pBuffer)->PI_Params;
pValue = (CHAR*)pBuffer + dwStructSize;
strcpy(pParam->P_Key, ISDN_PHONENUMBER_KEY);
pParam->P_Type = String;
pParam->P_Attributes = 0;
pParam->P_Value.String.Length = strlen (hIOPort->TPCB_Info[ADDRESS_INDEX]);
pParam->P_Value.String.Data = pValue;
strcpy(pParam->P_Value.String.Data, hIOPort->TPCB_Info[ADDRESS_INDEX]);
pValue += pParam->P_Value.String.Length + 1;
pParam++;
strcpy(pParam->P_Key, ISDN_LINETYPE_KEY);
pParam->P_Type = String;
pParam->P_Attributes = 0;
pParam->P_Value.String.Length = strlen (hIOPort->TPCB_Info[ISDN_LINETYPE_INDEX]);
pParam->P_Value.String.Data = pValue;
strcpy(pParam->P_Value.String.Data, hIOPort->TPCB_Info[ISDN_LINETYPE_INDEX]);
pValue += pParam->P_Value.String.Length + 1;
pParam++;
strcpy(pParam->P_Key, ISDN_FALLBACK_KEY);
pParam->P_Type = String;
pParam->P_Attributes = 0;
pParam->P_Value.String.Length = strlen (hIOPort->TPCB_Info[ISDN_FALLBACK_INDEX]);
pParam->P_Value.String.Data = pValue;
strcpy(pParam->P_Value.String.Data, hIOPort->TPCB_Info[ISDN_FALLBACK_INDEX]);
pValue += pParam->P_Value.String.Length + 1;
pParam++;
strcpy(pParam->P_Key, ISDN_COMPRESSION_KEY);
pParam->P_Type = String;
pParam->P_Attributes = 0;
pParam->P_Value.String.Length = strlen (hIOPort->TPCB_Info[ISDN_COMPRESSION_INDEX]);
pParam->P_Value.String.Data = pValue;
strcpy(pParam->P_Value.String.Data, hIOPort->TPCB_Info[ISDN_COMPRESSION_INDEX]);
pValue += pParam->P_Value.String.Length + 1;
pParam++;
strcpy(pParam->P_Key, ISDN_CHANNEL_AGG_KEY);
pParam->P_Type = String;
pParam->P_Attributes = 0;
pParam->P_Value.String.Length = strlen (hIOPort->TPCB_Info[ISDN_CHANNEL_AGG_INDEX]);
pParam->P_Value.String.Data = pValue;
strcpy(pParam->P_Value.String.Data, hIOPort->TPCB_Info[ISDN_CHANNEL_AGG_INDEX]);
pValue += pParam->P_Value.String.Length + 1;
pParam++;
strcpy(pParam->P_Key, CONNECTBPS_KEY);
pParam->P_Type = String;
pParam->P_Attributes = 0;
pParam->P_Value.String.Length = strlen (hIOPort->TPCB_Info[ISDN_CONNECTBPS_INDEX]);
pParam->P_Value.String.Data = pValue;
strcpy(pParam->P_Value.String.Data, hIOPort->TPCB_Info[ISDN_CONNECTBPS_INDEX]);
#else // CITRIX
DBGPRINT(("CDMODEM: GetIsdnParams: ISDN not supported\n"));
ASSERT(FALSE);
#endif // CITRIX
return(SUCCESS);
}
//*
//
//
//
//*
DWORD
GetX25Params (TapiPortControlBlock *hIOPort, RASMAN_PORTINFO *pBuffer ,PWORD pwSize)
{
RAS_PARAMS *pParam;
CHAR *pValue;
WORD wAvailable ;
DWORD dwStructSize = sizeof(RASMAN_PORTINFO) + sizeof(RAS_PARAMS) * 4 ;
#ifndef CITRIX
wAvailable = *pwSize;
*pwSize = (WORD) (dwStructSize + strlen (hIOPort->TPCB_Info[ADDRESS_INDEX])
+ strlen (hIOPort->TPCB_Info[X25_DIAGNOSTICS_INDEX])
+ strlen (hIOPort->TPCB_Info[X25_USERDATA_INDEX])
+ strlen (hIOPort->TPCB_Info[X25_FACILITIES_INDEX])
+ strlen (hIOPort->TPCB_Info[X25_CONNECTBPS_INDEX])
+ 1L) ;
if (*pwSize > wAvailable)
return(ERROR_BUFFER_TOO_SMALL);
// Fill in Buffer
((RASMAN_PORTINFO *)pBuffer)->PI_NumOfParams = 5 ;
pParam = ((RASMAN_PORTINFO *)pBuffer)->PI_Params;
pValue = (CHAR*)pBuffer + dwStructSize;
strcpy(pParam->P_Key, MXS_X25ADDRESS_KEY);
pParam->P_Type = String;
pParam->P_Attributes = 0;
pParam->P_Value.String.Length = strlen (hIOPort->TPCB_Info[ADDRESS_INDEX]);
pParam->P_Value.String.Data = pValue;
strcpy(pParam->P_Value.String.Data, hIOPort->TPCB_Info[ADDRESS_INDEX]);
pValue += pParam->P_Value.String.Length + 1;
pParam++;
strcpy(pParam->P_Key, MXS_DIAGNOSTICS_KEY);
pParam->P_Type = String;
pParam->P_Attributes = 0;
pParam->P_Value.String.Length = strlen (hIOPort->TPCB_Info[X25_DIAGNOSTICS_INDEX]);
pParam->P_Value.String.Data = pValue;
strcpy(pParam->P_Value.String.Data, hIOPort->TPCB_Info[X25_DIAGNOSTICS_INDEX]);
pValue += pParam->P_Value.String.Length + 1;
pParam++;
strcpy(pParam->P_Key, MXS_USERDATA_KEY);
pParam->P_Type = String;
pParam->P_Attributes = 0;
pParam->P_Value.String.Length = strlen (hIOPort->TPCB_Info[X25_USERDATA_INDEX]);
pParam->P_Value.String.Data = pValue;
strcpy(pParam->P_Value.String.Data, hIOPort->TPCB_Info[X25_USERDATA_INDEX]);
pValue += pParam->P_Value.String.Length + 1;
pParam++;
strcpy(pParam->P_Key, MXS_FACILITIES_KEY);
pParam->P_Type = String;
pParam->P_Attributes = 0;
pParam->P_Value.String.Length = strlen (hIOPort->TPCB_Info[X25_FACILITIES_INDEX]);
pParam->P_Value.String.Data = pValue;
strcpy(pParam->P_Value.String.Data, hIOPort->TPCB_Info[X25_FACILITIES_INDEX]);
pValue += pParam->P_Value.String.Length + 1;
pParam++;
strcpy(pParam->P_Key, CONNECTBPS_KEY);
pParam->P_Type = String;
pParam->P_Attributes = 0;
pParam->P_Value.String.Length = strlen (hIOPort->TPCB_Info[X25_CONNECTBPS_INDEX]);
pParam->P_Value.String.Data = pValue;
strcpy(pParam->P_Value.String.Data, hIOPort->TPCB_Info[X25_CONNECTBPS_INDEX]);
#else // CITRIX
DBGPRINT(("CDMODEM: GetX25Params: X25 not supported\n"));
ASSERT(FALSE);
#endif // CITRIX
return(SUCCESS);
}
//* GetMutex
//
//
//
//*
VOID
GetMutex (HANDLE mutex, DWORD to)
{
if (WaitForSingleObject (mutex, to) == WAIT_FAILED) {
GetLastError() ;
DbgBreakPoint() ;
}
}
//* FreeMutex
//
//
//
//*
VOID
FreeMutex (HANDLE mutex)
{
if (!ReleaseMutex(mutex)) {
GetLastError () ;
DbgBreakPoint() ;
}
}
//* InitiatePortDisconnection()
//
// Function: Starts the disconnect process. Note even though this covers SYNC completion of lineDrop this
// is not per TAPI spec.
//
// Returns:
//*
DWORD
InitiatePortDisconnection (TapiPortControlBlock *hIOPort)
{
DWORD retcode ;
hIOPort->TPCB_RequestId = INFINITE ; // mark requestid as unused
// For asyncmac/unimodem give a close indication to asyncmac if the endpoint is still valid
//
if (_stricmp (hIOPort->TPCB_DeviceType, DEVICETYPE_UNIMODEM) == 0) {
// tell asyncmac to close the link
//
if (hIOPort->TPCB_Endpoint != 0xffffffff) {
ASYMAC_CLOSE AsyMacClose;
OVERLAPPED overlapped ;
DWORD dwBytesReturned ;
memset (&overlapped, 0, sizeof(OVERLAPPED)) ;
AsyMacClose.MacAdapter = NULL;
AsyMacClose.hNdisEndpoint = LongToHandle(hIOPort->TPCB_Endpoint) ;
DeviceIoControl(ghAsyMac,
IOCTL_ASYMAC_CLOSE,
&AsyMacClose,
sizeof(AsyMacClose),
&AsyMacClose,
sizeof(AsyMacClose),
&dwBytesReturned,
&overlapped);
hIOPort->TPCB_Endpoint = 0xffffffff ;
}
// Close the handle given by lineGetId on unimodem ports
//
if (hIOPort->TPCB_CommHandle != INVALID_HANDLE_VALUE) {
DBGPRINT(( "InitiatePortDisconnection: Closing handle 0x%x",
hIOPort->TPCB_CommHandle ));
CloseHandle (hIOPort->TPCB_CommHandle) ;
hIOPort->TPCB_CommHandle = INVALID_HANDLE_VALUE ;
}
}
// Handle the case where lineMakeCall is not yet complete and the callhandle is invalid
//
if (hIOPort->TPCB_CallHandle == (HCALL) INFINITE) {
lineClose (hIOPort->TPCB_Line->TLI_LineHandle) ;
Sleep (30L) ; // arbitrary sleep time to allow cleanup in lower layers
retcode = lineOpen (RasLine,
hIOPort->TPCB_Line->TLI_LineId,
&hIOPort->TPCB_Line->TLI_LineHandle,
hIOPort->TPCB_Line->NegotiatedApiVersion,
hIOPort->TPCB_Line->NegotiatedExtVersion,
(ULONG) (ULONG_PTR) hIOPort->TPCB_Line,
LINECALLPRIVILEGE_OWNER,
hIOPort->TPCB_MediaMode,
NULL) ;
if (retcode)
DbgPrint ("InitiateDisconnection: lineOpen failed with %d\n", retcode) ;
//
// Set monitoring of rings
//
lineSetStatusMessages (hIOPort->TPCB_Line->TLI_LineHandle, LINEDEVSTATE_RINGING, 0) ;
return SUCCESS ;
}
// Initiate disconnection.
//
if ((hIOPort->TPCB_RequestId = lineDrop (hIOPort->TPCB_CallHandle, NULL, 0)) > 0x80000000 ) {
//
// Error issuing the linedrop. Should we try to deallocate anyway?
//
hIOPort->TPCB_State = PS_OPEN ;
hIOPort->TPCB_RequestId = INFINITE ;
lineDeallocateCall (hIOPort->TPCB_CallHandle) ;
// DbgPrint ("D\n") ;
return ERROR_DISCONNECTION ; // generic disconnect message
} else if (hIOPort->TPCB_RequestId) {
//
// The linedrop is completeing async
//
hIOPort->TPCB_State = PS_DISCONNECTING ;
// DbgPrint ("InitiatePortDisconnection: ReqId:%d\n", hIOPort->TPCB_RequestId) ;
return PENDING ;
} else { // SUCCESS
//
// The linedrop completed sync
//
hIOPort->TPCB_RequestId = INFINITE ;
if (hIOPort->TPCB_Line->IdleReceived) {
hIOPort->TPCB_Line->IdleReceived = FALSE;
hIOPort->TPCB_State = PS_OPEN ;
lineDeallocateCall (hIOPort->TPCB_CallHandle) ;
// DbgPrint ("D\n") ;
hIOPort->TPCB_CallHandle = (HCALL) 0xffffffff ;
return SUCCESS ;
} else {
//
// Wait for IdleReceived
//
hIOPort->TPCB_State = PS_DISCONNECTING ;
return PENDING ;
}
}
}
// LookUpControlBlock()
//
// Function: This function uses the given handle to find which TPCB is it refering to. This handle can be
// either a pointer to TPCB itself (in case of non unimodem devices) or it is the CommHandle
// for the unimodem port.
//
// Consider: Adding a cache for lookup speeding.
//
// Returns: Nothing.
//
TapiPortControlBlock *
LookUpControlBlock (HANDLE hPort)
{
DWORD i ;
TapiPortControlBlock *pports ;
// hPort is the TPCB pointer
//
if (((TapiPortControlBlock *)hPort >= RasPorts) &&
((TapiPortControlBlock *)hPort < RasPortsEnd) &&
(((TapiPortControlBlock *)hPort)->TPCB_Signature == CONTROLBLOCKSIGNATURE))
return (TapiPortControlBlock *)hPort ;
// hPort is not the TPCB pointer - see if this matches any of the CommHandles
//
for (pports = RasPorts, i=0; i < TotalPorts; i++, pports++) {
if (pports->TPCB_CommHandle == hPort)
return pports ;
}
return NULL ;
}
//* ValueToNum -------------------------------------------------------------
//
// Function: Converts a RAS_PARAMS P_Value, which may be either a DWORD or
// a string, to a DWORD.
//
// Returns: The numeric value of the input as a DWORD.
//
//*
DWORD
ValueToNum(RAS_PARAMS *p)
{
CHAR szStr[RAS_MAXLINEBUFLEN];
if (p->P_Type == String) {
strncpy(szStr, p->P_Value.String.Data, p->P_Value.String.Length);
szStr[p->P_Value.String.Length] = '\0';
return(atol(szStr));
} else
return(p->P_Value.Number);
}