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.
 
 
 
 
 
 

642 lines
21 KiB

//+---------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1997.
//
// File: S M R A S . C P P
//
// Contents: The RAS engine that provides statistics to the status monitor
//
// Notes:
//
// Author: CWill 12/02/1997
//
//----------------------------------------------------------------------------
#include "pch.h"
#pragma hdrstop
#include "ncras.h"
#include "sminc.h"
#include "netcon.h"
#include "smpsh.h"
#include "mprapi.h"
//+---------------------------------------------------------------------------
//
// Member: CRasStatEngine::CRasStatEngine
//
// Purpose: Creator
//
// Arguments: None
//
// Returns: Nil
//
CRasStatEngine::CRasStatEngine() :
m_hRasConn(NULL)
{
m_ncmType = NCM_PHONE;
m_dwCharacter = NCCF_OUTGOING_ONLY;
return;
}
//+---------------------------------------------------------------------------
//
// Member: CRasStatEngine::put_RasConn
//
// Purpose: Pass handles to the RAS engine
//
// Arguments: hRasConn - The handle being set
//
// Returns: Error code
//
VOID CRasStatEngine::put_RasConn(HRASCONN hRasConn)
{
AssertSz(hRasConn, "We should have a hRasConn");
m_hRasConn = hRasConn;
}
//+---------------------------------------------------------------------------
//
// Member: CRasStatEngine::put_MediaType
//
// Purpose: Pass media type of RAS connection type to the RAS engine
//
// Arguments: ncmType - NETCON_MEDIATYPE being set
// ncsmType - NETCON_SUBMEDIATYPE being set
//
// Returns:
//
VOID CRasStatEngine::put_MediaType(NETCON_MEDIATYPE ncmType, NETCON_SUBMEDIATYPE ncsmType)
{
m_ncmType = ncmType;
m_ncsmType = ncsmType;
}
//+---------------------------------------------------------------------------
//
// Member: CRasStatEngine::put_Character
//
// Purpose: Character of RAS connection
//
// Arguments: dwCharacter - The character being set
//
// Returns:
//
VOID CRasStatEngine::put_Character(DWORD dwCharacter)
{
m_dwCharacter = dwCharacter;
}
//+---------------------------------------------------------------------------
//
// Member: CRasStatEngine::HrUpdateData
//
// Purpose: Get new statistics from the devices. This data is used to be
// displayed in the UI.
//
// Arguments: pdwChangeFlags - Where to return for statistics
//
// Returns: Error code
//
HRESULT
CRasStatEngine::HrUpdateData (
DWORD* pdwChangeFlags,
BOOL* pfNoLongerConnected)
{
HRESULT hr = S_OK;
// Initialize the output parameters.
//
if (pdwChangeFlags)
{
*pdwChangeFlags = SMDCF_NULL;
}
*pfNoLongerConnected = FALSE;
CExceptionSafeComObjectLock EsLock(this);
// Get a pointer to the elements of the array.
//
if (m_dwCharacter & NCCF_OUTGOING_ONLY)
{
// Get the status of the connection.
//
NETCON_STATUS ncs;
hr = HrRasGetNetconStatusFromRasConnectStatus (
m_hRasConn, &ncs);
// Make sure we have a statistics structure
//
EnterCriticalSection(&g_csStatmonData);
if (!m_psmEngineData)
{
m_psmEngineData = new STATMON_ENGINEDATA;
if (m_psmEngineData)
{
ZeroMemory(m_psmEngineData, sizeof(STATMON_ENGINEDATA));
}
}
// Set the status
//
if (m_psmEngineData)
{
if (SUCCEEDED(hr) && (NCS_DISCONNECTED != ncs))
{
m_psmEngineData->SMED_CONNECTIONSTATUS = ncs;
}
else if (HRESULT_FROM_WIN32(ERROR_INVALID_HANDLE) == hr)
{
*pfNoLongerConnected = TRUE;
// set the connection status to "disconnected" so we can close the UI
m_psmEngineData->SMED_CONNECTIONSTATUS = NCS_DISCONNECTED;
hr = S_OK;
}
}
else
{
hr = E_OUTOFMEMORY;
}
LeaveCriticalSection(&g_csStatmonData);
if ((m_psmEngineData) && SUCCEEDED(hr) && (NCS_DISCONNECTED != ncs))
{
// Retrieve the statistics of the connection
//
RAS_STATS rsNewData;
rsNewData.dwSize = sizeof(RAS_STATS);
DWORD dwErr = RasGetConnectionStatistics(m_hRasConn, &rsNewData);
hr = HRESULT_FROM_WIN32 (dwErr);
TraceError ("RasGetConnectionStatistics", hr);
if (SUCCEEDED(hr))
{
// Update the change flags if asked for
//
if (pdwChangeFlags)
{
if (m_psmEngineData->SMED_PACKETSTRANSMITTING
!= rsNewData.dwFramesXmited)
{
*pdwChangeFlags |= SMDCF_TRANSMITTING;
}
if (m_psmEngineData->SMED_PACKETSRECEIVING
!= rsNewData.dwFramesRcved)
{
*pdwChangeFlags |= SMDCF_RECEIVING;
}
}
// Get the rest of the data
//
m_psmEngineData->SMED_DURATION = rsNewData.dwConnectDuration/1000;
// Don't pass out speed info for VPN connections (294953)
if (NCM_TUNNEL != m_ncmType)
{
m_psmEngineData->SMED_SPEEDTRANSMITTING = rsNewData.dwBps;
m_psmEngineData->SMED_SPEEDRECEIVING = rsNewData.dwBps;
}
m_psmEngineData->SMED_BYTESTRANSMITTING = rsNewData.dwBytesXmited;
m_psmEngineData->SMED_BYTESRECEIVING = rsNewData.dwBytesRcved;
m_psmEngineData->SMED_COMPRESSIONTRANSMITTING = rsNewData.dwCompressionRatioOut;
m_psmEngineData->SMED_COMPRESSIONRECEIVING = rsNewData.dwCompressionRatioIn;
m_psmEngineData->SMED_ERRORSTRANSMITTING = 0;
m_psmEngineData->SMED_ERRORSRECEIVING = rsNewData.dwCrcErr +
rsNewData.dwTimeoutErr +
rsNewData.dwAlignmentErr +
rsNewData.dwHardwareOverrunErr +
rsNewData.dwFramingErr +
rsNewData.dwBufferOverrunErr;
m_psmEngineData->SMED_PACKETSTRANSMITTING = rsNewData.dwFramesXmited;
m_psmEngineData->SMED_PACKETSRECEIVING = rsNewData.dwFramesRcved;
HrGetAutoNetSetting(m_guidId, &(m_psmEngineData->SMED_DHCP_ADDRESS_TYPE) );
m_psmEngineData->SMED_INFRASTRUCTURE_MODE = IM_NOT_SUPPORTED;
}
}
}
else if (m_dwCharacter & NCCF_INCOMING_ONLY)
{
// RAS inbound connection
EnterCriticalSection(&g_csStatmonData);
if (!m_psmEngineData)
{
m_psmEngineData = new STATMON_ENGINEDATA;
if(m_psmEngineData)
{
ZeroMemory(m_psmEngineData, sizeof(STATMON_ENGINEDATA));
}
}
// Set the status
//
if (m_psmEngineData)
{
// Set the status to connected by default
// Unless we get ERROR_INVALID_PARAMETER on any of the function calls below
//
m_psmEngineData->SMED_CONNECTIONSTATUS = NCS_CONNECTED;
}
else
{
hr = E_OUTOFMEMORY;
}
LeaveCriticalSection(&g_csStatmonData);
if (SUCCEEDED(hr) && m_psmEngineData)
{
// Get the server handle
//
RAS_SERVER_HANDLE hMprAdmin;
DWORD dwError = MprAdminServerConnect(NULL, &hMprAdmin);
if (dwError == NO_ERROR)
{
// Get connection duration
//
RAS_CONNECTION_0 * pConn0;
dwError = MprAdminConnectionGetInfo(hMprAdmin,
0,
m_hRasConn,
(LPBYTE*)&pConn0);
if (dwError == NO_ERROR)
{
// duration needs to be in milliseconds
m_psmEngineData->SMED_DURATION = pConn0->dwConnectDuration;
MprAdminBufferFree(pConn0);
// Get connection speed
// Don't pass out speed info for VPN connections (357758)
if (NCM_TUNNEL != m_ncmType)
{
// Enum all the ports and add up the link speed
//
RAS_PORT_0 * pPort0;
DWORD dwPortCount;
DWORD dwTotalEntries;
dwError = MprAdminPortEnum (hMprAdmin,
0,
m_hRasConn,
(LPBYTE*)&pPort0,
-1,
&dwPortCount,
&dwTotalEntries,
NULL);
if (dwError == NOERROR)
{
RAS_PORT_0 * pCurPort0 = pPort0;
DWORD dwConnSpeed=0;
while (dwPortCount)
{
RAS_PORT_1 * pCurPort1;
dwError = MprAdminPortGetInfo(hMprAdmin,
1,
pCurPort0->hPort,
(LPBYTE*)&pCurPort1);
if (dwError == NO_ERROR)
{
dwConnSpeed += pCurPort1->dwLineSpeed;
}
else
{
break;
}
MprAdminBufferFree(pCurPort1);
dwPortCount--;
pCurPort0++;
}
MprAdminBufferFree(pPort0);
if (dwError == NO_ERROR)
{
// Get the accumulated connection speed
m_psmEngineData->SMED_SPEEDTRANSMITTING = dwConnSpeed;
m_psmEngineData->SMED_SPEEDRECEIVING = dwConnSpeed;
}
}
}
if (dwError == NO_ERROR)
{
// Get Transmitted\Received Bytes, Compression and Bytes
RAS_CONNECTION_1 * pConn1;
dwError = MprAdminConnectionGetInfo(hMprAdmin,
1,
m_hRasConn,
(LPBYTE*)&pConn1);
if (dwError == NO_ERROR)
{
// Update the change flags if asked for
//
if (pdwChangeFlags)
{
if (m_psmEngineData->SMED_BYTESTRANSMITTING
!= pConn1->dwBytesXmited)
{
*pdwChangeFlags |= SMDCF_TRANSMITTING;
}
if (m_psmEngineData->SMED_BYTESRECEIVING
!= pConn1->dwBytesRcved)
{
*pdwChangeFlags |= SMDCF_RECEIVING;
}
}
m_psmEngineData->SMED_BYTESTRANSMITTING = pConn1->dwBytesXmited;
m_psmEngineData->SMED_BYTESRECEIVING = pConn1->dwBytesRcved;
m_psmEngineData->SMED_COMPRESSIONTRANSMITTING = pConn1->dwCompressionRatioOut;
m_psmEngineData->SMED_COMPRESSIONRECEIVING = pConn1->dwCompressionRatioIn;
m_psmEngineData->SMED_ERRORSTRANSMITTING = 0;
m_psmEngineData->SMED_ERRORSRECEIVING = pConn1->dwCrcErr +
pConn1->dwTimeoutErr +
pConn1->dwAlignmentErr +
pConn1->dwHardwareOverrunErr +
pConn1->dwFramingErr +
pConn1->dwBufferOverrunErr;
}
MprAdminBufferFree(pConn1);
}
}
if (dwError != NO_ERROR)
{
*pfNoLongerConnected = TRUE;
// set the connection status to "disconnected" so we can close the UI
m_psmEngineData->SMED_CONNECTIONSTATUS = NCS_DISCONNECTED;
hr = S_OK;
}
}
MprAdminServerDisconnect (hMprAdmin);
}
}
TraceError("CRasStatEngine::HrUpdateData", hr);
return hr;
}
//////////////////////////////////////////////////////////////////////////////
// //
// CPspRasGen //
// //
//////////////////////////////////////////////////////////////////////////////
CPspRasGen::CPspRasGen(VOID)
{
m_ncmType = NCM_PHONE;
m_dwCharacter = NCCF_OUTGOING_ONLY;
m_adwHelpIDs = NULL;
}
//+---------------------------------------------------------------------------
//
// Member: CPspRasGen::put_MediaType
//
// Purpose: Pass media type of RAS connection type to the RAS engine
//
// Arguments: ncmType - NETCON_MEDIATYPE being set
// ncsmType - NETCON_SUBMEDIATYPE being set
//
// Returns:
//
VOID CPspRasGen::put_MediaType(NETCON_MEDIATYPE ncmType, NETCON_SUBMEDIATYPE ncsmType)
{
m_ncmType = ncmType;
m_ncsmType = ncsmType;
}
VOID CPspRasGen::put_Character(DWORD dwCharacter)
{
m_dwCharacter = dwCharacter;
}
//////////////////////////////////////////////////////////////////////////////
// //
// CPspRasTool //
// //
//////////////////////////////////////////////////////////////////////////////
CPspRasTool::CPspRasTool(VOID)
{
m_ncmType = NCM_PHONE;
m_dwCharacter = NCCF_OUTGOING_ONLY;
m_adwHelpIDs = NULL;
}
VOID CPspRasTool::put_MediaType(NETCON_MEDIATYPE ncmType, NETCON_SUBMEDIATYPE ncsmType)
{
m_ncmType = ncmType;
m_ncsmType = ncsmType;
}
VOID CPspRasTool::put_Character(DWORD dwCharacter)
{
m_dwCharacter = dwCharacter;
}
//+---------------------------------------------------------------------------
//
// Member: CPspRasTool::HrInitToolPageType
//
// Purpose: Gets from the connection any information that is relevant to
// this particular connection type.
//
// Arguments: pncInit - The connection assocatied with this dialog
//
// Returns: Error code
//
HRESULT CPspRasTool::HrInitToolPageType(INetConnection* pncInit)
{
HRESULT hr = S_OK;
TraceError("CPspRasTool::HrInitToolPageType", hr);
return hr;
}
//+---------------------------------------------------------------------------
//
// Member: CPspRasTool::HrAddCommandLineFlags
//
// Purpose: Adds the flags for this selection to the command line for the
// tool being launched.
//
// Arguments: pstrFlags - The command line that the flags have to be
// appended to
// psmteSel - The tool entry associated with this selection
//
// Returns: Error code
//
HRESULT CPspRasTool::HrAddCommandLineFlags(tstring* pstrFlags,
CStatMonToolEntry* psmteSel)
{
HRESULT hr = S_OK;
//
// Check what flags are asked for and provide them if we can
//
TraceError("CPspRasTool::HrAddCommandLineFlags", hr);
return hr;
}
HRESULT CPspRasTool::HrGetDeviceType(INetConnection* pncInit)
{
HRESULT hr = S_OK;
RASCONN* aRasConn;
DWORD cRasConn;
hr = HrRasEnumAllActiveConnections (
&aRasConn,
&cRasConn);
if (SUCCEEDED(hr))
{
for (DWORD i = 0; i < cRasConn; i++)
{
if (m_guidId == aRasConn[i].guidEntry)
{
// Note: device types in RAS connections are defined
// as follows in public\sdk\inc ras.h as RASDT_XXX
m_strDeviceType = aRasConn[i].szDeviceType;
break;
}
}
MemFree (aRasConn);
}
return S_OK;
}
HRESULT CPspRasTool::HrGetComponentList(INetConnection* pncInit)
{
// Obtain ras handle to this connection
HRESULT hr = S_OK;
HRASCONN hRasConn = NULL;
if (m_dwCharacter & NCCF_OUTGOING_ONLY)
{
// for outgoing connection
INetRasConnection* pnrcNew = NULL;
hr = HrQIAndSetProxyBlanket(pncInit, &pnrcNew);
if (SUCCEEDED(hr))
{
hr = pnrcNew->GetRasConnectionHandle(
reinterpret_cast<ULONG_PTR*>(&hRasConn));
ReleaseObj(pnrcNew);
}
}
else if (m_dwCharacter & NCCF_INCOMING_ONLY)
{
// for incoming connection
INetInboundConnection* pnicNew;
hr = HrQIAndSetProxyBlanket(pncInit, &pnicNew);
if (SUCCEEDED(hr))
{
hr = pnicNew->GetServerConnectionHandle(
reinterpret_cast<ULONG_PTR*>(&hRasConn));
ReleaseObj(pnicNew);
}
}
if (SUCCEEDED(hr) && hRasConn)
{
// Get protocols list
DWORD dwRetCode;
DWORD dwSize;
// RASP_PppIp
RASPPPIP RasPppIp;
RasPppIp.dwSize = sizeof( RasPppIp );
dwSize = sizeof( RasPppIp );
dwRetCode = RasGetProjectionInfo (hRasConn, RASP_PppIp, &RasPppIp, &dwSize);
if ((dwRetCode == NO_ERROR) && (NO_ERROR == RasPppIp.dwError))
{
m_lstpstrCompIds.push_back(new tstring(L"MS_TCPIP"));
}
// RASP_PppIpx
RASPPPIPX RasPppIpx;
RasPppIpx.dwSize = sizeof( RasPppIpx );
dwSize = sizeof( RasPppIpx );
dwRetCode = RasGetProjectionInfo (hRasConn, RASP_PppIpx, &RasPppIpx, &dwSize);
if ((dwRetCode == NO_ERROR) && (NO_ERROR == RasPppIpx.dwError))
{
m_lstpstrCompIds.push_back(new tstring(L"MS_NWIPX"));
}
// RASP_PppNbf
RASPPPNBF RasPppNbf;
RasPppNbf.dwSize = sizeof( RasPppNbf );
dwSize = sizeof( RasPppNbf );
dwRetCode = RasGetProjectionInfo (hRasConn, RASP_PppNbf, &RasPppNbf, &dwSize);
if ((dwRetCode == NO_ERROR) && (NO_ERROR == RasPppNbf.dwError))
{
m_lstpstrCompIds.push_back(new tstring(L"MS_NetBEUI"));
}
// RASP_Slip
RASSLIP RasSlip;
RasSlip.dwSize = sizeof( RasSlip );
dwSize = sizeof( RasSlip );
dwRetCode = RasGetProjectionInfo (hRasConn, RASP_Slip, &RasSlip, &dwSize);
if ((dwRetCode == NO_ERROR) && (NO_ERROR == RasSlip.dwError))
{
m_lstpstrCompIds.push_back(new tstring(L"MS_TCPIP"));
}
}
// Get client and services
// $REVIEW(tongl 10/19): checked with Rao, for now we hard code
// using MSClient and F&P services for all RAS connections
// (raid #132575)
m_lstpstrCompIds.push_back(new tstring(L"MS_MSCLIENT"));
m_lstpstrCompIds.push_back(new tstring(L"MS_SERVER"));
return S_OK;
}