2011 lines
47 KiB
C
2011 lines
47 KiB
C
//****************************************************************************
|
|
// *
|
|
// Microsoft NT Remote Access Service
|
|
//
|
|
// Copyright (C) 1992-93 Microsft Corporation. All rights reserved.
|
|
//
|
|
// Filename: mxsutils.c
|
|
//
|
|
// Revision History
|
|
//
|
|
// Jun 10, 1992 J. Perry Hannah Created
|
|
//
|
|
//
|
|
// Description: This file contains utility functions used by RASMXS.DLL.
|
|
//
|
|
//****************************************************************************
|
|
|
|
#include <nt.h> //These first five headers are used by media.h
|
|
#include <ntrtl.h> //The first three(?) are used by DbgUserBreakPoint
|
|
#include <nturtl.h>
|
|
#include <windows.h>
|
|
#include <wanpub.h>
|
|
#include <asyncpub.h>
|
|
|
|
#include <string.h>
|
|
#include <malloc.h>
|
|
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
|
|
|
|
#include <rasman.h>
|
|
#include <raserror.h>
|
|
#include <rasfile.h>
|
|
#include <media.h>
|
|
#include <serial.h>
|
|
#include <mprlog.h>
|
|
#include <rtutils.h>
|
|
|
|
#include <rasmxs.h>
|
|
#include <mxsint.h>
|
|
#include <mxspriv.h>
|
|
#include "mxswrap.h" // inf file wrapper
|
|
|
|
|
|
|
|
//* Global Variables *******************************************************
|
|
//
|
|
extern RESPSECTION ResponseSection ; //Shared response section
|
|
extern DEVICE_CB *pDeviceList; //Points to DCB linked list
|
|
extern HANDLE *pDeviceListMutex ; //Mutex for above list
|
|
|
|
extern PortGetInfo_t PortGetInfo; //API typedef defined in media.h
|
|
extern PortSetInfo_t PortSetInfo; //API typedef defined in media.h
|
|
|
|
extern BOOL gbLogDeviceDialog; //Indicates logging is on if TRUE
|
|
extern HANDLE ghLogFile; //Handle of device log file
|
|
extern SavedSections *gpSavedSections ; // Pointer to cached sections
|
|
|
|
#define NUM_INTERNAL_MACROS 21
|
|
|
|
TCHAR *gszInternalMacroNames[] =
|
|
{
|
|
MXS_CARRIERBPS_KEY,
|
|
MXS_CONNECTBPS_KEY,
|
|
MXS_MESSAGE_KEY,
|
|
MXS_PHONENUMBER_KEY,
|
|
|
|
MXS_DIAGNOSTICS_KEY,
|
|
MXS_FACILITIES_KEY,
|
|
MXS_USERDATA_KEY,
|
|
MXS_X25PAD_KEY,
|
|
MXS_X25ADDRESS_KEY,
|
|
|
|
MXS_COMPRESSION_OFF_KEY,
|
|
MXS_COMPRESSION_ON_KEY,
|
|
MXS_HDWFLOWCONTROL_OFF_KEY,
|
|
MXS_HDWFLOWCONTROL_ON_KEY,
|
|
MXS_PROTOCOL_OFF_KEY,
|
|
MXS_PROTOCOL_ON_KEY,
|
|
MXS_SPEAKER_OFF_KEY,
|
|
MXS_SPEAKER_ON_KEY,
|
|
MXS_AUTODIAL_OFF_KEY,
|
|
MXS_AUTODIAL_ON_KEY,
|
|
MXS_USERNAME_KEY,
|
|
MXS_PASSWORD_KEY,
|
|
};
|
|
|
|
|
|
|
|
|
|
//* Utility Functions ******************************************************
|
|
//
|
|
|
|
|
|
//* GetDeviceCB ------------------------------------------------------------
|
|
//
|
|
// Function: Looks for a Device Control Block in the global Device linked
|
|
// list. If no DCB is found that contains an hIOPort matching
|
|
// the input parameter, one is created, initalized, and added
|
|
// to the list.
|
|
//
|
|
// Returns: Pointer to the DEVICE_CB which contains an hIOPort matching the
|
|
// the second input parameter.
|
|
//*
|
|
|
|
DWORD
|
|
GetDeviceCB(HANDLE hIOPort,
|
|
char *pszDeviceType,
|
|
char *pszDeviceName,
|
|
DEVICE_CB **ppDev)
|
|
{
|
|
DWORD dRC = SUCCESS ;
|
|
|
|
*ppDev = FindDeviceInList(pDeviceList, hIOPort, pszDeviceType, pszDeviceName);
|
|
|
|
|
|
if (*ppDev == NULL)
|
|
{
|
|
dRC = AddDeviceToList(&pDeviceList,
|
|
hIOPort,
|
|
pszDeviceType,
|
|
pszDeviceName,
|
|
ppDev);
|
|
|
|
if (dRC != SUCCESS)
|
|
goto getdcbend ;
|
|
|
|
dRC = CreateInfoTable(*ppDev);
|
|
if (dRC != SUCCESS)
|
|
goto getdcbend ;
|
|
|
|
|
|
dRC = CreateAttributes(*ppDev) ;
|
|
|
|
}
|
|
|
|
getdcbend:
|
|
|
|
return (dRC);
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//* FindDeviceInList -------------------------------------------------------
|
|
//
|
|
// Function: Finds the Device Control Block in the global Device linked
|
|
// list which contains the hIOPort handle, device type, and
|
|
// device name.
|
|
//
|
|
// Returns: Pointer to the DEVICE_CB which contains matches for the second,
|
|
// third, and fourth parameters, or NULL if no such DEVICE_CB
|
|
// is found.
|
|
//*
|
|
|
|
DEVICE_CB*
|
|
FindDeviceInList(DEVICE_CB *pDev,
|
|
HANDLE hIOPort,
|
|
TCHAR *pszDeviceType,
|
|
TCHAR *pszDeviceName)
|
|
{
|
|
while (pDev != NULL)
|
|
{
|
|
pDev = FindPortInList(pDev, hIOPort, NULL);
|
|
if (pDev == NULL)
|
|
break;
|
|
|
|
if (_stricmp(pDev->szDeviceType, pszDeviceType) == 0 &&
|
|
_stricmp(pDev->szDeviceName, pszDeviceName) == 0)
|
|
break;
|
|
|
|
pDev = pDev->pNextDeviceCB;
|
|
}
|
|
|
|
return(pDev);
|
|
}
|
|
|
|
|
|
|
|
|
|
//* FindPortInList ---------------------------------------------------------
|
|
//
|
|
// Function: Finds the first Device Control Block in the global Device linked
|
|
// list which contains the hIOPort handle.
|
|
//
|
|
// If pPrevDev is not NULL on input, then on output it *pPrevDev
|
|
// points to the DCB just prior to the "found" DCB pointed to by
|
|
// the returned pointer. If the function return value is not NULL
|
|
// *pPrevDev will be valid.
|
|
//
|
|
// NOTE: If the found DCB is at the head of the list, pPrevDev
|
|
// will be the same as the return value.
|
|
//
|
|
// Returns: Pointer to the DEVICE_CB which contains an hIOPort matching the
|
|
// the second input parameter, or NULL if no such DEVICE_CB is found.
|
|
//*
|
|
|
|
DEVICE_CB*
|
|
FindPortInList(DEVICE_CB *pDeviceList, HANDLE hIOPort, DEVICE_CB **pPrevDev)
|
|
{
|
|
DEVICE_CB *pDev;
|
|
|
|
|
|
pDev = pDeviceList; //Allow for case of only one DCB on list
|
|
|
|
while(pDeviceList != NULL && pDeviceList->hPort != hIOPort)
|
|
{
|
|
pDev = pDeviceList;
|
|
pDeviceList = pDeviceList->pNextDeviceCB;
|
|
}
|
|
|
|
if (pPrevDev != NULL)
|
|
*pPrevDev = pDev;
|
|
|
|
return(pDeviceList);
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//* AddDeviceToList --------------------------------------------------------
|
|
//
|
|
// Function: Creates a Device Control Block and adds it to the head of the
|
|
// global Device linked list.
|
|
//
|
|
// Returns: SUCCESS
|
|
// ERROR_UNKNOWN_DEVICE_TYPE
|
|
// ERROR_ALLOCATING_MEMORY
|
|
//*
|
|
|
|
DWORD
|
|
AddDeviceToList(DEVICE_CB **ppDeviceList,
|
|
HANDLE hIOPort,
|
|
LPTSTR lpszDeviceType,
|
|
LPTSTR lpszDeviceName,
|
|
DEVICE_CB **ppDevice)
|
|
{
|
|
DEVICE_CB *pDev;
|
|
DEVICETYPE eDeviceType;
|
|
DWORD dRC;
|
|
TCHAR szFileName[MAX_PATH];
|
|
DEVICE_CB *origpDeviceList ;
|
|
|
|
origpDeviceList = *ppDeviceList ; // save this pointer since it may be restored later
|
|
|
|
// Check input
|
|
|
|
eDeviceType = DeviceTypeStrToEnum(lpszDeviceType);
|
|
if (eDeviceType == DT_UNKNOWN)
|
|
return(ERROR_UNKNOWN_DEVICE_TYPE);
|
|
|
|
|
|
// INF file sections are opened before the DCB is created because the
|
|
// open/close count must be kept balanced even when errors occur. (If
|
|
// OpenResponseSection fails it does not increment the count, and because
|
|
// the DCB does not exist DeviceWork does not decrement the count.)
|
|
|
|
|
|
// Open global response section for modems
|
|
*szFileName = TEXT('\0');
|
|
GetInfFileName(lpszDeviceType, szFileName, sizeof(szFileName));
|
|
if (eDeviceType == DT_MODEM) {
|
|
dRC = OpenResponseSection (szFileName) ;
|
|
if (dRC != SUCCESS)
|
|
return dRC ;
|
|
}
|
|
|
|
|
|
// Put new DCB at head of list
|
|
|
|
pDev = *ppDeviceList;
|
|
|
|
GetMem(sizeof(DEVICE_CB), (BYTE **)ppDeviceList);
|
|
if (*ppDeviceList == NULL)
|
|
return(ERROR_ALLOCATING_MEMORY);
|
|
|
|
*ppDevice = *ppDeviceList;
|
|
(*ppDevice)->pNextDeviceCB = pDev;
|
|
|
|
|
|
// Initialize New Device Control Block
|
|
|
|
pDev = *ppDevice;
|
|
pDev->hPort = hIOPort;
|
|
strcpy(pDev->szDeviceName, lpszDeviceName);
|
|
strcpy(pDev->szDeviceType, lpszDeviceType);
|
|
pDev->eDeviceType = eDeviceType;
|
|
pDev->pInfoTable = NULL;
|
|
pDev->pMacros = NULL;
|
|
pDev->hInfFile = INVALID_HRASFILE;
|
|
pDev->fPartialResponse = FALSE;
|
|
pDev->bErrorControlOn = FALSE;
|
|
|
|
pDev->Overlapped.RO_Overlapped.Internal = 0;
|
|
pDev->Overlapped.RO_Overlapped.InternalHigh = 0;
|
|
pDev->Overlapped.RO_Overlapped.Offset = 0;
|
|
pDev->Overlapped.RO_Overlapped.OffsetHigh = 0;
|
|
pDev->Overlapped.RO_Overlapped.hEvent = NULL;
|
|
pDev->Overlapped.RO_EventType = OVEVT_DEV_ASYNCOP;
|
|
|
|
pDev->dwRetries = 1;
|
|
|
|
|
|
// Initialize State variables
|
|
|
|
pDev->eDevNextAction = SEND; // DeviceStateMachine() State
|
|
pDev->eCmdType = CT_GENERIC; // Used by DeviceStateMachine()
|
|
pDev->eNextCmdType = CT_GENERIC; // Used by DeviceStateMachine()
|
|
pDev->fEndOfSection = FALSE; // Used by DeviceStateMachine()
|
|
|
|
pDev->eRcvState = GETECHO; // ReceiveStateMachine() State
|
|
|
|
|
|
// Open device section of INF file
|
|
if (FindOpenDevSection (szFileName, lpszDeviceName, &(pDev->hInfFile)) == TRUE)
|
|
return SUCCESS ;
|
|
|
|
dRC = RasDevOpen(szFileName, lpszDeviceName, &(pDev->hInfFile));
|
|
if (dRC != SUCCESS) {
|
|
|
|
// restore the pointers
|
|
//
|
|
*ppDeviceList = origpDeviceList ;
|
|
*ppDevice = NULL ;
|
|
free (pDev) ;
|
|
return(dRC);
|
|
|
|
} else
|
|
AddOpenDevSection (szFileName, lpszDeviceName, pDev->hInfFile) ; // Add to the opened list
|
|
|
|
return(SUCCESS);
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//* CreateInfoTable --------------------------------------------------------
|
|
//
|
|
// Function: Creates an InfoTable and initalizes it by reading the variables
|
|
// and macros found in the INF file into it. The InfoTable is
|
|
// attached to the Device Control Block pointed to by the input
|
|
// parameter.
|
|
//
|
|
// This function allocates memory.
|
|
//
|
|
// Returns: SUCCESS
|
|
// ERROR_ALLOCATING_MEMORY
|
|
// Return value from RasDevOpen() or RasDevGetParams().
|
|
//*
|
|
|
|
DWORD
|
|
CreateInfoTable(DEVICE_CB *pDevice)
|
|
{
|
|
DWORD dRC, dSize = 0;
|
|
RASMAN_DEVICEINFO *pInfoTable = NULL ;
|
|
|
|
|
|
// Read variables and macros into InfoTable from INF file
|
|
|
|
dRC = RasDevGetParams(pDevice->hInfFile, (BYTE *)(pInfoTable), &dSize);
|
|
if (dRC == ERROR_BUFFER_TOO_SMALL)
|
|
{
|
|
dSize += sizeof(RAS_PARAMS) * NUM_INTERNAL_MACROS;
|
|
|
|
GetMem(dSize, (BYTE **)&pInfoTable);
|
|
if (pInfoTable == NULL)
|
|
return(ERROR_ALLOCATING_MEMORY);
|
|
|
|
dRC = RasDevGetParams(pDevice->hInfFile, (BYTE *)(pInfoTable), &dSize);
|
|
}
|
|
if (dRC != SUCCESS)
|
|
{
|
|
free(pInfoTable);
|
|
return(dRC);
|
|
}
|
|
|
|
|
|
if ((dRC = AddInternalMacros(pDevice, pInfoTable)) != SUCCESS)
|
|
{
|
|
free(pInfoTable);
|
|
return(dRC);
|
|
}
|
|
|
|
|
|
// Attach InfoTable to Device Control Block
|
|
|
|
pDevice->pInfoTable = pInfoTable;
|
|
|
|
return(SUCCESS);
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//* AddInternalMacros ------------------------------------------------------
|
|
//
|
|
// Function: Adds internal macros to existing InfoTable.
|
|
//
|
|
// Asumptions: The InfoTable buffer was created with room enough for
|
|
// the internal macros.
|
|
//
|
|
// Returns: SUCCESS
|
|
// ERROR_ALLOCATING_MEMORY
|
|
//*
|
|
|
|
DWORD
|
|
AddInternalMacros(DEVICE_CB *pDev, RASMAN_DEVICEINFO *pDI)
|
|
{
|
|
WORD i;
|
|
RAS_PARAMS *pParam;
|
|
|
|
|
|
// Get pointer to next unused param
|
|
|
|
pParam = &(pDI->DI_Params[pDI->DI_NumOfParams]);
|
|
|
|
|
|
// Fill in params for internal macros
|
|
|
|
for (i=0; i<NUM_INTERNAL_MACROS; i++)
|
|
{
|
|
strcpy(pParam->P_Key, gszInternalMacroNames[i]);
|
|
|
|
pParam->P_Type = String;
|
|
pParam->P_Attributes = 0;
|
|
pParam->P_Value.String.Length = 0;
|
|
|
|
GetMem(1, &(pParam->P_Value.String.Data));
|
|
if (pParam->P_Value.String.Data == NULL)
|
|
return(ERROR_ALLOCATING_MEMORY);
|
|
|
|
*(pParam->P_Value.String.Data) = '\0';
|
|
|
|
pParam++;
|
|
}
|
|
|
|
pDI->DI_NumOfParams += NUM_INTERNAL_MACROS;
|
|
|
|
return(SUCCESS);
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//* CreateAttributes -------------------------------------------------------
|
|
//
|
|
// Function: This function is used to set attributes for the first time
|
|
// when the InfoTable is created. UpdateInfoTable() is used
|
|
// to later change attributes.
|
|
//
|
|
// First, all attributes are set according to the parameter
|
|
// key with all binary macros being enabled. Then the
|
|
// DEFAULTOFF variable is parsed, and macros listed there are
|
|
// disabled.
|
|
//
|
|
// Assumptions: - The ATTRIB_VARIABLE attribute bit has already been set
|
|
// by RasDevGetParams().
|
|
// - Parameters in InfoTable are sorted by P_Key.
|
|
// - Both parts of binary macros are present.
|
|
// These assumptions imply that if somename_off is in InfoTable
|
|
// somename_on is also present and is adjacent to somename_off.
|
|
//
|
|
// Returns: SUCCESS
|
|
// ERROR_DEFAULTOFF_MACRO_NOT_FOUND
|
|
// ERROR_ALLOCATING_MEMORY
|
|
// Return codes from PortGetInfo
|
|
//*
|
|
|
|
DWORD
|
|
CreateAttributes(DEVICE_CB *pDevice)
|
|
{
|
|
int iDefaultOff = -1;
|
|
DWORD i, dwMemSize;
|
|
DWORD dwRC;
|
|
BOOL fFound;
|
|
TCHAR *lpszDefaultOff, *lpszEOS, szCoreName[MAX_PARAM_KEY_SIZE];
|
|
RAS_PARAMS *pParam;
|
|
|
|
RASMAN_DEVICEINFO *pInfo = pDevice->pInfoTable;
|
|
RASMAN_PORTINFO *pPortInfo;
|
|
|
|
|
|
|
|
//DebugPrintf(("mxsutils CreateAttributes\n"));
|
|
|
|
// Set attributes according to Keyword type,
|
|
// defaulting user settable parameters to enabled.
|
|
|
|
for (i=0; i < pInfo->DI_NumOfParams; i++)
|
|
{
|
|
pParam = &(pInfo->DI_Params[i]);
|
|
//DebugPrintf(("%32s %s\n", pParam, pParam->P_Value.String.Data));
|
|
|
|
if (IsVariable(*pParam))
|
|
pParam->P_Attributes = ATTRIB_VARIABLE;
|
|
|
|
else if (IsBinaryMacro(pParam->P_Key))
|
|
pParam->P_Attributes = ATTRIB_BINARYMACRO |
|
|
ATTRIB_USERSETTABLE |
|
|
ATTRIB_ENABLED;
|
|
else
|
|
pParam->P_Attributes = ATTRIB_ENABLED;
|
|
|
|
|
|
// Remember location of DEFAULTOFF variable
|
|
|
|
if (_stricmp(pInfo->DI_Params[i].P_Key, MXS_DEFAULTOFF_KEY) == 0)
|
|
iDefaultOff = i;
|
|
}
|
|
|
|
|
|
// Call PortGetInfo (first loading the rasser.dll if necessary)
|
|
|
|
if (PortGetInfo == NULL)
|
|
{
|
|
if ((dwRC = LoadRasserDll(&PortGetInfo, &PortSetInfo)) != SUCCESS)
|
|
return(dwRC);
|
|
}
|
|
|
|
dwMemSize = 256;
|
|
|
|
GetMem(dwMemSize, (BYTE **)&pPortInfo);
|
|
if (pPortInfo == NULL)
|
|
return(ERROR_ALLOCATING_MEMORY);
|
|
|
|
|
|
dwRC = PortGetInfo(pDevice->hPort, NULL, (BYTE *)pPortInfo, &dwMemSize);
|
|
if (dwRC == ERROR_BUFFER_TOO_SMALL)
|
|
{
|
|
free(pPortInfo);
|
|
|
|
GetMem(dwMemSize, (BYTE **)&pPortInfo);
|
|
if (pPortInfo == NULL)
|
|
return(ERROR_ALLOCATING_MEMORY);
|
|
|
|
PortGetInfo(pDevice->hPort, NULL, (BYTE *)pPortInfo, &dwMemSize);
|
|
}
|
|
else if ( dwRC )
|
|
{
|
|
dwRC = SUCCESS;
|
|
return dwRC;
|
|
}
|
|
|
|
dwRC = SUCCESS ;
|
|
|
|
|
|
// Save the Port name in the DCB
|
|
|
|
GetPcbString(pPortInfo, SER_PORTNAME_KEY, pDevice->szPortName);
|
|
|
|
|
|
// Get the current Bps of the port.
|
|
// If the modem does not report the connect bps we will use this one.
|
|
|
|
GetPcbString(pPortInfo, SER_CONNECTBPS_KEY, pDevice->szPortBps);
|
|
|
|
|
|
// Does serial.ini file contain a DEFAULTOFF variable?
|
|
|
|
if (!GetPortDefaultOff(pPortInfo, &lpszDefaultOff))
|
|
{
|
|
// No DEFAULTOFF in port INI file
|
|
// Check that DEFAULTOFF variable was found in device Info table
|
|
|
|
if (iDefaultOff == -1) //DEFAULTOFF not found
|
|
{ //Assume none are to be disabled
|
|
free(pPortInfo);
|
|
return(SUCCESS);
|
|
}
|
|
|
|
lpszDefaultOff = pInfo->DI_Params[iDefaultOff].P_Value.String.Data;
|
|
}
|
|
|
|
|
|
// Prepare DEFALULTOFF string
|
|
|
|
InitParameterStr(lpszDefaultOff, &lpszEOS);
|
|
|
|
|
|
|
|
// Disable parameters listed in DEFAULTOFF variable.
|
|
|
|
while (lpszDefaultOff < lpszEOS)
|
|
{
|
|
fFound = FALSE;
|
|
|
|
for (i=0; i < pInfo->DI_NumOfParams; i++)
|
|
{
|
|
if (IsBinaryMacro(pInfo->DI_Params[i].P_Key))
|
|
{
|
|
GetCoreMacroName(pInfo->DI_Params[i].P_Key, szCoreName);
|
|
if (_stricmp(lpszDefaultOff, szCoreName) == 0)
|
|
{
|
|
pInfo->DI_Params[i].P_Attributes &= ~ATTRIB_ENABLED; //One suffix
|
|
pInfo->DI_Params[i+1].P_Attributes &= ~ATTRIB_ENABLED; //Other suffix
|
|
fFound = TRUE;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!fFound)
|
|
{
|
|
free(pPortInfo);
|
|
return(ERROR_DEFAULTOFF_MACRO_NOT_FOUND);
|
|
}
|
|
|
|
GetNextParameter(&lpszDefaultOff, lpszEOS);
|
|
}
|
|
|
|
free(pPortInfo);
|
|
return(SUCCESS);
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//* GetPortDefaultOff ------------------------------------------------------
|
|
//
|
|
// Function: This function finds the DEFAULTOFF key in the RASMAN_PORTINFO
|
|
// table supplied by the first parameter. A pointer to the value
|
|
// string is the output in the second parameter.
|
|
//
|
|
// If the DEFAULTOFF key is not found, the function returns FALSE,
|
|
// and the second parameter is undefined.
|
|
//
|
|
// Arguments:
|
|
// pPortInfo IN Pointer to Port Info Table from PortGetInfo()
|
|
// lpszValue OUT DEFAULTOFF value string
|
|
//
|
|
// Returns: TRUE if DEFAULTOFF key is found, otherwise FALSE
|
|
//
|
|
//*
|
|
|
|
BOOL
|
|
GetPortDefaultOff(RASMAN_PORTINFO *pPortInfo, TCHAR **lpszValue)
|
|
{
|
|
WORD i;
|
|
|
|
|
|
for (i=0; i<pPortInfo->PI_NumOfParams; i++)
|
|
|
|
if (_stricmp(SER_DEFAULTOFFSTR_KEY, pPortInfo->PI_Params[i].P_Key) == 0)
|
|
break;
|
|
|
|
if (i >= pPortInfo->PI_NumOfParams)
|
|
return(FALSE);
|
|
|
|
*lpszValue = pPortInfo->PI_Params[i].P_Value.String.Data;
|
|
return(TRUE);
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//* GetPcbString -----------------------------------------------------------
|
|
//
|
|
// Funciton: Searches a RASMAN_PORTINFO struct for a P_Key that matches
|
|
// the second parameter, pszPcbKey. The P_Value.String.Data
|
|
// is copied to the third parameter, pszDest which is the
|
|
// output parameter.
|
|
//
|
|
// Note: This function may only be called for keys that have
|
|
// P_Type String values (and never for P_Type Number values).
|
|
//
|
|
// Assumptions: The first parameter has been initalize by a call to
|
|
// PortGetInfo.
|
|
//
|
|
// Returns: nothing.
|
|
//
|
|
//*
|
|
|
|
void
|
|
GetPcbString(RASMAN_PORTINFO *pPortInfo, char *pszPcbKey, char *pszDest)
|
|
{
|
|
WORD i;
|
|
|
|
|
|
for (i=0; i<pPortInfo->PI_NumOfParams; i++)
|
|
|
|
if (_stricmp(pszPcbKey, pPortInfo->PI_Params[i].P_Key) == 0)
|
|
break;
|
|
|
|
if (i >= pPortInfo->PI_NumOfParams ||
|
|
pPortInfo->PI_Params[i].P_Type != String)
|
|
return;
|
|
|
|
strncpy(pszDest,
|
|
pPortInfo->PI_Params[i].P_Value.String.Data,
|
|
pPortInfo->PI_Params[i].P_Value.String.Length);
|
|
|
|
*(pszDest + pPortInfo->PI_Params[i].P_Value.String.Length) = '\0';
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//* UpdateInfoTable --------------------------------------------------------
|
|
//
|
|
// Function: This function is used to update attributes when DeviceSetInfo()
|
|
// is called. The nested for loops search the Info Table for each
|
|
// input param to be set.
|
|
//
|
|
// If the full macro name (including _off or _on for binary macros)
|
|
// is given in the input P_Key, the P_Value is copied and the
|
|
// Enable bit in P_Attributes is copied. If the core name
|
|
// is given for binary macros, only the Enable bit is copied.
|
|
//
|
|
// Assumptions: - Parameters in InfoTable are sorted by P_Key.
|
|
// - Both parts of binary macros are present in the InfoTable.
|
|
// These assumptions imply that if somename_off is in InfoTable
|
|
// somename_on is also present and is adjacent to somename_off.
|
|
//
|
|
// Pseudo Code: for (each input param to be set)
|
|
// for (each item in InfoTable)
|
|
// if (P_Keys match && !IsVariable)
|
|
// copy P_Value
|
|
// copy Enable Attribute bit
|
|
// else if (P_Keys binary macro core names match)
|
|
// copy Enable Attribute bit
|
|
//
|
|
// Returns: SUCCESS
|
|
// ERROR_WRONG_KEY_SPECIFIED
|
|
//
|
|
//*
|
|
|
|
DWORD
|
|
UpdateInfoTable(DEVICE_CB *pDevice, RASMAN_DEVICEINFO *pNewInfo)
|
|
{
|
|
WORD i, j;
|
|
BOOL fFound;
|
|
DWORD dwRC, dwSrcLen, dwNumber;
|
|
TCHAR *pszSrc, szNumberStr[MAX_LEN_STR_FROM_NUMBER + 1];
|
|
|
|
RASMAN_DEVICEINFO *pInfoTable = pDevice->pInfoTable;
|
|
|
|
|
|
|
|
for (i=0; i < pNewInfo->DI_NumOfParams; i++) //For each param to set,
|
|
{
|
|
fFound = FALSE;
|
|
|
|
|
|
for (j=0; j < pInfoTable->DI_NumOfParams; j++) //check InfoTable entries
|
|
{
|
|
// Check for unary macro match
|
|
|
|
if (IsUnaryMacro(pInfoTable->DI_Params[j]) &&
|
|
|
|
_stricmp(pNewInfo->DI_Params[i].P_Key,
|
|
pInfoTable->DI_Params[j].P_Key) == 0)
|
|
{
|
|
|
|
// Check format of P_Value field; convert to string if necessary
|
|
|
|
if (pNewInfo->DI_Params[i].P_Type == String)
|
|
{
|
|
pszSrc = pNewInfo->DI_Params[i].P_Value.String.Data;
|
|
dwSrcLen = pNewInfo->DI_Params[i].P_Value.String.Length;
|
|
}
|
|
else
|
|
{ //P_Type == Number
|
|
_itoa(pNewInfo->DI_Params[i].P_Value.Number,
|
|
szNumberStr,
|
|
10);
|
|
pszSrc = szNumberStr;
|
|
dwSrcLen = strlen(szNumberStr);
|
|
}
|
|
|
|
|
|
// Copy P_Value (allocating more memory as necessary)
|
|
|
|
dwRC = UpdateParamString(&(pInfoTable->DI_Params[j]),
|
|
pszSrc,
|
|
dwSrcLen);
|
|
if (dwRC != SUCCESS)
|
|
return(dwRC);
|
|
|
|
|
|
fFound = TRUE;
|
|
break;
|
|
}
|
|
|
|
|
|
// Check for Binary Macro match
|
|
|
|
else if(CoreMacroNameMatch(pNewInfo->DI_Params[i].P_Key,
|
|
pInfoTable->DI_Params[j].P_Key))
|
|
{
|
|
|
|
// Convert string to number, if necessary
|
|
|
|
if (pNewInfo->DI_Params[i].P_Type == String)
|
|
{
|
|
strncpy(szNumberStr,
|
|
pNewInfo->DI_Params[i].P_Value.String.Data,
|
|
pNewInfo->DI_Params[i].P_Value.String.Length);
|
|
|
|
szNumberStr[pNewInfo->DI_Params[i].P_Value.String.Length] = '\0';
|
|
|
|
dwNumber = atoi(szNumberStr);
|
|
}
|
|
else
|
|
dwNumber = pNewInfo->DI_Params[i].P_Value.Number;
|
|
|
|
|
|
// Set macro enabled bit in Attributes field
|
|
|
|
if (dwNumber == 0)
|
|
{
|
|
pInfoTable->DI_Params[j].P_Attributes &= ~ATTRIB_ENABLED; //Clear bit
|
|
pInfoTable->DI_Params[j+1].P_Attributes &= ~ATTRIB_ENABLED;
|
|
}
|
|
else
|
|
{
|
|
pInfoTable->DI_Params[j].P_Attributes |= ATTRIB_ENABLED; //Set bit
|
|
pInfoTable->DI_Params[j+1].P_Attributes |= ATTRIB_ENABLED;
|
|
}
|
|
|
|
fFound = TRUE;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (!fFound)
|
|
return(ERROR_WRONG_KEY_SPECIFIED);
|
|
}
|
|
|
|
return(SUCCESS);
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//* DeviceAttachedToPort ---------------------------------------------------
|
|
//
|
|
// Funciton: Searched through a port info block for DeviceType and
|
|
// DeviceName and compares the found strings to the second
|
|
// and third input parameters.
|
|
//
|
|
// Assumptions: The first parameter has been initalize by a call to
|
|
// PortGetInfo.
|
|
// SER_DEVCIETYPE_KEY and SER_DEVICENAME_KEY each appear
|
|
// only once in the RASMAN_PORTINFO block.
|
|
//
|
|
// Returns: TRUE if pszDeviceType and pszDeviceName are found in
|
|
// pPortInfo, else FALSE.
|
|
//*
|
|
|
|
BOOL
|
|
DeviceAttachedToPort(RASMAN_PORTINFO *pPortInfo,
|
|
char *pszDeviceType,
|
|
char *pszDeviceName)
|
|
{
|
|
WORD i;
|
|
BOOL bTypeMatch = FALSE, bNameMatch = FALSE;
|
|
|
|
|
|
for (i=0; i<pPortInfo->PI_NumOfParams; i++)
|
|
{
|
|
if (_stricmp(SER_DEVICETYPE_KEY, pPortInfo->PI_Params[i].P_Key) == 0)
|
|
{
|
|
if ( strlen(pszDeviceType) ==
|
|
pPortInfo->PI_Params[i].P_Value.String.Length
|
|
&&
|
|
_strnicmp(pszDeviceType,
|
|
pPortInfo->PI_Params[i].P_Value.String.Data,
|
|
pPortInfo->PI_Params[i].P_Value.String.Length) == 0)
|
|
|
|
bTypeMatch = TRUE;
|
|
else
|
|
break;
|
|
}
|
|
|
|
if (_stricmp(SER_DEVICENAME_KEY, pPortInfo->PI_Params[i].P_Key) == 0)
|
|
{
|
|
if ( strlen(pszDeviceName) ==
|
|
pPortInfo->PI_Params[i].P_Value.String.Length
|
|
&&
|
|
_strnicmp(pszDeviceName,
|
|
pPortInfo->PI_Params[i].P_Value.String.Data,
|
|
pPortInfo->PI_Params[i].P_Value.String.Length) == 0)
|
|
|
|
bNameMatch = TRUE;
|
|
else
|
|
break;
|
|
}
|
|
|
|
if (bTypeMatch && bNameMatch)
|
|
break;
|
|
}
|
|
|
|
|
|
return(bTypeMatch && bNameMatch);
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//* CreateDefaultOffString -------------------------------------------------
|
|
//
|
|
// Funciton:
|
|
// DeviceName and compares the found strings to the second
|
|
// and third input parameters.
|
|
//
|
|
// Assumptions: Buffer pointed to by pszDefaultOff is large enough for
|
|
// all DefaultOff macros.
|
|
//
|
|
// Returns: Nothing
|
|
//*
|
|
|
|
void
|
|
CreateDefaultOffString(DEVICE_CB *pDev, char *pszDefaultOff)
|
|
{
|
|
WORD i, k, wLen;
|
|
|
|
char *szDefaultOffMacros[] = { MXS_SPEAKER_KEY ,
|
|
MXS_HDWFLOWCONTROL_KEY ,
|
|
MXS_PROTOCOL_KEY ,
|
|
MXS_COMPRESSION_KEY };
|
|
|
|
|
|
*pszDefaultOff = '\0';
|
|
|
|
|
|
// Find each macro and if it is off then add its name to DefaultOff string
|
|
|
|
for (i=0; i < sizeof(szDefaultOffMacros)/sizeof(char *); i++)
|
|
{
|
|
k = (WORD) FindTableEntry(pDev->pInfoTable, szDefaultOffMacros[i]);
|
|
|
|
if (k == INVALID_INDEX)
|
|
continue;
|
|
|
|
|
|
// If macro is turned off then copy its key to the DefaultOff string
|
|
|
|
if ( ! (pDev->pInfoTable->DI_Params[k].P_Attributes & ATTRIB_ENABLED))
|
|
{
|
|
strcat(pszDefaultOff, szDefaultOffMacros[i]);
|
|
strcat(pszDefaultOff, " "); //Add deliminting space
|
|
}
|
|
}
|
|
|
|
|
|
// Remove last delimiting space
|
|
|
|
wLen = (WORD)strlen(pszDefaultOff);
|
|
if (wLen > 0)
|
|
pszDefaultOff[wLen - 1] = '\0';
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//* BuildOutputTable -------------------------------------------------------
|
|
//
|
|
// Function: Copies macros from internal InfoTable to the caller's buffer.
|
|
// For Parameter: Function copies:
|
|
// Variable Entire RASMAN_DEVICEINFO struct
|
|
// Unary Macro Entire RASMAN_DEVICEINFO struct
|
|
// Binary Macro Everything except P_Value field
|
|
//
|
|
// Assumptions: - Output buffer will ALWAYS be large enough.
|
|
// - Parameters in InfoTable are sorted by P_Key (except
|
|
// internal macros).
|
|
// - Both parts of binary macros are present.
|
|
// These assumptions imply that if somename_off is in InfoTable
|
|
// somename_on is also present and is adjacent to somename_off.
|
|
//
|
|
// Returns: SUCCESS
|
|
// ERROR_BUFFER_TOO_SMALL
|
|
//
|
|
//*
|
|
|
|
DWORD
|
|
BuildOutputTable(DEVICE_CB *pDevice, BYTE *pInfo, DWORD *pdwSize)
|
|
{
|
|
WORD i, j;
|
|
DWORD cOutputParams = 0;
|
|
LPTCH pValue;
|
|
TCHAR szCoreName[MAX_PARAM_KEY_SIZE];
|
|
|
|
RASMAN_DEVICEINFO *pInfoTable = pDevice->pInfoTable,
|
|
*pOutputTable = (RASMAN_DEVICEINFO *)pInfo;
|
|
|
|
|
|
// Compute location of first value string (follows RAS_PARAMS)
|
|
|
|
cOutputParams =
|
|
pInfoTable->DI_NumOfParams - MacroCount(pInfoTable, BINARY_MACROS);
|
|
*pdwSize =
|
|
sizeof(RASMAN_DEVICEINFO) + sizeof(RAS_PARAMS) * (cOutputParams - 1);
|
|
pValue = pInfo + *pdwSize;
|
|
|
|
|
|
// Set NumOfParams
|
|
|
|
pOutputTable->DI_NumOfParams = cOutputParams;
|
|
|
|
|
|
// Copy macros
|
|
|
|
for (i=0, j=0; i < pInfoTable->DI_NumOfParams; i++)
|
|
{
|
|
if (IsBinaryMacro(pInfoTable->DI_Params[i].P_Key))
|
|
{
|
|
// copy core macro name, Type, and Attributes, but not Value
|
|
|
|
GetCoreMacroName(pInfoTable->DI_Params[i].P_Key, szCoreName);
|
|
strcpy(pOutputTable->DI_Params[j].P_Key, szCoreName);
|
|
|
|
pOutputTable->DI_Params[j].P_Type = pInfoTable->DI_Params[i].P_Type;
|
|
pOutputTable->DI_Params[j].P_Attributes =
|
|
pInfoTable->DI_Params[i].P_Attributes;
|
|
|
|
pOutputTable->DI_Params[j].P_Value.String.Data = pValue;
|
|
*pValue++ = '\0';
|
|
|
|
pOutputTable->DI_Params[j].P_Value.String.Length = 0;
|
|
|
|
i++;
|
|
j++;
|
|
}
|
|
else // Is Unary Macro or Variable
|
|
{
|
|
// copy everything including Value
|
|
|
|
pOutputTable->DI_Params[j] = pInfoTable->DI_Params[i];
|
|
|
|
pOutputTable->DI_Params[j].P_Value.String.Data = pValue;
|
|
strncpy(pValue, pInfoTable->DI_Params[i].P_Value.String.Data,
|
|
pInfoTable->DI_Params[i].P_Value.String.Length);
|
|
|
|
pOutputTable->DI_Params[j].P_Value.String.Length
|
|
= pInfoTable->DI_Params[i].P_Value.String.Length;
|
|
|
|
pValue += pInfoTable->DI_Params[i].P_Value.String.Length;
|
|
*pValue++ = '\0';
|
|
j++;
|
|
}
|
|
}
|
|
|
|
*pdwSize = (DWORD) (pValue - pInfo);
|
|
return(SUCCESS);
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//* ConnectListen() --------------------------------------------------------
|
|
//
|
|
// Function: Worker routine for DeviceConnect and DeviceListen.
|
|
//
|
|
// Returns: ERROR_NO_COMMAND_FOUND
|
|
// ERROR_STATE_MACHINES_ALREADY_STARTED
|
|
// and codes returned by DeviceStateMachine()
|
|
//*
|
|
|
|
DWORD
|
|
ConnectListen(HANDLE hIOPort,
|
|
char *pszDeviceType,
|
|
char *pszDeviceName,
|
|
CMDTYPE eCmd)
|
|
{
|
|
DWORD dRC;
|
|
DEVICE_CB *pDevice;
|
|
|
|
|
|
// Get Device Control Block for this hIOPort
|
|
|
|
dRC = GetDeviceCB(hIOPort, pszDeviceType, pszDeviceName, &pDevice);
|
|
if (dRC != SUCCESS)
|
|
return(dRC);
|
|
|
|
|
|
// Check that DeviceStateMachine is not started (but is reset)
|
|
|
|
if (pDevice->eDevNextAction != SEND)
|
|
return(ERROR_STATE_MACHINES_ALREADY_STARTED);
|
|
|
|
|
|
// Create Macro Translation Table for use by RasDevAPIs
|
|
|
|
if ((dRC = BuildMacroXlationTable(pDevice)) != SUCCESS)
|
|
return(dRC);
|
|
|
|
|
|
// Do the next block only once for most devices,
|
|
// but retry a few times when getting modem hardware errors
|
|
|
|
do
|
|
{
|
|
// Initialize command types
|
|
|
|
switch(RasDevIdFirstCommand(pDevice->hInfFile))
|
|
{
|
|
case CT_INIT:
|
|
pDevice->eCmdType = CT_INIT;
|
|
pDevice->eNextCmdType = eCmd;
|
|
break;
|
|
|
|
case CT_DIAL: //If 1st cmd is DIAL or LISTEN assume
|
|
case CT_LISTEN: //the other is also present
|
|
pDevice->eCmdType = eCmd;
|
|
break;
|
|
|
|
case CT_GENERIC:
|
|
pDevice->eCmdType = CT_GENERIC;
|
|
break;
|
|
|
|
default:
|
|
return(ERROR_NO_COMMAND_FOUND);
|
|
}
|
|
|
|
|
|
// Reseting state variables and purging com ports are not needed on
|
|
// first time through loop, but are need on subsequent loops.
|
|
|
|
// Reset state variables to initial values
|
|
|
|
pDevice->eDevNextAction = SEND;
|
|
pDevice->eRcvState = GETECHO;
|
|
|
|
|
|
// Cancel any pending com port action and purge com buffers
|
|
|
|
PurgeComm(hIOPort,
|
|
PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR);
|
|
|
|
|
|
// Start state machine
|
|
|
|
dRC = DeviceStateMachine(pDevice, hIOPort);
|
|
|
|
} while(dRC == ERROR_PORT_OR_DEVICE &&
|
|
pDevice->eDeviceType == DT_MODEM &&
|
|
pDevice->dwRetries++ < MODEM_RETRIES );
|
|
|
|
|
|
return(dRC);
|
|
}
|
|
|
|
|
|
//* DeviceTypeStrToEnum ----------------------------------------------------
|
|
//
|
|
// Function: Converts a device type string into a device type enum.
|
|
//
|
|
// Returns: The device type code.
|
|
//
|
|
//*
|
|
|
|
DEVICETYPE
|
|
DeviceTypeStrToEnum(LPTSTR lpszDeviceType)
|
|
{
|
|
if (_strnicmp(lpszDeviceType, MXS_NULL_TXT, MAX_DEVICETYPE_NAME) == 0)
|
|
return(DT_NULL);
|
|
|
|
if (_strnicmp(lpszDeviceType, MXS_MODEM_TXT, MAX_DEVICETYPE_NAME) == 0)
|
|
return(DT_MODEM);
|
|
|
|
if (_strnicmp(lpszDeviceType, MXS_PAD_TXT, MAX_DEVICETYPE_NAME) == 0)
|
|
return(DT_PAD);
|
|
|
|
if (_strnicmp(lpszDeviceType, MXS_SWITCH_TXT, MAX_DEVICETYPE_NAME) == 0)
|
|
return(DT_SWITCH);
|
|
|
|
return(DT_UNKNOWN);
|
|
}
|
|
|
|
|
|
|
|
|
|
//* GetInfFileName ---------------------------------------------------------
|
|
//
|
|
// Function: Converts a device type string into the full path name for the
|
|
// appropriate INF file.
|
|
//
|
|
// The RAS_PATH define contains leading and trailin backslashes.
|
|
// It looks like "\\RAS\\".
|
|
//
|
|
// Returns: Nothing.
|
|
//
|
|
//*
|
|
|
|
void
|
|
GetInfFileName(LPTSTR pszDeviceType, LPTSTR pszFileName, DWORD dwFileNameLen)
|
|
{
|
|
UINT uLen;
|
|
|
|
|
|
uLen = GetSystemDirectory(pszFileName, dwFileNameLen);
|
|
|
|
strcat(pszFileName, RAS_PATH);
|
|
|
|
switch(DeviceTypeStrToEnum(pszDeviceType))
|
|
{
|
|
case DT_NULL:
|
|
case DT_MODEM:
|
|
strcat(pszFileName, MODEM_INF_FILENAME);
|
|
break;
|
|
|
|
case DT_PAD:
|
|
strcat(pszFileName, PAD_INF_FILENAME);
|
|
break;
|
|
|
|
case DT_SWITCH:
|
|
strcat(pszFileName, SWITCH_INF_FILENAME);
|
|
break;
|
|
|
|
default:
|
|
strcat(pszFileName, "");
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//* IsVariable -------------------------------------------------------------
|
|
//
|
|
// Function: Returns TRUE if parameter's "Variable" attribute bit is set.
|
|
// Note that FALSE implies that the paramater is a macro.
|
|
//
|
|
//*
|
|
|
|
BOOL
|
|
IsVariable(RAS_PARAMS Param)
|
|
{
|
|
return(ATTRIB_VARIABLE & Param.P_Attributes);
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//* IsUnaryMacro -----------------------------------------------------------
|
|
//
|
|
// Function: Returns TRUE if param is a unary macro, otherwise FALSE.
|
|
//
|
|
//*
|
|
|
|
BOOL
|
|
IsUnaryMacro(RAS_PARAMS Param)
|
|
{
|
|
return(!IsVariable(Param) && !IsBinaryMacro(Param.P_Key));
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//* IsBinaryMacro ----------------------------------------------------------
|
|
//
|
|
// Function: Returns TRUE if the string ends with off suffix or on suffix.
|
|
//
|
|
// FALSE inmplies that the string is a unary macro or a variable
|
|
// name.
|
|
//
|
|
//*
|
|
|
|
BOOL
|
|
IsBinaryMacro(TCHAR *pch)
|
|
{
|
|
return((BOOL)BinarySuffix(pch));
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//* BinarySuffix -----------------------------------------------------------
|
|
//
|
|
// Function: This function indicates whether the input string ends in
|
|
// _off or _on.
|
|
//
|
|
// Returns: ON_SUFFIX, OFF_SUFFIX, or FALSE if neither is the case
|
|
//
|
|
//*
|
|
WORD
|
|
BinarySuffix(TCHAR *pch)
|
|
{
|
|
while (*pch != '\0')
|
|
pch++;
|
|
|
|
pch -= strlen(MXS_ON_SUFX);
|
|
if (_stricmp(pch, MXS_ON_SUFX) == 0)
|
|
return(ON_SUFFIX);
|
|
|
|
while (*pch != '\0')
|
|
pch++;
|
|
|
|
pch -= strlen(MXS_OFF_SUFX);
|
|
if (_stricmp(pch, MXS_OFF_SUFX) == 0)
|
|
return(OFF_SUFFIX);
|
|
|
|
return(FALSE);
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//* GetCoreMacroName -------------------------------------------------------
|
|
//
|
|
// Function: Copies FullName to CoreName, but omits the angle brackets, <>,
|
|
// for all macros, and omits the "_ON" or "_OFF" suffix for binary
|
|
// macros.
|
|
//
|
|
// Returns: SUCCESS
|
|
// ERROR_NOT_BINARY_MACRO
|
|
//
|
|
//*
|
|
|
|
DWORD
|
|
GetCoreMacroName(LPTSTR lpszFullName, LPTSTR lpszCoreName)
|
|
{
|
|
LPTCH lpch;
|
|
|
|
|
|
strcpy(lpszCoreName, lpszFullName); // Copy FullName
|
|
|
|
lpch = lpszCoreName;
|
|
|
|
while (*lpch != '\0') // Check for _ON suffix
|
|
lpch++;
|
|
|
|
lpch -= strlen(MXS_ON_SUFX);
|
|
if (_stricmp(lpch, MXS_ON_SUFX) == 0)
|
|
{
|
|
*lpch = '\0';
|
|
return(SUCCESS);
|
|
}
|
|
|
|
|
|
while (*lpch != '\0') // Check for _OFF suffix
|
|
lpch++;
|
|
|
|
lpch -= strlen(MXS_OFF_SUFX);
|
|
if (_stricmp(lpch, MXS_OFF_SUFX) == 0)
|
|
{
|
|
*lpch = '\0';
|
|
return(SUCCESS);
|
|
}
|
|
|
|
return(ERROR_NOT_BINARY_MACRO);
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//* CoreMacroNameMatch -----------------------------------------------------
|
|
//
|
|
// Function: Assumes that lpszShortName is in the form of a unary macro
|
|
// name, <macro>, and that lpszFullName is a binary macro.
|
|
// If either assumption is false the function returns FALSE.
|
|
// Only if the names (without the angle brackets, <>, and without
|
|
// the _on or _off suffixes) match exactly is TRUE returned.
|
|
//
|
|
// <speaker> will match <speaker_off> or <speaker_on>, but
|
|
// will not match <speakers_off>.
|
|
//
|
|
// Returns: TRUE/FALSE
|
|
//
|
|
//*
|
|
|
|
BOOL
|
|
CoreMacroNameMatch(LPTSTR lpszShortName, LPTSTR lpszFullName)
|
|
{
|
|
TCHAR szCoreName[MAX_PARAM_KEY_SIZE];
|
|
DWORD dRC;
|
|
|
|
|
|
dRC = GetCoreMacroName(lpszFullName, szCoreName);
|
|
if (dRC != SUCCESS)
|
|
return(FALSE);
|
|
|
|
return(_stricmp(lpszShortName, szCoreName) == 0);
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//* InitParameterStr -------------------------------------------------------
|
|
//
|
|
// Function: Changes all spaces in the first parameter to NULL characters.
|
|
// On return the second parameter is a pointer to the NULL
|
|
// character at the end of the input string.
|
|
//
|
|
// This function converts space separated parameters into NULL
|
|
// terminated strings. GetNextParameter() is then used to move
|
|
// a pointer from one string to the next.
|
|
//
|
|
// Caution: This function alters the input string.
|
|
//
|
|
// Returns: Nothing.
|
|
//
|
|
//*
|
|
|
|
void
|
|
InitParameterStr(TCHAR *pch, TCHAR **ppchEnd)
|
|
{
|
|
while (*pch != '\0')
|
|
{
|
|
if ((*pch == ' ') || (*pch == ','))
|
|
*pch = '\0';
|
|
pch++;
|
|
}
|
|
|
|
*ppchEnd = pch;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//* GetNextParameter -------------------------------------------------------
|
|
//
|
|
// Function: If the first parameter points to a consecutive series of null
|
|
// terminated strings, this function advances the first parameter
|
|
// to the beginning of the next null terminated string.
|
|
// It will not move past the second parameter which is a pointer
|
|
// to the end of the consecutive series.
|
|
//
|
|
// Returns: Nothing.
|
|
//
|
|
//*
|
|
void
|
|
GetNextParameter(TCHAR **ppch, TCHAR *pchEnd)
|
|
{
|
|
while (**ppch != '\0') //Move to next zero character
|
|
(*ppch)++;
|
|
|
|
while (*ppch < pchEnd && **ppch == '\0') //Move to 1st char of next substr
|
|
(*ppch)++;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//* MacroCount -------------------------------------------------------------
|
|
//
|
|
// Function: This function returns a count of macros in the RASMAN_DEVICEINFO
|
|
// struct that the input parameter points to.
|
|
// ALL_MACROS: Unary and binary macros are counted.
|
|
// BINARY_MACRO: Only binary macros are counted.
|
|
// In either case the ON and OFF parts of a binary macro
|
|
// together count as one macro (not two).
|
|
//
|
|
// Returns: Count of macros in *pInfo.
|
|
//
|
|
//*
|
|
|
|
WORD
|
|
MacroCount(RASMAN_DEVICEINFO *pInfo, WORD wType)
|
|
{
|
|
WORD i, cMacros;
|
|
|
|
|
|
for(i=0, cMacros=0; i < pInfo->DI_NumOfParams; i++)
|
|
{
|
|
if (IsVariable(pInfo->DI_Params[i]))
|
|
;
|
|
|
|
else if (IsBinaryMacro(pInfo->DI_Params[i].P_Key))
|
|
{
|
|
i++; // Step thru each part of a binary macro
|
|
cMacros++; // But count only once
|
|
}
|
|
else // Unary macro
|
|
if (wType == ALL_MACROS)
|
|
cMacros++;
|
|
}
|
|
|
|
return(cMacros);
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//* CmdTypeToStr -----------------------------------------------------------
|
|
//
|
|
// Function: This function takes an enum CMDTYPE and converts it to a
|
|
// zero terminated ASCII string which it places in the buffer
|
|
// passed in the first parameter.
|
|
//
|
|
// Returns: Pointer to first parameter
|
|
//
|
|
//*
|
|
|
|
PTCH
|
|
CmdTypeToStr(PTCH pszStr, CMDTYPE eCmdType)
|
|
{
|
|
switch(eCmdType)
|
|
{
|
|
case CT_GENERIC:
|
|
*pszStr = '\0';
|
|
break;
|
|
|
|
case CT_INIT:
|
|
strcpy(pszStr, "_INIT");
|
|
break;
|
|
|
|
case CT_DIAL:
|
|
strcpy(pszStr, "_DIAL");
|
|
break;
|
|
|
|
case CT_LISTEN:
|
|
strcpy(pszStr, "_LISTEN");
|
|
break;
|
|
}
|
|
|
|
return(pszStr);
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//* IsLoggingOn -----------------------------------------------------------
|
|
//
|
|
// Funciton: Reads the registry to determine if the device dialog is to
|
|
// be logged in a file.
|
|
//
|
|
// Returns: TRUE if logging is to take place; otherwise FALSE
|
|
//
|
|
//*
|
|
|
|
BOOL
|
|
IsLoggingOn(void)
|
|
{
|
|
HKEY hKey;
|
|
LONG lRC;
|
|
DWORD dwType, dwValue, dwValueSize = sizeof(dwValue);
|
|
|
|
|
|
lRC = RegOpenKey(HKEY_LOCAL_MACHINE, RASMAN_REGISTRY_PATH, &hKey);
|
|
if (lRC != ERROR_SUCCESS)
|
|
return(FALSE);
|
|
|
|
lRC = RegQueryValueEx(hKey,
|
|
RASMAN_LOGGING_VALUE,
|
|
NULL,
|
|
&dwType,
|
|
(LPBYTE)&dwValue,
|
|
&dwValueSize);
|
|
|
|
RegCloseKey(hKey);
|
|
|
|
if (lRC != ERROR_SUCCESS)
|
|
return(FALSE);
|
|
|
|
if (dwType != REG_DWORD)
|
|
return(FALSE);
|
|
|
|
|
|
return(dwValue ? TRUE : FALSE);
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//* InitLog ---------------------------------------------------------------
|
|
//
|
|
// Funciton: Opens the log file in overwrite mode and writes a header
|
|
// which includes date and time.
|
|
//
|
|
// Returns: Nothing.
|
|
//
|
|
//*
|
|
|
|
void
|
|
InitLog(void)
|
|
{
|
|
TCHAR szBuffer[MAX_CMD_BUF_LEN];
|
|
int iSize;
|
|
DWORD dwBytesWritten;
|
|
SYSTEMTIME st;
|
|
|
|
|
|
// Create log file path
|
|
|
|
GetSystemDirectory(szBuffer, sizeof(szBuffer));
|
|
strcat(szBuffer, RAS_PATH);
|
|
strcat(szBuffer, LOG_FILENAME);
|
|
|
|
|
|
ghLogFile = CreateFile(szBuffer,
|
|
GENERIC_WRITE,
|
|
FILE_SHARE_READ,
|
|
NULL,
|
|
CREATE_ALWAYS,
|
|
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN,
|
|
NULL);
|
|
|
|
if (ghLogFile == INVALID_HANDLE_VALUE)
|
|
{
|
|
gbLogDeviceDialog = FALSE;
|
|
return;
|
|
}
|
|
|
|
|
|
// Create header
|
|
|
|
GetLocalTime(&st);
|
|
|
|
iSize = sprintf(szBuffer,
|
|
"Remote Access Service Device Log %02d/%02d/%d %02d:%02d:%02d\r\n",
|
|
st.wMonth, st.wDay, st.wYear, st.wHour, st.wMinute, st.wSecond);
|
|
|
|
WriteFile(ghLogFile, szBuffer, (DWORD)iSize, &dwBytesWritten, NULL);
|
|
|
|
strcpy(szBuffer,
|
|
"---------------------------------------------------------------\r\n\r\n");
|
|
|
|
WriteFile(ghLogFile, szBuffer, strlen(szBuffer), &dwBytesWritten, NULL);
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//* LogString -------------------------------------------------------------
|
|
//
|
|
// Funciton: Writes label and string to the Device Log file.
|
|
//
|
|
// Assumptions: Total length of labels and port handle string will be < 80
|
|
// characters.
|
|
//
|
|
// Returns: nothing.
|
|
//
|
|
//*
|
|
|
|
void
|
|
LogString(DEVICE_CB *pDev, TCHAR *pszLabel, TCHAR *psString, DWORD dwStringLen)
|
|
{
|
|
TCHAR sBuffer[MAX_CMD_BUF_LEN + 80];
|
|
TCHAR szPortLabel[] = "Port:";
|
|
DWORD dwBytesWritten, dwTotalLen;
|
|
|
|
|
|
// If file is getting large, start over with new file
|
|
|
|
if (GetFileSize(ghLogFile, NULL) > 100000)
|
|
{
|
|
CloseHandle(ghLogFile);
|
|
InitLog();
|
|
}
|
|
|
|
|
|
strcpy(sBuffer, szPortLabel);
|
|
dwTotalLen = strlen(szPortLabel);
|
|
|
|
strcpy(sBuffer + dwTotalLen, pDev->szPortName);
|
|
dwTotalLen += strlen(pDev->szPortName);
|
|
|
|
strcpy(sBuffer + dwTotalLen, " ");
|
|
dwTotalLen++;
|
|
|
|
strcpy(sBuffer + dwTotalLen, pszLabel);
|
|
dwTotalLen += strlen(pszLabel);
|
|
|
|
memcpy(sBuffer + dwTotalLen, psString, dwStringLen);
|
|
dwTotalLen += dwStringLen;
|
|
|
|
strcpy(sBuffer + dwTotalLen, "\r\n");
|
|
dwTotalLen += 2;
|
|
|
|
WriteFile(ghLogFile, sBuffer, dwTotalLen, &dwBytesWritten, NULL);
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//* CheckForOverruns -------------------------------------------------------
|
|
//
|
|
// Funciton: Checks for com port overrun errors.
|
|
//
|
|
// Assumptions: Com port errors have been cleared before rasmxs dll APIs
|
|
// are called, that is, serial dll API PortInit was called
|
|
// prior to using the port, or PortClose and PortOpen were
|
|
// called.
|
|
//
|
|
// Returns: TRUE if an overrun error has occured; otherwise FALSE.
|
|
//
|
|
//*
|
|
|
|
BOOL
|
|
CheckForOverruns(HANDLE hIOPort)
|
|
{
|
|
DWORD dwErrors = 0;
|
|
|
|
|
|
ClearCommError(hIOPort, &dwErrors, NULL);
|
|
|
|
return((dwErrors & CE_OVERRUN) ? TRUE : FALSE);
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//* LoadRasserDll ---------------------------------------------------------
|
|
//
|
|
// Funciton: Loads rasser.dll and gets entry points for two APIs.
|
|
//
|
|
// Returns: SUCCESS
|
|
// ERROR_PORT_NOT_CONFIGURED
|
|
//*
|
|
|
|
DWORD
|
|
LoadRasserDll(PortGetInfo_t *pPortGetInfo, PortSetInfo_t *pPortSetInfo)
|
|
{
|
|
HANDLE hLib;
|
|
|
|
|
|
// Load DLL
|
|
|
|
hLib = LoadLibrary(SERIAL_DLL_FILENAME);
|
|
if (hLib == NULL)
|
|
{
|
|
LogError(ROUTERLOG_CANNOT_LOAD_SERIAL_DLL, 0, NULL, NO_ERROR);
|
|
return(ERROR_PORT_NOT_CONFIGURED);
|
|
}
|
|
|
|
|
|
// Get entry points
|
|
// Note: Create a new, more appropriate error code to use here,
|
|
// such as, ERROR_CORRUPT_DLL.
|
|
|
|
PortSetInfo = (PortSetInfo_t) GetProcAddress(hLib, "PortSetInfo");
|
|
if (PortSetInfo == NULL)
|
|
return(ERROR_PORT_NOT_CONFIGURED);
|
|
|
|
PortGetInfo = (PortGetInfo_t) GetProcAddress(hLib, "PortGetInfo");
|
|
if (PortGetInfo == NULL)
|
|
return(ERROR_PORT_NOT_CONFIGURED);
|
|
|
|
|
|
return(SUCCESS);
|
|
}
|
|
|
|
|
|
|
|
|
|
//* OpenResponseSection ---------------------------------------------------
|
|
//
|
|
// Funciton: This function is only called if the device is a modem.
|
|
//
|
|
// 7-9-93 We now open the modem response section when a DCB
|
|
// is created for the first modem. Then we leave it open
|
|
// (while the RASMXS DLL is in memory).
|
|
//
|
|
// Returns: Error values from RasDevOpen.
|
|
//
|
|
//*
|
|
DWORD
|
|
OpenResponseSection (PCHAR szFileName)
|
|
{
|
|
DWORD dRC = SUCCESS ;
|
|
|
|
|
|
// **** Exclusion Begin ****
|
|
WaitForSingleObject(ResponseSection.Mutex, INFINITE) ;
|
|
|
|
if (ResponseSection.UseCount == 0)
|
|
dRC = RasDevOpen(szFileName,
|
|
RESPONSES_SECTION_NAME,
|
|
&ResponseSection.Handle) ;
|
|
|
|
if (dRC == SUCCESS)
|
|
ResponseSection.UseCount = 1 ; //This used to be an increment.
|
|
|
|
|
|
// *** Exclusion End ***
|
|
ReleaseMutex(ResponseSection.Mutex);
|
|
|
|
return dRC ;
|
|
}
|
|
|
|
|
|
|
|
|
|
//* OpenResponseSection ---------------------------------------------------
|
|
//
|
|
// Funciton: This function should never be called.
|
|
//
|
|
// 7-9-93 We now open the modem response section when a DCB
|
|
// is created for the first modem. Then we leave it open
|
|
// (while the RASMXS DLL is in memory).
|
|
//
|
|
// Returns: nothing.
|
|
//
|
|
//*
|
|
|
|
/***
|
|
VOID
|
|
CloseResponseSection ()
|
|
{
|
|
|
|
// **** Exclusion Begin ****
|
|
WaitForSingleObject(ResponseSection.Mutex, INFINITE) ;
|
|
|
|
ResponseSection.UseCount-- ;
|
|
|
|
if (ResponseSection.UseCount == 0)
|
|
RasDevClose (ResponseSection.Handle) ;
|
|
|
|
// *** Exclusion End ***
|
|
ReleaseMutex(ResponseSection.Mutex);
|
|
|
|
}
|
|
***/
|
|
|
|
|
|
//* FindOpenDevSection
|
|
//
|
|
//
|
|
// Returns: TRUE if found, FALSE if not.
|
|
//*
|
|
BOOL
|
|
FindOpenDevSection (PTCH lpszFileName, PTCH lpszSectionName, HRASFILE *hFile)
|
|
{
|
|
|
|
SavedSections* temp ;
|
|
|
|
for (temp = gpSavedSections; temp; temp=temp->Next) {
|
|
if (!_strcmpi (temp->FileName, lpszFileName) &&
|
|
!_strcmpi (temp->SectionName, lpszSectionName) &&
|
|
!temp->InUse) {
|
|
*hFile = temp->hFile ;
|
|
temp->InUse = TRUE ;
|
|
RasDevResetCommand (*hFile) ;
|
|
return TRUE ;
|
|
}
|
|
}
|
|
|
|
return FALSE ;
|
|
}
|
|
|
|
|
|
//*
|
|
//
|
|
//
|
|
//
|
|
//*
|
|
VOID
|
|
AddOpenDevSection (PTCH lpszFileName, PTCH lpszSectionName, HRASFILE hFile)
|
|
{
|
|
SavedSections *temp ;
|
|
|
|
GetMem(sizeof(SavedSections), (char **)&temp) ;
|
|
if (temp == NULL)
|
|
return ; // section not saved - no problem
|
|
strcpy (temp->FileName, lpszFileName) ;
|
|
strcpy (temp->SectionName, lpszSectionName) ;
|
|
temp->InUse = TRUE ;
|
|
temp->hFile = hFile ;
|
|
|
|
if (gpSavedSections)
|
|
temp->Next = gpSavedSections ;
|
|
else
|
|
temp->Next = NULL ;
|
|
|
|
gpSavedSections = temp ;
|
|
}
|
|
|
|
|
|
//*
|
|
//
|
|
//
|
|
//
|
|
//*
|
|
VOID
|
|
CloseOpenDevSection (HRASFILE hFile)
|
|
{
|
|
SavedSections* temp ;
|
|
|
|
for (temp = gpSavedSections; temp; temp=temp->Next) {
|
|
if (temp->hFile == hFile) {
|
|
temp->InUse = FALSE ;
|
|
return ;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//* DbgPrntf --------------------------------------------------------------
|
|
//
|
|
// Funciton: DbgPrntf -- printf to the debugger console
|
|
// Takes printf style arguments.
|
|
// Expects newline characters at the end of the string.
|
|
// Written by BruceK.
|
|
//
|
|
// Returns: nothing
|
|
//
|
|
//*
|
|
|
|
#ifdef DEBUG
|
|
|
|
#include <stdarg.h>
|
|
#include <stdio.h>
|
|
|
|
|
|
void DbgPrntf(const char * format, ...) {
|
|
va_list marker;
|
|
char String[512];
|
|
|
|
va_start(marker, format);
|
|
vsprintf(String, format, marker);
|
|
OutputDebugString(String);
|
|
}
|
|
|
|
#endif //DEBUG
|
|
|
|
|
|
|
|
|
|
|
|
//* DbgStr ----------------------------------------------------------------
|
|
//
|
|
// Funciton: Writes an unterminated string to the debugger.
|
|
//
|
|
// Returns: nothing
|
|
//
|
|
//*
|
|
|
|
#ifdef DEBUG
|
|
|
|
|
|
void DbgStr(char Str[], DWORD StrLen)
|
|
{
|
|
DWORD i;
|
|
char Char[] = " ";
|
|
|
|
|
|
for (i=0; i<StrLen; i++)
|
|
{
|
|
Char[0] = Str[i];
|
|
OutputDebugString(Char);
|
|
}
|
|
|
|
if (StrLen > 0)
|
|
OutputDebugString("\n");
|
|
}
|
|
|
|
#endif //DEBUG
|
|
|
|
|
|
|
|
|
|
|
|
//* ConPrintf -------------------------------------------------------------
|
|
//
|
|
// Funciton: Writes debug information to the process's console window.
|
|
// Written by StefanS.
|
|
//
|
|
// Returns: nothing
|
|
//
|
|
//*
|
|
|
|
#ifdef DBGCON
|
|
|
|
VOID
|
|
ConPrintf ( char *Format, ... )
|
|
|
|
{
|
|
va_list arglist;
|
|
char OutputBuffer[1024];
|
|
DWORD length;
|
|
|
|
|
|
va_start( arglist, Format );
|
|
vsprintf( OutputBuffer, Format, arglist );
|
|
va_end( arglist );
|
|
|
|
length = strlen( OutputBuffer );
|
|
|
|
WriteFile( GetStdHandle(STD_OUTPUT_HANDLE),
|
|
(LPVOID )OutputBuffer,
|
|
length,
|
|
&length,
|
|
NULL );
|
|
|
|
}
|
|
|
|
#endif //DBGCON
|