Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

2148 lines
55 KiB

/* Copyright (c) 1995, Microsoft Corporation, all rights reserved
**
** rasman.c
** RAS Manager helpers
** Listed alphabetically
**
** These routines have been exempted from the TCHARizing applied to the rest
** of the library because RASMAN is still an ANSI interface.
**
** 09/20/95 Steve Cobb
*/
#include <windows.h> // Win32 root
#include <stdlib.h> // for atol()
#include <debug.h> // Trace/Assert library
#include <nouiutil.h> // Our public header
#include <raserror.h> // RAS error constants
#include <mcx.h> // Unimodem
#include <unimodem.h>
/* These types are described in MSDN and appear in Win95's unimdm.h private
** header (complete with typo) but not in any SDK headers.
*/
typedef struct tagDEVCFGGDR
{
DWORD dwSize;
DWORD dwVersion;
WORD fwOptions;
WORD wWaitBong;
}
DEVCFGHDR;
typedef struct tagDEVCFG
{
DEVCFGHDR dfgHdr;
COMMCONFIG commconfig;
}
DEVCFG;
#define MANUAL_DIAL 0x0004
#define TERMINAL_PRE 0x0001
// Test rig to return a variety of fake ports from GetRasPorts.
//
#define DUMMYPORTS 0
#if DUMMYPORTS
DWORD g_cPorts = 6;
#endif
/*----------------------------------------------------------------------------
** Local prototypes
**----------------------------------------------------------------------------
*/
DWORD
GetRasDevices(
IN HANDLE hConnection,
IN CHAR* pszDeviceType,
OUT RASMAN_DEVICE** ppDevices,
OUT DWORD* pdwEntries );
DWORD
GetRasPortParam(
IN HPORT hport,
IN CHAR* pszKey,
OUT RASMAN_PORTINFO** ppPortInfo,
OUT RAS_PARAMS** ppParam );
/*----------------------------------------------------------------------------
** Routines
**----------------------------------------------------------------------------
*/
DWORD
ClearRasdevStats(
IN RASDEV* pdev,
IN BOOL fBundle )
/* Resets statistics counters for a device.
**
** (Abolade Gbadegesin Nov-9-1995)
*/
{
if (pdev == NULL) { return ERROR_INVALID_PARAMETER; }
if ((HPORT)pdev->RD_Handle == (HPORT)INVALID_HANDLE_VALUE) {
return ERROR_INVALID_HANDLE;
}
ASSERT(g_pRasPortClearStatistics);
return (fBundle ? g_pRasBundleClearStatistics(NULL, (HPORT)pdev->RD_Handle)
: g_pRasPortClearStatistics(NULL, (HPORT)pdev->RD_Handle));
}
#if 0
DWORD
DeviceIdFromDeviceName(
TCHAR* pszDeviceName )
/* Returns the TAPI device ID associated with 'pszDeviceName'. Returns
** 0xFFFFFFFE if not found, 0xFFFFFFFF if found but not a Unimodem.
**
** This routine assumes that TAPI devices have unique names.
*/
{
DWORD dwErr;
DWORD dwId;
DWORD dwPorts;
RASMAN_PORT* pPorts;
TRACE("DeviceIdFromDeviceName");
dwId = 0xFFFFFFFE;
if (pszDeviceName)
{
dwErr = GetRasPorts( &pPorts, &dwPorts );
if (dwErr == 0)
{
CHAR* pszDeviceNameA;
pszDeviceNameA = StrDupAFromT( pszDeviceName );
if (pszDeviceNameA)
{
INT i;
RASMAN_PORT* pPort;
for (i = 0, pPort = pPorts; i < dwPorts; ++i, ++pPort)
{
if (lstrcmpiA( pszDeviceNameA, pPort->P_DeviceName ) == 0)
{
dwId = pPort->P_LineDeviceId;
break;
}
}
Free( pszDeviceNameA );
}
Free( pPorts );
}
}
TRACE1("DeviceIdFromDeviceName=%d",dwErr);
return dwId;
}
#endif
DWORD
FreeRasdevTable(
RASDEV* pDevTable,
DWORD iDevCount )
/* Frees a table built by GetRasdevTable.
**
** Returns 0 if succesful, or an error code.
**
** (Abolade Gbadegesin Nov-9-1995)
*/
{
DWORD i;
//
// validate arguments
//
if (pDevTable == NULL) { return ERROR_INVALID_PARAMETER; }
//
// free the device-name string fields
//
for (i = 0; i < iDevCount; i++) {
if (pDevTable[i].RD_DeviceName) { Free(pDevTable[i].RD_DeviceName); }
}
//
// free the array itself
//
Free(pDevTable);
return NO_ERROR;
}
DWORD
GetConnectTime(
IN HRASCONN hrasconn,
OUT DWORD* pdwConnectTime )
/* Loads '*pdwConnectTime' with the duration in milliseconds of the
** connection on pdev.
**
** Returns 0 if succesful, or an error code.
**
** (Abolade Gbadegesin Nov-9-1995)
*/
{
HPORT hport;
DWORD dwErr;
RASMAN_INFO info;
if (pdwConnectTime == NULL) { return ERROR_INVALID_PARAMETER; }
//
// initialize the argument
//
*pdwConnectTime = 0;
//
// get an HPORT for the HRASCONN
//
ASSERT(g_pRasGetHport);
hport = g_pRasGetHport(hrasconn);
if (hport == (HPORT)INVALID_HANDLE_VALUE) { return ERROR_INVALID_HANDLE; }
//
// get information on the HPORT
//
ASSERT(g_pRasGetInfo);
dwErr = g_pRasGetInfo(NULL, hport, &info);
if (dwErr != NO_ERROR) { return dwErr; }
if (info.RI_ConnState != CONNECTED) { *pdwConnectTime = 0; }
else { *pdwConnectTime = info.RI_ConnectDuration; }
return NO_ERROR;
}
DWORD
GetRasconnFraming(
IN HRASCONN hrasconn,
OUT DWORD* pdwSendFraming,
OUT DWORD* pdwRecvFraming )
/* Retrieves the framing bits for an active RAS connection.
**
** (Abolade Gbadegesin Nov-9-1995)
*/
{
DWORD dwErr;
HPORT hport;
RAS_FRAMING_INFO info;
//
// validate arguments
//
if (pdwSendFraming == NULL || pdwRecvFraming == NULL) {
return ERROR_INVALID_HANDLE;
}
//
// retrieve the HPORT for this connection
//
ASSERT(g_pRasGetHport);
hport = g_pRasGetHport(hrasconn);
if (hport == (HPORT)INVALID_HANDLE_VALUE) {
return ERROR_INVALID_HANDLE;
}
//
// retrieve the framing information for this port
//
ASSERT(g_pRasPortGetFramingEx);
dwErr = g_pRasPortGetFramingEx(NULL, hport, &info);
if (dwErr != NO_ERROR) { return dwErr; }
*pdwSendFraming = info.RFI_SendFramingBits;
*pdwRecvFraming = info.RFI_RecvFramingBits;
return NO_ERROR;
}
DWORD
GetRasconnFromRasdev(
IN RASDEV* pdev,
OUT RASCONN** ppconn,
IN RASCONN* pConnTable OPTIONAL,
IN DWORD iConnCount OPTIONAL )
/* Given a RASDEV structure for an active device, this function retrieves
** the RASCONN which corresponds to the device's current connection. The
** second and third arguments are optional; they specify a table of
** RASCONN structures to be searched. This is useful if the caller has
** already enumerated the active connections, so that this function does
** not need to re-enumerate them.
**
** (Abolade Gbadegesin Nov-9-1995)
*/
{
BOOL bFreeTable;
DWORD dwErr, i;
RASDEVSTATS stats;
//
// validate arguments
//
if (pdev == NULL || ppconn == NULL) { return ERROR_INVALID_PARAMETER; }
*ppconn = NULL;
//
// get stats for the RASDEV
//
dwErr = GetRasdevStats(pdev, &stats);
if (dwErr != NO_ERROR) { return dwErr; }
bFreeTable = FALSE;
//
// if the caller didn't pass in a table of RASCONNs, retrieve one
//
if (pConnTable == NULL) {
dwErr = GetRasconnTable(&pConnTable, &iConnCount);
if (dwErr != NO_ERROR) { return dwErr; }
bFreeTable = TRUE;
}
//
// find the connection which matches the RASDEV passed in
//
for (i = 0; i < iConnCount; i++) {
if ((HRASCONN)stats.RDS_Hrasconn == (pConnTable + i)->hrasconn) {
break;
}
}
//
// see how the search ended
//
if (i >= iConnCount) {
dwErr = ERROR_NO_DATA;
}
else {
dwErr = NO_ERROR;
if (!bFreeTable) {
//
// point to the place where we found the RASCONN
//
*ppconn = pConnTable + i;
}
else {
//
// make a copy of the RASCONN found
//
*ppconn = Malloc(sizeof(RASCONN));
if (!*ppconn) { dwErr = ERROR_NOT_ENOUGH_MEMORY; }
else { **ppconn = *(pConnTable + i); }
}
}
if (bFreeTable) { Free(pConnTable); }
return dwErr;
}
DWORD
GetRasdevBundle(
IN RASDEV* pdev,
OUT DWORD* pdwBundle )
/* Retrieves a handle which represents the current connection
** on the given device. This handle has the property that it will be
** identical for two devices which are multi-linked together.
** In the case of NT RAS, the RASMAN HBUNDLE is retrieved.
**
** (Abolade Gbadegesin Mar-6-1996)
*/
{
return g_pRasPortGetBundle(NULL, (HPORT)pdev->RD_Handle, (HBUNDLE *)pdwBundle);
}
DWORD
GetRasdevFraming(
IN RASDEV* pdev,
OUT DWORD* pdwFraming )
/* Retrieves the framing bits for an active RAS connection.
**
** (Abolade Gbadegesin Nov-9-1995)
*/
{
DWORD dwErr;
RAS_FRAMING_INFO info;
//
// validate arguments
//
if (pdwFraming == NULL) { return ERROR_INVALID_HANDLE; }
//
// retrieve the framing information for this port
//
ASSERT(g_pRasPortGetFramingEx);
dwErr = g_pRasPortGetFramingEx(NULL, (HPORT)pdev->RD_Handle, &info);
if (dwErr != NO_ERROR) { return dwErr; }
if (info.RFI_SendFramingBits & OLD_RAS_FRAMING) {
*pdwFraming = RASFP_Ras;
}
else
if (info.RFI_SendFramingBits & PPP_MULTILINK_FRAMING ||
info.RFI_SendFramingBits & PPP_FRAMING) {
*pdwFraming = RASFP_Ppp;
}
else
if (info.RFI_SendFramingBits & SLIP_FRAMING) {
*pdwFraming = RASFP_Slip;
}
else {
*pdwFraming = 0;
}
return NO_ERROR;
}
DWORD
GetRasdevFromRasconn(
IN RASCONN* pconn,
OUT RASDEV** ppdev,
IN RASDEV* pDevTable OPTIONAL,
IN DWORD iDevCount OPTIONAL )
/* Given a RASCONN structure for an active connection, this function
** retrieves the RASDEV for the device over which the connection is
** active. The second and third arguments are optional; they specify a
** table of RASDEV structures to be searched. This is useful if the
** caller has already enumerated the existing devices, so that this
** function does not need to re-enumerate them.
**
** (Abolade Gbadegesin Nov-9-1995)
*/
{
HPORT hport;
DWORD i, dwErr = NO_ERROR;
BOOL bFreeTable;
//
// validate the arguments
//
if (pconn == NULL || ppdev == NULL) { return ERROR_INVALID_PARAMETER; }
*ppdev = NULL;
//
// retrieve the device table if the caller didn't pass one in
//
bFreeTable = FALSE;
// For whistler bug 26403 gangz
//
do
{
if (pDevTable == NULL) {
dwErr = GetRasdevTable(&pDevTable, &iDevCount);
if (dwErr != NO_ERROR) {
return dwErr;
}
bFreeTable = TRUE;
}
//
// retrieve the HPORT for the RASCONN passed in
//
ASSERT(g_pRasGetHport);
hport = g_pRasGetHport(pconn->hrasconn);
if (hport == (HPORT)INVALID_HANDLE_VALUE)
{
// For whistler bug 26403 gangz
// here to break rather than return;
//
dwErr = ERROR_INVALID_HANDLE;
break;
}
//
// find the device to which the HPORT corresponds
//
for (i = 0; i < iDevCount; i++) {
if (hport == pDevTable[i].RD_Handle) { break; }
}
//
// see how the search ended
//
if (i >= iDevCount)
{
dwErr = ERROR_NO_DATA;
break;
}
else
{
dwErr = NO_ERROR;
if (!bFreeTable) {
*ppdev = pDevTable + i;
}
else {
*ppdev = Malloc(sizeof(RASDEV));
if (!*ppdev) { dwErr = ERROR_NOT_ENOUGH_MEMORY; }
else {
**ppdev = *(pDevTable + i);
(*ppdev)->RD_DeviceName = StrDup(pDevTable[i].RD_DeviceName);
if (!(*ppdev)->RD_DeviceName) {
Free(*ppdev);
*ppdev = NULL;
dwErr = ERROR_NOT_ENOUGH_MEMORY;
break;
}
}
}
}
}while(FALSE);
if (bFreeTable) { FreeRasdevTable(pDevTable, iDevCount); }
return dwErr;
}
DWORD
GetRasDevices(
IN HANDLE hConnection,
IN CHAR* pszDeviceType,
OUT RASMAN_DEVICE** ppDevices,
OUT DWORD* pdwEntries )
/* Fills caller's '*ppDevices' with the address of a heap block containing
** '*pwEntries' RASMAN_DEVICE structures.
**
** Returns 0 if successful, otherwise a non-0 error code. If successful,
** it is the caller's responsibility to free the returned memory block.
*/
{
DWORD dwSize = 0;
DWORD dwErr;
TRACE1("GetRasDevices(%s)",pszDeviceType);
ASSERT(g_pRasDeviceEnum);
TRACE("RasDeviceEnum...");
dwErr = g_pRasDeviceEnum(hConnection, pszDeviceType, NULL, &dwSize, pdwEntries );
TRACE2("RasDeviceEnum=%d,c=%d",dwErr,*pdwEntries);
if (dwErr == 0)
{
/* No devices to enumerate. Set up to allocate a single byte anyway,
** so things work without lots of special code.
*/
dwSize = 1;
}
else if (dwErr != ERROR_BUFFER_TOO_SMALL)
return dwErr;
*ppDevices = (RASMAN_DEVICE* )Malloc( dwSize );
if (!*ppDevices)
return ERROR_NOT_ENOUGH_MEMORY;
TRACE("RasDeviceEnum...");
dwErr = g_pRasDeviceEnum(
hConnection,
pszDeviceType,
(PBYTE )*ppDevices,
&dwSize,
pdwEntries );
TRACE1("RasDeviceEnum=%d",dwErr);
if (dwErr != 0)
{
Free( *ppDevices );
return dwErr;
}
return 0;
}
DWORD
GetRasDeviceString(
IN HPORT hport,
IN CHAR* pszDeviceType,
IN CHAR* pszDeviceName,
IN CHAR* pszKey,
OUT CHAR** ppszValue,
IN DWORD dwXlate )
/* Loads callers '*ppszValue' with the address of a heap block containing
** a NUL-terminated copy of the value string associated with key 'pszKey'
** for the device on port 'hport'. 'pszDeviceType' specifies the type of
** device, e.g. "modem". 'pszDeviceName' specifies the name of the
** device, e.g. "Hayes V-Series 9600". 'dwXlate' is a bit mask of XLATE_
** bits specifying translations to perform on the returned string.
**
** Returns 0 if successful, otherwise a non-0 error code. If successful,
** it is the caller's responsibility to Free the returned string.
*/
{
DWORD dwErr = 0;
RASMAN_DEVICEINFO* pDeviceInfo = NULL;
RAS_PARAMS* pParam;
DWORD dwSize = 0;
INT i;
TRACE2("GetRasDeviceString(%s,%s)",pszDeviceName,pszKey);
*ppszValue = NULL;
do
{
ASSERT(g_pRasDeviceGetInfo);
TRACE("RasDeviceGetInfo...");
dwErr = g_pRasDeviceGetInfo(
NULL, hport, pszDeviceType, pszDeviceName, NULL, &dwSize );
TRACE2("RasDeviceGetInfo=%d,s=%d",dwErr,(INT)dwSize);
if (dwErr != ERROR_BUFFER_TOO_SMALL && dwErr != 0)
break;
/* So it will fall thru and be "not found".
*/
if (dwSize == 0)
dwSize = 1;
pDeviceInfo = (RASMAN_DEVICEINFO* )Malloc( dwSize );
if (!pDeviceInfo)
return ERROR_NOT_ENOUGH_MEMORY;
TRACE("RasDeviceGetInfo...");
dwErr = g_pRasDeviceGetInfo(
NULL, hport, pszDeviceType, pszDeviceName, (PBYTE )pDeviceInfo, &dwSize );
TRACE2("RasDeviceGetInfo=%d,s=%d",dwErr,(INT)dwSize);
if (dwErr != 0)
break;
dwErr = ERROR_KEY_NOT_FOUND;
for (i = 0, pParam = pDeviceInfo->DI_Params;
i < (INT )pDeviceInfo->DI_NumOfParams;
++i, ++pParam)
{
if (lstrcmpiA( pParam->P_Key, pszKey ) == 0)
{
*ppszValue = PszFromRasValue( &pParam->P_Value, dwXlate );
dwErr = (*ppszValue) ? 0 : ERROR_NOT_ENOUGH_MEMORY;
break;
}
}
}
while (FALSE);
Free0( pDeviceInfo );
TRACE1("String=\"%s\"",(*ppszValue)?*ppszValue:"");
return dwErr;
}
DWORD
GetRasdevStats(
IN RASDEV* pdev,
OUT RASDEVSTATS* pstats )
/* Retrieves statistics for a device.
**
** (Abolade Gbadegesin Nov-9-1995)
*/
{
DWORD dwsize;
RASMAN_INFO info;
RAS_STATISTICS *prs;
BYTE buffer[sizeof(RAS_STATISTICS) + MAX_STATISTICS * 2 * sizeof(DWORD)];
DWORD dwErr, *pdw, dwGone, dwB, dwBC, dwBU;
if (pdev == NULL || pstats == NULL) { return ERROR_INVALID_PARAMETER; }
ZeroMemory(pstats, sizeof(RASDEVSTATS));
//
// retrieve the condition and connect time
//
ASSERT(g_pRasGetInfo);
dwErr = g_pRasGetInfo(NULL, (HPORT)pdev->RD_Handle, &info);
if (dwErr != NO_ERROR) {
pstats->RDS_Condition = DISCONNECTED;
return dwErr;
}
//
// need to handle ports which are not connected
// already a bug filed.
//
if (info.RI_PortStatus != OPEN) {
pstats->RDS_Condition = DISCONNECTED;
return NO_ERROR;
}
pstats->RDS_Condition = info.RI_ConnState;
if (info.RI_ConnState == CONNECTED) {
pstats->RDS_ConnectTime = info.RI_ConnectDuration;
pstats->RDS_Hrasconn = (HRASCONN)info.RI_ConnectionHandle;
}
//
// get dial-in/dial-out usage
//
if (info.RI_CurrentUsage & CALL_IN)
pstats->RDS_Flags |= RDFLAG_IsDialedIn;
if (info.RI_CurrentUsage & CALL_OUT)
pstats->RDS_Flags |= RDFLAG_IsDialedOut;
if (info.RI_CurrentUsage & CALL_ROUTER)
pstats->RDS_Flags |= RDFLAG_IsRouter;
//
// Retrieve the line speed
//
pstats->RDS_LineSpeed = info.RI_LinkSpeed;
//
// Retrieve the i/o statistics for both the link and the bundle
//
prs = (RAS_STATISTICS *)buffer;
dwsize = sizeof(RAS_STATISTICS) + MAX_STATISTICS * 2 * sizeof(DWORD);
ZeroMemory(buffer, dwsize);
ASSERT(g_pRasBundleGetStatistics);
dwErr = g_pRasBundleGetStatistics(
NULL, (HPORT)pdev->RD_Handle, (PBYTE)prs, &dwsize
);
if (dwErr != NO_ERROR) { return dwErr; }
//
// Save the statistics in the caller's RASDEVSTATS structure.
//
pdw = prs->S_Statistics;
pstats->RDS_InFrames = pdw[FRAMES_RCVED];
pstats->RDS_OutFrames = pdw[FRAMES_XMITED];
pstats->RDS_InBytesTotal =
pdw[BYTES_RCVED] +
pdw[BYTES_RCVED_UNCOMPRESSED] -
pdw[BYTES_RCVED_COMPRESSED];
pstats->RDS_OutBytesTotal =
pdw[BYTES_XMITED] +
pdw[BYTES_XMITED_UNCOMPRESSED] -
pdw[BYTES_XMITED_COMPRESSED];
pstats->RDS_InBytes =
pdw[MAX_STATISTICS + BYTES_RCVED] +
pdw[MAX_STATISTICS + BYTES_RCVED_UNCOMPRESSED] -
pdw[MAX_STATISTICS + BYTES_RCVED_COMPRESSED];
pstats->RDS_OutBytes =
pdw[MAX_STATISTICS + BYTES_XMITED] +
pdw[MAX_STATISTICS + BYTES_XMITED_UNCOMPRESSED] -
pdw[MAX_STATISTICS + BYTES_XMITED_COMPRESSED];
pstats->RDS_ErrCRC =
pdw[MAX_STATISTICS + CRC_ERR];
pstats->RDS_ErrTimeout =
pdw[MAX_STATISTICS + TIMEOUT_ERR];
pstats->RDS_ErrAlignment =
pdw[MAX_STATISTICS + ALIGNMENT_ERR];
pstats->RDS_ErrFraming =
pdw[MAX_STATISTICS + FRAMING_ERR];
pstats->RDS_ErrHwOverruns =
pdw[MAX_STATISTICS + HARDWARE_OVERRUN_ERR];
pstats->RDS_ErrBufOverruns =
pdw[MAX_STATISTICS + BUFFER_OVERRUN_ERR];
#if 0
TRACE4(
"RasBundleGetStatistics(rx=%d,tx=%d,rxb=%d,txb=%d)",
pstats->RDS_InBytes, pstats->RDS_OutBytes,
pstats->RDS_InBytesTotal, pstats->RDS_OutBytesTotal
);
#endif
//
// Compute compression ratios, using the bundle-stats
//
pstats->RDS_InCompRatio = 0;
dwGone = 0;
dwB = pdw[BYTES_RCVED];
dwBC = pdw[BYTES_RCVED_COMPRESSED];
dwBU = pdw[BYTES_RCVED_UNCOMPRESSED];
if (dwBC < dwBU) { dwGone = dwBU - dwBC; }
if (dwB + dwGone > 100) {
DWORD dwDen = (dwB + dwGone) / 100;
pstats->RDS_InCompRatio = (dwGone + (dwDen / 2)) / dwDen;
}
pstats->RDS_OutCompRatio = 0;
dwGone = 0;
dwB = pdw[BYTES_XMITED];
dwBC = pdw[BYTES_XMITED_COMPRESSED];
dwBU = pdw[BYTES_XMITED_UNCOMPRESSED];
if (dwBC < dwBU) { dwGone = dwBU - dwBC; }
if (dwB + dwGone > 100) {
DWORD dwDen = (dwB + dwGone) / 100;
pstats->RDS_OutCompRatio = (dwGone + (dwDen / 2)) / dwDen;
}
return NO_ERROR;
}
DWORD
GetRasdevTable(
OUT RASDEV** ppDevTable,
OUT DWORD* piDevCount )
/* Gets an array of RAS devices configured. Loads '*ppDevTable' with a
** heap block of '*ppDevTable' entries. On NT, this is essentially the
** output of GetRasPorts(), in a format which includes a devicename,
** flags, and a handle. Given a RASMAN_PORT structure, we append the
** device and port names to make a unique device string which is part of
** the output.
**
** Returns 0 if successful, or an error.
**
** (Abolade Gbadegesin Nov-9-1995)
*/
{
DWORD dwPortCount;
DWORD i, iLength, dwErr;
RASDEV *pDevTable, *pdev;
PTSTR pszDevice, pszPort;
TCHAR szDevice[RAS_MaxDeviceName + 1];
RASMAN_PORT *pPortTable, *pport;
//
// validate the arguments
//
if (ppDevTable == NULL || piDevCount == NULL) {
return ERROR_INVALID_PARAMETER;
}
*piDevCount = 0;
*ppDevTable = NULL;
//
// get a table of ports from RASMAN; the string fields are ANSI
//
dwErr = GetRasPorts(NULL, &pPortTable, &dwPortCount);
if (dwErr != NO_ERROR) { return dwErr; }
if (dwPortCount == 0) { return NO_ERROR; }
//
// allocate space for as many device structs as there are ports
//
pDevTable = Malloc(dwPortCount * sizeof(RASDEV));
if (pDevTable == NULL) {
Free(pPortTable);
return ERROR_NOT_ENOUGH_MEMORY;
}
ZeroMemory(pDevTable, dwPortCount * sizeof(RASDEV));
//
// convert each RASMAN_PORT structure to a RASDEV structure.
//
for (i = 0, pport = pPortTable; i < dwPortCount; i++, pport++) {
pdev = pDevTable + i;
//
// copy over code-page-independent fields
//
pdev->RD_Handle = pport->P_Handle;
if (pport->P_ConfiguredUsage & CALL_IN)
pdev->RD_Flags |= RDFLAG_DialIn;
if (pport->P_ConfiguredUsage & CALL_OUT)
pdev->RD_Flags |= RDFLAG_DialOut;
if (pport->P_ConfiguredUsage & CALL_ROUTER)
pdev->RD_Flags |= RDFLAG_Router;
if (pport->P_CurrentUsage & CALL_IN)
pdev->RD_Flags |= RDFLAG_IsDialedIn;
if (pport->P_CurrentUsage & CALL_OUT)
pdev->RD_Flags |= RDFLAG_IsDialedOut;
if (pport->P_CurrentUsage & CALL_ROUTER)
pdev->RD_Flags |= RDFLAG_IsRouter;
//
// copy the device-type string
//
#ifdef UNICODE
StrCpyWFromAUsingAnsiEncoding(
pdev->RD_DeviceType,
pport->P_DeviceType,
RAS_MaxDeviceType);
#else
lstrcpy(pdev->RD_DeviceType, pport->P_DeviceType);
#endif
//
// copy the device-name and portname,
// storing them in temporary strings
//
#ifdef UNICODE
StrCpyWFromAUsingAnsiEncoding(
szDevice,
pport->P_DeviceName,
RAS_MaxDeviceName);
StrCpyWFromAUsingAnsiEncoding(
pdev->RD_PortName,
pport->P_PortName,
MAX_PORT_NAME);
pszDevice = szDevice;
pszPort = pdev->RD_PortName;
#else
pszDevice = pport->P_DeviceName;
lstrcpyn(pdev->RD_PortName, pport->P_PortName, MAX_PORT_NAME + 1);
pszPort = pdev->RD_PortName;
#endif
//
// get a display name from the device and port names
//
pdev->RD_DeviceName = PszFromDeviceAndPort(pszDevice, pszPort);
if (pdev->RD_DeviceName == NULL) {
Free(pPortTable);
FreeRasdevTable(pDevTable, dwPortCount);
return ERROR_NOT_ENOUGH_MEMORY;
}
}
Free(pPortTable);
*ppDevTable = pDevTable;
*piDevCount = dwPortCount;
return NO_ERROR;
}
DWORD
GetRasMessage(
IN HRASCONN hrasconn,
OUT TCHAR** ppszMessage )
/* Loads caller's '*ppszMessage' with the address of a heap block
** containing the current MXS_MESSAGE_KEY value associated with RAS
** connection 'hrasconn'.
**
** Returns 0 if successful or an error code. It is caller's
** responsibility to Free the returned string.
*/
{
DWORD dwErr;
RASCONNSTATUS rcs;
CHAR* pszMessage;
TRACE("GetRasMessage");
*ppszMessage = 0;
ZeroMemory( &rcs, sizeof(rcs) );
rcs.dwSize = sizeof(rcs);
ASSERT(g_pRasGetConnectStatus);
TRACE("RasGetConnectStatus");
dwErr = g_pRasGetConnectStatus( hrasconn, &rcs );
TRACE1("RasGetConnectStatus=%d",dwErr);
if (dwErr == 0)
{
CHAR* pszDeviceTypeA;
CHAR* pszDeviceNameA;
pszDeviceTypeA = StrDupAFromT( rcs.szDeviceType );
pszDeviceNameA = StrDupAFromT( rcs.szDeviceName );
if (!pszDeviceTypeA || !pszDeviceNameA)
{
Free0( pszDeviceNameA );
return ERROR_NOT_ENOUGH_MEMORY;
}
dwErr = GetRasDeviceString(
g_pRasGetHport( hrasconn ), pszDeviceTypeA, pszDeviceNameA,
MXS_MESSAGE_KEY, &pszMessage, XLATE_ErrorResponse );
Free0( pszDeviceTypeA );
Free0( pszDeviceNameA );
if (dwErr == 0)
{
*ppszMessage = StrDupTFromA( pszMessage );
if (!*ppszMessage)
dwErr = ERROR_NOT_ENOUGH_MEMORY;
Free0( pszMessage );
}
}
return dwErr;
}
DWORD
GetRasPads(
OUT RASMAN_DEVICE** ppDevices,
OUT DWORD* pdwEntries )
/* Fills caller's '*ppDevices' with the address of a heap block containing
** '*pwEntries' X.25 PAD DEVICE structures.
**
** Returns 0 if successful, otherwise a non-0 error code. If successful,
** it is the caller's responsibility to free the returned memory block.
*/
{
return GetRasDevices( NULL, MXS_PAD_TXT, ppDevices, pdwEntries );
}
VOID
GetRasPortMaxBps(
IN HPORT hport,
OUT DWORD* pdwMaxConnectBps,
OUT DWORD* pdwMaxCarrierBps )
/* Loads callers '*pdwMaxConnectBps' with the maximum port->modem bps rate
** for port 'pport', or with 0 if not found. '*pdwMaxCarrierBps' is the
** same but for maximum modem->modem speed.
*/
{
CHAR* pszValue = NULL;
DWORD dwErr;
TRACE("GetRasPortMaxBps");
dwErr = GetRasPortString(
hport, SER_CONNECTBPS_KEY, &pszValue, XLATE_None );
if (dwErr == 0)
*pdwMaxConnectBps = (DWORD )atol( pszValue );
else
*pdwMaxConnectBps = 0;
Free0(pszValue);
pszValue = NULL;
dwErr = GetRasPortString(
hport, SER_CARRIERBPS_KEY, &pszValue, XLATE_None );
if (dwErr == 0)
*pdwMaxCarrierBps = (DWORD )atol( pszValue );
else
*pdwMaxCarrierBps = 0;
Free0(pszValue);
}
VOID
GetRasPortModemSettings(
IN HPORT hport,
OUT BOOL* pfHwFlowDefault,
OUT BOOL* pfEcDefault,
OUT BOOL* pfEccDefault )
/* Loads caller's flags with the default setting of Hardware Flow Control,
** Error Control, and Error Control and Compression for the given 'hport'.
*/
{
CHAR* pszValue = NULL;
*pfHwFlowDefault = TRUE;
*pfEcDefault = TRUE;
*pfEccDefault = TRUE;
if (GetRasPortString(
hport, SER_C_DEFAULTOFFSTR_KEY, &pszValue, XLATE_None ) == 0)
{
if (StrStrA( pszValue, MXS_HDWFLOWCONTROL_KEY ) != NULL)
*pfHwFlowDefault = FALSE;
if (StrStrA( pszValue, MXS_PROTOCOL_KEY ) != NULL)
*pfEcDefault = FALSE;
if (StrStrA( pszValue, MXS_COMPRESSION_KEY ) != NULL)
*pfEccDefault = FALSE;
Free0( pszValue );
}
}
DWORD
GetRasPortParam(
IN HPORT hport,
IN CHAR* pszKey,
OUT RASMAN_PORTINFO** ppPortInfo,
OUT RAS_PARAMS** ppParam )
/* Loads callers '*ppParam' with the address of a RAS_PARAM block
** associated with key 'pszKey', or NULL if none. 'ppPortInfo' is the
** address of the array of RAS_PARAMS containing the found 'pparam'.
**
** Returns 0 if successful, otherwise a non-0 error code. If successful,
** it is the caller's responsibility to Free the returned '*ppPortInfo'.
*/
{
DWORD dwErr = 0;
DWORD dwSize = 0;
INT i;
TRACE("GetRasPortParam");
*ppPortInfo = NULL;
do
{
ASSERT(g_pRasPortGetInfo);
TRACE("RasPortGetInfo");
dwErr = g_pRasPortGetInfo(NULL, hport, NULL, &dwSize );
TRACE2("RasPortGetInfo=%d,s=%d",dwErr,(INT)dwSize);
if (dwErr != ERROR_BUFFER_TOO_SMALL && dwErr != 0)
break;
/* So it will fall thru and be "not found".
*/
if (dwSize == 0)
dwSize = 1;
*ppPortInfo = (RASMAN_PORTINFO* )Malloc( dwSize );
if (!*ppPortInfo)
return ERROR_NOT_ENOUGH_MEMORY;
TRACE("RasPortGetInfo");
dwErr = g_pRasPortGetInfo(NULL, hport, (PBYTE )*ppPortInfo, &dwSize );
TRACE2("RasPortGetInfo=%d,s=%d",dwErr,(INT)dwSize);
if (dwErr != 0)
break;
for (i = 0, *ppParam = (*ppPortInfo)->PI_Params;
i < (INT )(*ppPortInfo)->PI_NumOfParams;
++i, ++(*ppParam))
{
if (lstrcmpiA( (*ppParam)->P_Key, pszKey ) == 0)
break;
}
if (i >= (INT )(*ppPortInfo)->PI_NumOfParams)
dwErr = ERROR_KEY_NOT_FOUND;
}
while (FALSE);
return dwErr;
}
DWORD
GetRasPorts(
IN HANDLE hConnection,
OUT RASMAN_PORT** ppPorts,
OUT DWORD* pdwEntries )
/* Enumerate RAS ports. Sets '*ppPort' to the address of a heap memory
** block containing an array of PORT structures with '*pwEntries'
** elements.
**
** Returns 0 if successful, otherwise a non-0 error code. If successful,
** it is the caller's responsibility to free the returned memory block.
*/
{
DWORD dwSize = 0;
DWORD dwErr;
TRACE("GetRasPorts");
#if DUMMYPORTS
{
RASMAN_PORT* pPort;
DWORD c;
TRACE("TEST: Fake ISDN ports");
*pdwEntries = c = g_cPorts;
dwSize = *pdwEntries * sizeof(RASMAN_PORT);
*ppPorts = (RASMAN_PORT* )Malloc( dwSize );
if (!*ppPorts)
return ERROR_NOT_ENOUGH_MEMORY;
do
{
pPort = *ppPorts;
ZeroMemory( pPort, sizeof(*pPort) );
lstrcpyA( pPort->P_PortName, "COM1" );
pPort->P_Status = CLOSED;
pPort->P_ConfiguredUsage = CALL_OUT;
pPort->P_CurrentUsage = CALL_OUT;
lstrcpyA( pPort->P_MediaName, "rasser" );
lstrcpyA( pPort->P_DeviceName, "US Robotics Courier V32 bis" );
lstrcpyA( pPort->P_DeviceType, "MODEM" );
if (--c == 0)
break;
++pPort;
ZeroMemory( pPort, sizeof(*pPort) );
lstrcpyA( pPort->P_PortName, "ISDN1" );
pPort->P_Status = CLOSED;
pPort->P_ConfiguredUsage = CALL_OUT;
pPort->P_CurrentUsage = CALL_OUT;
lstrcpyA( pPort->P_MediaName, "rastapi" );
lstrcpyA( pPort->P_DeviceName, "Digiboard PCIMac ISDN adapter" );
lstrcpyA( pPort->P_DeviceType, "ISDN" );
if (--c == 0)
break;
++pPort;
ZeroMemory( pPort, sizeof(*pPort) );
lstrcpyA( pPort->P_PortName, "ISDN2" );
pPort->P_Status = CLOSED;
pPort->P_ConfiguredUsage = CALL_OUT;
pPort->P_CurrentUsage = CALL_OUT;
lstrcpyA( pPort->P_MediaName, "rastapi" );
lstrcpyA( pPort->P_DeviceName, "Digiboard PCIMac ISDN adapter" );
lstrcpyA( pPort->P_DeviceType, "ISDN" );
if (--c == 0)
break;
++pPort;
ZeroMemory( pPort, sizeof(*pPort) );
lstrcpyA( pPort->P_PortName, "COM500" );
pPort->P_Status = CLOSED;
pPort->P_ConfiguredUsage = CALL_OUT;
pPort->P_CurrentUsage = CALL_OUT;
lstrcpyA( pPort->P_MediaName, "rasser" );
lstrcpyA( pPort->P_DeviceName, "Eicon X.PAD" );
lstrcpyA( pPort->P_DeviceType, "PAD" );
if (--c == 0)
break;
++pPort;
ZeroMemory( pPort, sizeof(*pPort) );
lstrcpyA( pPort->P_PortName, "X251" );
pPort->P_Status = CLOSED;
pPort->P_ConfiguredUsage = CALL_OUT;
pPort->P_CurrentUsage = CALL_OUT;
lstrcpyA( pPort->P_MediaName, "rastapi" );
lstrcpyA( pPort->P_DeviceName, "Digiboard X.25 adapter" );
lstrcpyA( pPort->P_DeviceType, "X25" );
if (--c == 0)
break;
++pPort;
ZeroMemory( pPort, sizeof(*pPort) );
lstrcpyA( pPort->P_PortName, "VPN1" );
pPort->P_Status = CLOSED;
pPort->P_ConfiguredUsage = CALL_OUT;
pPort->P_CurrentUsage = CALL_OUT;
lstrcpyA( pPort->P_MediaName, "rastapi" );
lstrcpyA( pPort->P_DeviceName, "RASPPTPM" );
lstrcpyA( pPort->P_DeviceType, "VPN1" );
if (--c == 0)
break;
}
while (FALSE);
}
#else
ASSERT(g_pRasPortEnum);
TRACE("RasPortEnum...");
dwErr = g_pRasPortEnum(hConnection, NULL, &dwSize, pdwEntries );
TRACE2("RasPortEnum=%d,c=%d",dwErr,(INT)*pdwEntries);
if (dwErr == 0)
{
/* No ports to enumerate. Set up to allocate a single byte anyway, so
** things work without lots of special code.
*/
dwSize = 1;
}
else if (dwErr != ERROR_BUFFER_TOO_SMALL)
return dwErr;
*ppPorts = (RASMAN_PORT* )Malloc( dwSize );
if (!*ppPorts)
return ERROR_NOT_ENOUGH_MEMORY;
TRACE("RasPortEnum...");
dwErr = g_pRasPortEnum(hConnection, (PBYTE )*ppPorts, &dwSize, pdwEntries );
TRACE2("RasPortEnum=%d,c=%d",dwErr,(INT)*pdwEntries);
if (dwErr != 0)
{
Free( *ppPorts );
*ppPorts = NULL;
return dwErr;
}
#endif
#if 1 // Verbose trace
{
RASMAN_PORT* pPort;
DWORD i;
for (pPort = *ppPorts, i = 0; i < *pdwEntries; ++i, ++pPort)
{
TRACE4("Port[%d]=%s,DID=$%08x,AID=$%08x",
pPort->P_Handle,pPort->P_PortName,
pPort->P_LineDeviceId,pPort->P_AddressId);
TRACE3(" M=%s,DT=%s,DN=%s",
pPort->P_MediaName,pPort->P_DeviceType,pPort->P_DeviceName);
TRACE3(" S=$%08x,CfgU=$%08x,CurU=$%08x",
pPort->P_Status,pPort->P_ConfiguredUsage,pPort->P_CurrentUsage);
}
}
#endif
return 0;
}
DWORD
GetRasPortString(
IN HPORT hport,
IN CHAR* pszKey,
OUT CHAR** ppszValue,
IN DWORD dwXlate )
/* Loads callers '*ppszValue' with the address of a heap block containing
** a NUL-terminated copy of the value string associated with key 'pszKey'
** on port 'hport'. 'dwXlate' is a bit mask of XLATE_ bits specifying
** translations to be done on the string value.
**
** Returns 0 if successful, otherwise a non-0 error code. If successful,
** it is the caller's responsibility to Free the returned string.
*/
{
RASMAN_PORTINFO* pPortInfo;
RAS_PARAMS* pParam;
DWORD dwErr;
TRACE("GetRasPortString");
dwErr = GetRasPortParam( hport, pszKey, &pPortInfo, &pParam );
*ppszValue = NULL;
if (dwErr == 0)
{
*ppszValue = PszFromRasValue( &pParam->P_Value, dwXlate );
dwErr = (*ppszValue) ? 0 : ERROR_NOT_ENOUGH_MEMORY;
}
Free0( pPortInfo );
return dwErr;
}
DWORD
GetRasSwitches(
IN HANDLE hConnection,
OUT RASMAN_DEVICE** ppDevices,
OUT DWORD* pdwEntries )
/* Fills caller's '*ppDevices' with the address of a heap block containing
** '*pwEntries' switch DEVICE structures.
**
** Returns 0 if successful, otherwise a non-0 error code. If successful,
** it is the caller's responsibility to free the returned memory block.
*/
{
return GetRasDevices( hConnection, MXS_SWITCH_TXT, ppDevices, pdwEntries );
}
DWORD
GetRasUnimodemBlob(
IN HANDLE hConnection,
IN HPORT hport,
IN CHAR* pszDeviceType,
OUT BYTE** ppBlob,
OUT DWORD* pcbBlob )
{
return GetRasUnimodemBlobEx(
hConnection,
hport,
pszDeviceType,
FALSE,
ppBlob,
pcbBlob);
}
DWORD
GetRasUnimodemBlobEx(
IN HANDLE hConnection,
IN HPORT hport,
IN CHAR* pszDeviceType,
IN BOOL fGlobal,
OUT BYTE** ppBlob,
OUT DWORD* pcbBlob )
/* Loads '*ppBlob' and '*pcbBlob' with the sanitized Unimodem blob and
** size associated with 'hport' and 'pszDeviceType'. It is caller's
** responsibility to Free the returned '*ppBlob'.
**
** Returns 0 if successful, or an error code.
*/
{
DWORD dwErr;
BYTE* pBlob;
DWORD cbBlob;
PRASGETDEVCONFIG pFunc;
CHAR* pszFuncName;
cbBlob = 0;
pFunc = (fGlobal) ? g_pRasGetDevConfigEx : g_pRasGetDevConfig;
pszFuncName = (fGlobal) ? "RasGetDevConfigEx" : "RasGetDevConfig";
ASSERT(pFunc);
TRACE(pszFuncName);
dwErr = pFunc(hConnection, hport, pszDeviceType, NULL, &cbBlob );
TRACE2("%s=%d", pszFuncName, dwErr);
if (dwErr != 0 && dwErr != ERROR_BUFFER_TOO_SMALL)
return dwErr;
if (cbBlob > 0)
{
pBlob = Malloc( cbBlob );
if (!pBlob)
return ERROR_NOT_ENOUGH_MEMORY;
TRACE(pszFuncName);
dwErr = pFunc(hConnection, hport, pszDeviceType, pBlob, &cbBlob );
TRACE2("%s=%d", pszFuncName, dwErr);
if (dwErr != 0)
{
Free( pBlob );
return dwErr;
}
SanitizeUnimodemBlob( pBlob );
}
else
pBlob = NULL;
*ppBlob = pBlob;
*pcbBlob = cbBlob;
return dwErr;
}
VOID
GetRasUnimodemInfo(
IN HANDLE hConnection,
IN HPORT hport,
IN CHAR* pszDeviceType,
OUT UNIMODEMINFO* pInfo )
/* Loads 'pInfo' with the RAS-relevant information of the port 'hport'
** with device name 'pszDeviceName'.
*/
{
DWORD dwErr;
BYTE* pBlob = NULL;
DWORD cbBlob = 0;
SetDefaultUnimodemInfo( pInfo );
dwErr = GetRasUnimodemBlob(
hConnection,
hport,
pszDeviceType,
&pBlob,
&cbBlob );
if (dwErr == 0 && cbBlob > 0)
UnimodemInfoFromBlob( pBlob, pInfo );
Free0( pBlob );
}
TCHAR*
GetRasX25Diagnostic(
IN HRASCONN hrasconn )
/* Returns the X.25 diagnostics string or NULL if none. It is caller's
** responsibility to Free the returned string.
*/
{
DWORD dwErr;
HPORT hport;
RASMAN_INFO info;
CHAR* pszDiagnosticA = NULL;
TCHAR* pszDiagnostic = NULL;
pszDiagnosticA = NULL;
hport = g_pRasGetHport( hrasconn );
ASSERT(g_pRasGetInfo);
TRACE1("RasGetInfo(%d)",hport);
dwErr = g_pRasGetInfo( NULL, hport, &info );
TRACE1("RasGetInfo=%d",dwErr);
/* Error codes are ignored here since the diagnosistic
** is informational only. If they fail the diagnostic
** will simply appear blank.
*/
if (dwErr == 0)
{
GetRasDeviceString(
hport, info.RI_DeviceTypeConnecting,
info.RI_DeviceConnecting, MXS_DIAGNOSTICS_KEY,
&pszDiagnosticA, XLATE_Diagnostic );
}
if(NULL != pszDiagnosticA)
{
pszDiagnostic = StrDupTFromA( pszDiagnosticA );
Free( pszDiagnosticA );
}
return pszDiagnostic;
}
BOOL
IsRasdevBundled(
IN RASDEV* pdev,
IN RASDEV* pDevTable,
IN DWORD iDevCount
)
/* Determines whether the device described by 'pdev' is bundled,
** by looking for another device in 'pDevTable' which has the same bundle
** as 'pdev'.
**
** Returnes TRUE if the device is bundled, FALSE otherwise.
*/
{
DWORD i;
RASDEV* pdev2;
DWORD dwBundle;
//
// First get the device's bundle;
// If this fails, assume it is not connected and return FALSE.
//
if (GetRasdevBundle(pdev, &dwBundle) != NO_ERROR) { return FALSE; }
//
// Walk through the other devices in the table, looking for one
// with the same bundle.
//
for (i = 0, pdev2 = pDevTable;
i < iDevCount; i++, pdev2++) {
DWORD dwBundle2;
//
// skip this if it is the device we already know about
//
if (pdev->RD_Handle == pdev2->RD_Handle) { continue; }
//
// get the bundle
//
if (GetRasdevBundle(pdev2, &dwBundle2) != NO_ERROR) { continue; }
//
// if the bundle is the same, we know its multilinked
//
if (dwBundle == dwBundle2) { return TRUE; }
}
return FALSE;
}
CHAR*
PszFromRasValue(
IN RAS_VALUE* prasvalue,
IN DWORD dwXlate )
/* Returns the address of a heap block containing a NUL-terminated string
** value from caller's '*prasvalue', or NULL if out of memory. 'dwXlate'
** is a bit mask of XLATE_ bits specifying translations to be performed on
** the string. The value is assumed to be of format String. It is
** translated to modem.inf style.
*/
{
#define MAXEXPANDPERCHAR 5
#define HEXCHARS "0123456789ABCDEF"
INT i;
BOOL fXlate;
BOOL fXlateCtrl;
BOOL fXlateCr;
BOOL fXlateCrSpecial;
BOOL fXlateLf;
BOOL fXlateLfSpecial;
BOOL fXlateLAngle;
BOOL fXlateRAngle;
BOOL fXlateBSlash;
BOOL fXlateSSpace;
BOOL fNoCharSinceLf;
INT nLen;
CHAR* pszIn = NULL;
CHAR* pszBuf = NULL;
CHAR* pszOut = NULL;
CHAR* pszTemp = NULL;
nLen = prasvalue->String.Length;
pszIn = prasvalue->String.Data;
pszBuf = Malloc( (nLen * MAXEXPANDPERCHAR) + 1 );
if (!pszBuf)
return NULL;
/* Translate the returned string based on the translation bit map. The
** assumption here is that all these devices talk ASCII and not some
** localized ANSI.
*/
fXlate = (dwXlate != 0);
fXlateCtrl = (dwXlate & XLATE_Ctrl);
fXlateCr = (dwXlate & XLATE_Cr);
fXlateCrSpecial = (dwXlate & XLATE_CrSpecial);
fXlateLf = (dwXlate & XLATE_Lf);
fXlateLfSpecial = (dwXlate & XLATE_LfSpecial);
fXlateLAngle = (dwXlate & XLATE_LAngle);
fXlateRAngle = (dwXlate & XLATE_RAngle);
fXlateBSlash = (dwXlate & XLATE_BSlash);
fXlateSSpace = (dwXlate & XLATE_SSpace);
pszOut = pszBuf;
fNoCharSinceLf = TRUE;
for (i = 0; i < nLen; ++i)
{
CHAR ch = pszIn[ i ];
if (fXlate)
{
if (ch == 0x0D)
{
if (fXlateSSpace && fNoCharSinceLf)
continue;
if (fXlateCrSpecial)
{
/* Special symbol for carriage return.
*/
lstrcpyA( pszOut, "<cr>" );
pszOut += 4;
continue;
}
}
if (ch == 0x0A)
{
if (fXlateSSpace && fNoCharSinceLf)
continue;
fNoCharSinceLf = TRUE;
if (fXlateLfSpecial)
{
/* Special symbol for line feed.
*/
lstrcpyA( pszOut, "<lf>" );
pszOut += 4;
continue;
}
}
if (ch != 0x0A && ch != 0x0D)
fNoCharSinceLf = FALSE;
if ((((ch < 0x20 || ch > 0x7E)
&& ch != 0x0D && ch != 0x0A) && fXlateCtrl)
|| (ch == 0x0D && fXlateCr)
|| (ch == 0x0A && fXlateLf)
|| (ch == 0x3C && fXlateLAngle)
|| (ch == 0x3E && fXlateRAngle)
|| (ch == 0x5C && fXlateBSlash))
{
/* Expand to "dump" form, i.e. <hFF> where FF is the hex value
** of the character.
*/
*pszOut++ = '<';
*pszOut++ = 'h';
*pszOut++ = HEXCHARS[ ch / 16 ];
*pszOut++ = HEXCHARS[ ch % 16 ];
*pszOut++ = '>';
continue;
}
}
/* Just copy without translation.
*/
*pszOut++ = ch;
}
*pszOut = '\0';
// For whistler 517011
//
pszTemp = Realloc( pszBuf, lstrlenA( pszBuf ) + 1 );
if(pszTemp)
{
pszBuf = pszTemp;
}
else
{
Free(pszBuf);
pszBuf = NULL;
}
return pszBuf;
}
VOID
SanitizeUnimodemBlob(
IN OUT BYTE* pBlob )
/* Fix non-RAS-compatible settings in unimodem blob 'pBlob'.
**
** (Based on Gurdeepian routine)
*/
{
DEVCFG* pDevCfg;
MODEMSETTINGS* pModemSettings;
RAS_DEVCONFIG* pRasDevCfg;
pRasDevCfg = (RAS_DEVCONFIG*)pBlob;
pDevCfg = (DEVCFG *)
((PBYTE) pRasDevCfg + pRasDevCfg->dwOffsetofModemSettings);
pModemSettings = (MODEMSETTINGS* )(((BYTE* )&pDevCfg->commconfig)
+ pDevCfg->commconfig.dwProviderOffset);
TRACE1(
"SanitizeUnimodemBlob: mdm prot=%d",
MDM_GET_EXTENDEDINFO(pModemSettings->dwPreferredModemOptions));
/* No unimodem service provider pre/post-connect terminal, operator dial,
** or tray lights. RAS does these itself.
*/
pDevCfg->dfgHdr.fwOptions = 0;
pDevCfg->commconfig.dcb.fBinary = TRUE;
pDevCfg->commconfig.dcb.fParity = TRUE;
pDevCfg->commconfig.dcb.fOutxDsrFlow = FALSE;
pDevCfg->commconfig.dcb.fDtrControl = DTR_CONTROL_ENABLE;
pDevCfg->commconfig.dcb.fTXContinueOnXoff = FALSE;
pDevCfg->commconfig.dcb.fOutX = FALSE;
pDevCfg->commconfig.dcb.fInX = FALSE;
pDevCfg->commconfig.dcb.fErrorChar = FALSE;
pDevCfg->commconfig.dcb.fNull = FALSE;
pDevCfg->commconfig.dcb.fAbortOnError = FALSE;
pDevCfg->commconfig.dcb.ByteSize = 8;
pDevCfg->commconfig.dcb.Parity = NOPARITY;
pDevCfg->commconfig.dcb.StopBits = ONESTOPBIT;
/* Wait 55 seconds to establish call.
*/
/*
pModemSettings->dwCallSetupFailTimer = 55;
*/
/* Disable inactivity timeout.
*/
pModemSettings->dwInactivityTimeout = 0;
}
VOID
SetDefaultUnimodemInfo(
OUT UNIMODEMINFO* pInfo )
/* Sets 'pInfo' to default settings.
*/
{
pInfo->fHwFlow = FALSE;
pInfo->fEc = FALSE;
pInfo->fEcc = FALSE;
pInfo->dwBps = 9600;
pInfo->fSpeaker = TRUE;
pInfo->fOperatorDial = FALSE;
pInfo->fUnimodemPreTerminal = FALSE;
}
VOID
UnimodemProtInfoFromExtendedCaps(
OUT UNIMODEMINFO* pInfo,
IN BYTE* pExtCapsBlob)
/* Loads the modem protocol info for 'pInfo' from the extended caps
** blob retrieved from tapi.
**
*/
{
MODEM_PROTOCOL_CAPS* lpProtCaps = NULL;
PROTOCOL_ITEM* pProtItem = NULL;
DWORD dwIndex;
do
{
// Extract the modem caps
//
lpProtCaps = (MODEM_PROTOCOL_CAPS *)pExtCapsBlob;
if (lpProtCaps->hdr.dwSig != dwSIG_MODEM_PROTOCOL_CAPS ||
lpProtCaps->dwNumProtocols == 0 ||
lpProtCaps->dwProtocolListOffset == 0)
{
break;
}
// If no protocols are supported, don't bother creating the
// list
if (lpProtCaps->dwNumProtocols == 0)
{
break;
}
// Create the list
//
pInfo->pListProtocols = DtlCreateList(0);
if (pInfo->pListProtocols == NULL)
{
break;
}
// Get the list of supported protocols
//
pProtItem = (PROTOCOL_ITEM*)
(((LPBYTE)lpProtCaps) + lpProtCaps->dwProtocolListOffset);
// Enumerate the protocols
//
for (dwIndex = 0;
dwIndex < lpProtCaps->dwNumProtocols;
dwIndex++, pProtItem++)
{
DTLNODE * pNode = NULL;
PWCHAR pszName = NULL;
DWORD dwSize;
// Get the friendly name from the structure
//
pszName = (PWCHAR)
(pExtCapsBlob + pProtItem->dwProtocolNameOffset);
if (pszName == NULL)
{
continue;
}
// Calculate the size of the friendly name
//
dwSize = (wcslen(pszName) + 1) * sizeof(WCHAR);
// Allocate a node accordingly
//
pNode =
DtlCreateSizedNode(dwSize, (LONG_PTR)pProtItem->dwProtocol);
if (pNode == NULL)
{
continue;
}
// Initialize the node and add it to the list
//
wcscpy((PWCHAR) DtlGetData(pNode), pszName);
DtlAddNodeLast(pInfo->pListProtocols, pNode);
}
} while (FALSE);
// Cleanup
{
}
}
VOID
UnimodemInfoFromBlob(
IN BYTE* pBlob,
OUT UNIMODEMINFO* pInfo )
/* Loads 'pInfo' with RAS-relevant Unimodem information retrieved from
** Unimodem blob 'pBlob'.
**
** (Based on Gurdeepian routine)
*/
{
DEVCFG* pDevCfg;
MODEMSETTINGS* pModemSettings;
RAS_DEVCONFIG* pRasDevCfg;
pRasDevCfg = (RAS_DEVCONFIG*)pBlob;
pDevCfg = (DEVCFG *)
((PBYTE) pRasDevCfg + pRasDevCfg->dwOffsetofModemSettings);
pModemSettings = (MODEMSETTINGS* )(((BYTE* )&pDevCfg->commconfig)
+ pDevCfg->commconfig.dwProviderOffset);
pInfo->fSpeaker =
(pModemSettings->dwSpeakerMode != MDMSPKR_OFF)
? TRUE : FALSE;
pInfo->fHwFlow =
(pModemSettings->dwPreferredModemOptions & MDM_FLOWCONTROL_HARD)
? TRUE : FALSE;
pInfo->fEcc =
(pModemSettings->dwPreferredModemOptions & MDM_COMPRESSION)
? TRUE : FALSE;
pInfo->fEc =
(pModemSettings->dwPreferredModemOptions & MDM_ERROR_CONTROL)
? TRUE : FALSE;
pInfo->dwBps = pDevCfg->commconfig.dcb.BaudRate;
pInfo->fOperatorDial =
(pDevCfg->dfgHdr.fwOptions & MANUAL_DIAL)
? TRUE : FALSE;
pInfo->fUnimodemPreTerminal =
(pDevCfg->dfgHdr.fwOptions & TERMINAL_PRE)
? TRUE : FALSE;
// Get the modem protocol
//
pInfo->dwModemProtocol =
MDM_GET_EXTENDEDINFO(pModemSettings->dwPreferredModemOptions);
// Pull out the extended caps stuff
//
if ( pRasDevCfg->dwSizeofExtendedCaps )
{
UnimodemProtInfoFromExtendedCaps(
pInfo,
(BYTE*)(pBlob + pRasDevCfg->dwOffsetofExtendedCaps));
}
else
{
pInfo->pListProtocols = NULL;
}
}
VOID
UnimodemInfoToBlob(
IN UNIMODEMINFO* pInfo,
IN OUT BYTE* pBlob )
/* Applies RAS-relevant Unimodem information supplied in 'pInfo' to
** Unimodem blob 'pBlob'.
**
** (Based on Gurdeepian routine)
*/
{
DEVCFG* pDevCfg;
MODEMSETTINGS* pModemSettings;
RAS_DEVCONFIG* pRasDevCfg;
pRasDevCfg = (RAS_DEVCONFIG*) pBlob;
// Pull out the device config stuff
//
pDevCfg = (DEVCFG *)
((PBYTE) pRasDevCfg + pRasDevCfg->dwOffsetofModemSettings);
pModemSettings = (MODEMSETTINGS* )(((BYTE* )&pDevCfg->commconfig)
+ pDevCfg->commconfig.dwProviderOffset);
pModemSettings->dwSpeakerMode =
(pInfo->fSpeaker) ? MDMSPKR_DIAL : MDMSPKR_OFF;
if (pInfo->fHwFlow)
{
pDevCfg->commconfig.dcb.fOutxCtsFlow = TRUE;
pDevCfg->commconfig.dcb.fRtsControl = RTS_CONTROL_HANDSHAKE;
pModemSettings->dwPreferredModemOptions |= MDM_FLOWCONTROL_HARD;
}
else
{
pDevCfg->commconfig.dcb.fOutxCtsFlow = FALSE;
pDevCfg->commconfig.dcb.fRtsControl = RTS_CONTROL_DISABLE;
pModemSettings->dwPreferredModemOptions &= ~(MDM_FLOWCONTROL_HARD);
}
if (pInfo->fEc)
pModemSettings->dwPreferredModemOptions |= MDM_ERROR_CONTROL;
else
pModemSettings->dwPreferredModemOptions &= ~(MDM_ERROR_CONTROL);
if (pInfo->fEcc)
pModemSettings->dwPreferredModemOptions |= MDM_COMPRESSION;
else
pModemSettings->dwPreferredModemOptions &= ~(MDM_COMPRESSION);
pDevCfg->commconfig.dcb.BaudRate = pInfo->dwBps;
if (pInfo->fOperatorDial)
pDevCfg->dfgHdr.fwOptions |= MANUAL_DIAL;
if (pInfo->fUnimodemPreTerminal)
pDevCfg->dfgHdr.fwOptions |= TERMINAL_PRE;
// Set the modem protocol
//
MDM_SET_EXTENDEDINFO(
pModemSettings->dwPreferredModemOptions,
pInfo->dwModemProtocol);
}
WCHAR *GetUnicodeName(HPORT hport)
{
WCHAR *pwsz = Malloc(sizeof(WCHAR) * (MAX_DEVICE_NAME + 1));
if(NULL != pwsz)
{
if(ERROR_SUCCESS != RasGetUnicodeDeviceName(
hport,
pwsz))
{
Free(pwsz);
pwsz = NULL;
}
}
return pwsz;
}