462 lines
13 KiB
C++
462 lines
13 KiB
C++
//+---------------------------------------------------------------------------
|
|
//
|
|
// Microsoft Windows
|
|
// Copyright (C) Microsoft Corporation, 1998.
|
|
//
|
|
// File: S M U T I L . C P P
|
|
//
|
|
// Contents: Utility functions to help out the status monitor
|
|
//
|
|
// Notes:
|
|
//
|
|
// Author: CWill 2 Dec 1997
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
#include "pch.h"
|
|
#pragma hdrstop
|
|
#include "netcon.h"
|
|
#include "nsres.h"
|
|
#include "sminc.h"
|
|
|
|
const UINT c_uiKilo = 1000;
|
|
const UINT c_cmsSecond = 1;
|
|
const UINT c_cmsMinute = (c_cmsSecond * 60);
|
|
const UINT c_cmsHour = (c_cmsMinute * 60);
|
|
const UINT c_cmsDay = (c_cmsHour * 24);
|
|
|
|
static const WCHAR c_szZero[] = L"0";
|
|
extern const WCHAR c_szSpace[];
|
|
|
|
struct StatusIconMapEntry
|
|
{
|
|
NETCON_MEDIATYPE ncm;
|
|
BOOL fInbound;
|
|
BOOL fTransmitting;
|
|
BOOL fReceiving;
|
|
INT iStatusIcon;
|
|
};
|
|
|
|
static const StatusIconMapEntry c_SIMEArray[] =
|
|
{
|
|
// Mediatype
|
|
// | Inbound
|
|
// | | Transmitting
|
|
// | | | Receiving
|
|
// | | | | 32x32 Status Icon
|
|
// | | | | |
|
|
// v v v v v
|
|
// Dial-up
|
|
NCM_PHONE, FALSE, FALSE, FALSE, IDI_PO_NON_M_16,
|
|
NCM_PHONE, FALSE, FALSE, TRUE, IDI_PO_RCV_M_16,
|
|
NCM_PHONE, FALSE, TRUE, FALSE, IDI_PO_TRN_M_16,
|
|
NCM_PHONE, FALSE, TRUE, TRUE, IDI_PO_CON_M_16,
|
|
NCM_PHONE, TRUE, FALSE, FALSE, IDI_PI_NON_M_16,
|
|
NCM_PHONE, TRUE, FALSE, TRUE, IDI_PI_RCV_M_16,
|
|
NCM_PHONE, TRUE, TRUE, FALSE, IDI_PI_TRN_M_16,
|
|
NCM_PHONE, TRUE, TRUE, TRUE, IDI_PI_CON_M_16,
|
|
|
|
// LAN
|
|
NCM_LAN, FALSE, FALSE, FALSE, IDI_LB_NON_M_16,
|
|
NCM_LAN, FALSE, FALSE, TRUE, IDI_LB_RCV_M_16,
|
|
NCM_LAN, FALSE, TRUE, FALSE, IDI_LB_TRN_M_16,
|
|
NCM_LAN, FALSE, TRUE, TRUE, IDI_LB_CON_M_16,
|
|
|
|
// Direct connect
|
|
NCM_DIRECT, FALSE, FALSE, FALSE, IDI_DO_NON_M_16,
|
|
NCM_DIRECT, FALSE, FALSE, TRUE, IDI_DO_RCV_M_16,
|
|
NCM_DIRECT, FALSE, TRUE, FALSE, IDI_DO_TRN_M_16,
|
|
NCM_DIRECT, FALSE, TRUE, TRUE, IDI_DO_CON_M_16,
|
|
NCM_DIRECT, TRUE, FALSE, FALSE, IDI_DI_NON_M_16,
|
|
NCM_DIRECT, TRUE, FALSE, TRUE, IDI_DI_RCV_M_16,
|
|
NCM_DIRECT, TRUE, TRUE, FALSE, IDI_DI_TRN_M_16,
|
|
NCM_DIRECT, TRUE, TRUE, TRUE, IDI_DI_CON_M_16,
|
|
|
|
// Tunnel
|
|
NCM_TUNNEL, FALSE, FALSE, FALSE, IDI_TO_NON_M_16,
|
|
NCM_TUNNEL, FALSE, FALSE, TRUE, IDI_TO_RCV_M_16,
|
|
NCM_TUNNEL, FALSE, TRUE, FALSE, IDI_TO_TRN_M_16,
|
|
NCM_TUNNEL, FALSE, TRUE, TRUE, IDI_TO_CON_M_16,
|
|
NCM_TUNNEL, TRUE, FALSE, FALSE, IDI_TI_NON_M_16,
|
|
NCM_TUNNEL, TRUE, FALSE, TRUE, IDI_TI_RCV_M_16,
|
|
NCM_TUNNEL, TRUE, TRUE, FALSE, IDI_TI_TRN_M_16,
|
|
NCM_TUNNEL, TRUE, TRUE, TRUE, IDI_TI_CON_M_16,
|
|
|
|
// ISDN
|
|
NCM_ISDN, FALSE, FALSE, FALSE, IDI_PO_NON_M_16,
|
|
NCM_ISDN, FALSE, FALSE, TRUE, IDI_PO_RCV_M_16,
|
|
NCM_ISDN, FALSE, TRUE, FALSE, IDI_PO_TRN_M_16,
|
|
NCM_ISDN, FALSE, TRUE, TRUE, IDI_PO_CON_M_16,
|
|
NCM_ISDN, TRUE, FALSE, FALSE, IDI_PI_NON_M_16,
|
|
NCM_ISDN, TRUE, FALSE, TRUE, IDI_PI_RCV_M_16,
|
|
NCM_ISDN, TRUE, TRUE, FALSE, IDI_PI_TRN_M_16,
|
|
NCM_ISDN, TRUE, TRUE, TRUE, IDI_PI_CON_M_16,
|
|
|
|
// PPPoE
|
|
NCM_PPPOE, FALSE, FALSE, FALSE, IDI_BR_NON_M_16,
|
|
NCM_PPPOE, FALSE, FALSE, TRUE, IDI_BR_RCV_M_16,
|
|
NCM_PPPOE, FALSE, TRUE, FALSE, IDI_BR_TRN_M_16,
|
|
NCM_PPPOE, FALSE, TRUE, TRUE, IDI_BR_CON_M_16,
|
|
|
|
// SHAREDACCESSHOST
|
|
NCM_SHAREDACCESSHOST_LAN, FALSE, FALSE, FALSE, IDI_LB_NON_M_16,
|
|
NCM_SHAREDACCESSHOST_LAN, FALSE, FALSE, TRUE, IDI_LB_RCV_M_16,
|
|
NCM_SHAREDACCESSHOST_LAN, FALSE, TRUE, FALSE, IDI_LB_TRN_M_16,
|
|
NCM_SHAREDACCESSHOST_LAN, FALSE, TRUE, TRUE, IDI_LB_CON_M_16,
|
|
|
|
NCM_SHAREDACCESSHOST_RAS, FALSE, FALSE, FALSE, IDI_LB_NON_M_16,
|
|
NCM_SHAREDACCESSHOST_RAS, FALSE, FALSE, TRUE, IDI_LB_RCV_M_16,
|
|
NCM_SHAREDACCESSHOST_RAS, FALSE, TRUE, FALSE, IDI_LB_TRN_M_16,
|
|
NCM_SHAREDACCESSHOST_RAS, FALSE, TRUE, TRUE, IDI_LB_CON_M_16,
|
|
|
|
};
|
|
|
|
const DWORD g_dwStatusIconMapEntryCount = celems(c_SIMEArray);
|
|
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: HrGetPcpFromPnse
|
|
//
|
|
// Purpose: Gets the connection point off of an INetStatistics Engine
|
|
//
|
|
// Arguments: pnseSrc - The interface we want to get the connection
|
|
// point off of
|
|
// ppcpStatEng - Where to return the connection point
|
|
//
|
|
// Returns: Error code.
|
|
//
|
|
HRESULT HrGetPcpFromPnse(
|
|
INetStatisticsEngine* pnseSrc,
|
|
IConnectionPoint** ppcpStatEng)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
IConnectionPointContainer* pcpcStatEng = NULL;
|
|
|
|
AssertSz(pnseSrc, "We should have a pnseSrc");
|
|
AssertSz(ppcpStatEng, "We should have a ppcpStatEng");
|
|
|
|
hr = pnseSrc->QueryInterface(IID_IConnectionPointContainer,
|
|
reinterpret_cast<VOID**>(&pcpcStatEng));
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
// Find the interface
|
|
hr = pcpcStatEng->FindConnectionPoint(
|
|
IID_INetConnectionStatisticsNotifySink,
|
|
ppcpStatEng);
|
|
|
|
// Release the connection point
|
|
ReleaseObj(pcpcStatEng);
|
|
}
|
|
|
|
TraceError("HrGetPcpFromPnse", hr);
|
|
return hr;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: IGetCurrentConnectionTrayIconId
|
|
//
|
|
// Purpose: Get the INetConnection pointer from the persisted data
|
|
//
|
|
// Arguments: ncmType - Media type
|
|
// dwChangeFlags - What states have changed
|
|
//
|
|
// Returns: The id of the small icon for the connection or -1 on failure
|
|
//
|
|
// Notes:
|
|
//
|
|
INT IGetCurrentConnectionTrayIconId(NETCON_MEDIATYPE ncmType, NETCON_STATUS ncsStatus, DWORD dwChangeFlags)
|
|
{
|
|
INT iBaseIcon = -1;
|
|
|
|
// Check the trans/recv flags to see what our base icon is.
|
|
//
|
|
if (ncsStatus == NCS_INVALID_ADDRESS)
|
|
{
|
|
iBaseIcon = IDI_CFT_INVALID_ADDRESS;
|
|
}
|
|
else
|
|
{
|
|
if (SMDCF_TRANSMITTING & dwChangeFlags)
|
|
{
|
|
if (SMDCF_RECEIVING & dwChangeFlags)
|
|
{
|
|
// Transmitting and receiving
|
|
iBaseIcon = IDI_CFT_XMTRECV;
|
|
}
|
|
else
|
|
{
|
|
// Transmitting only
|
|
iBaseIcon = IDI_CFT_XMT;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (SMDCF_RECEIVING & dwChangeFlags)
|
|
{
|
|
// Receiving only
|
|
iBaseIcon = IDI_CFT_RECV;
|
|
}
|
|
else
|
|
{
|
|
// Neither transmitting nor receiving
|
|
iBaseIcon = IDI_CFT_BLANK;
|
|
}
|
|
}
|
|
}
|
|
|
|
return iBaseIcon;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: GetCurrentConnectionStatusIconId
|
|
//
|
|
// Purpose: Get the INetConnection pointer from the persisted data
|
|
//
|
|
// Arguments: ncmType - Media type
|
|
// ncsmType - SubMedia type
|
|
// dwCharacteristics - Connection characteristics
|
|
// dwChangeFlags - What states have changed
|
|
//
|
|
// Returns: The id of the small icon for the connection or -1 on failure
|
|
//
|
|
// Notes:
|
|
//
|
|
HICON GetCurrentConnectionStatusIconId(
|
|
NETCON_MEDIATYPE ncmType,
|
|
NETCON_SUBMEDIATYPE ncsmType,
|
|
DWORD dwCharacteristics,
|
|
DWORD dwChangeFlags)
|
|
{
|
|
HICON hMyIcon = NULL;
|
|
DWORD dwLoop = 0;
|
|
BOOL fValidIcon = FALSE;
|
|
BOOL fTransmitting = !!(dwChangeFlags & SMDCF_TRANSMITTING);
|
|
BOOL fReceiving = !!(dwChangeFlags & SMDCF_RECEIVING);
|
|
INT iStatusIcon = -1;
|
|
|
|
// Loop through the map and find the appropriate icon
|
|
//
|
|
|
|
DWORD dwConnectionIcon = 0x4;
|
|
dwConnectionIcon |= fTransmitting ? 0x2 : 0;
|
|
dwConnectionIcon |= fReceiving ? 0x1 : 0;
|
|
|
|
HRESULT hr = HrGetIconFromMediaType(GetSystemMetrics(SM_CXICON), ncmType, ncsmType, dwConnectionIcon, (dwCharacteristics & NCCF_INCOMING_ONLY), &hMyIcon);
|
|
if (FAILED(hr))
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
return hMyIcon;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: FIsStringInList
|
|
//
|
|
// Purpose: To see if a string is in a string list
|
|
//
|
|
// Arguments: plstpstrList - The list in which the string is to be found
|
|
// szString - The string being looked for
|
|
//
|
|
// Returns: TRUE if the string is in the list
|
|
// FALSE otherwise (including the case where the list is empty)
|
|
//
|
|
// Notes: It is an case insensitive search
|
|
//
|
|
BOOL FIsStringInList(list<tstring*>* plstpstrList, const WCHAR* szString)
|
|
{
|
|
BOOL fRet = FALSE;
|
|
|
|
// Only look in non-empty lists
|
|
//
|
|
if (!plstpstrList->empty())
|
|
{
|
|
list<tstring*>::iterator iterLstpstr;
|
|
|
|
iterLstpstr = plstpstrList->begin();
|
|
while ((!fRet)
|
|
&& (iterLstpstr != plstpstrList->end()))
|
|
{
|
|
// See if the string in the list matches the string we are
|
|
// comparing against
|
|
//
|
|
if (!lstrcmpiW((*iterLstpstr)->c_str(), szString))
|
|
{
|
|
fRet = TRUE;
|
|
}
|
|
|
|
iterLstpstr++;
|
|
}
|
|
}
|
|
|
|
return fRet;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: FormatBytesPerSecond
|
|
//
|
|
// Purpose: To format nicely BPS into a readable string.
|
|
//
|
|
// Arguments:
|
|
// uiBps []
|
|
// pchBuffer []
|
|
//
|
|
// Returns: Number of characters put into the buffer.
|
|
//
|
|
INT
|
|
FormatBytesPerSecond (
|
|
UINT uiBps,
|
|
WCHAR* pchBuffer)
|
|
{
|
|
enum {eZero = 0, eKilo, eMega, eGiga, eTera, eMax};
|
|
const WCHAR* pszBPSFormat = NULL;
|
|
INT iOffset = 0;
|
|
UINT uiDecimal = 0;
|
|
|
|
// Make sure our resources are still in the correct order
|
|
//
|
|
AssertSz(((((IDS_SM_BPS_ZERO + eKilo) == IDS_SM_BPS_KILO)
|
|
&& (IDS_SM_BPS_ZERO + eMega) == IDS_SM_BPS_MEGA)
|
|
&& ((IDS_SM_BPS_ZERO + eGiga) == IDS_SM_BPS_GIGA)
|
|
&& ((IDS_SM_BPS_ZERO + eTera) == IDS_SM_BPS_TERA)),
|
|
"Someone's been messing with the BPS format strings");
|
|
|
|
for (iOffset = eZero; iOffset < eMax; iOffset++)
|
|
{
|
|
|
|
// If we still have data, increment the counter
|
|
//
|
|
if (c_uiKilo > uiBps)
|
|
{
|
|
break;
|
|
}
|
|
|
|
// Divide up the string
|
|
//
|
|
uiDecimal = (uiBps % c_uiKilo);
|
|
uiBps /= c_uiKilo;
|
|
}
|
|
|
|
// We only want one digit for the decimal
|
|
//
|
|
uiDecimal /= (c_uiKilo/10);
|
|
|
|
// Get the string used to display
|
|
//
|
|
pszBPSFormat = SzLoadIds(IDS_SM_BPS_ZERO + iOffset);
|
|
AssertSz(pszBPSFormat, "We need a format string for BPS");
|
|
|
|
// Create the string
|
|
//
|
|
return wsprintfW(pchBuffer, pszBPSFormat, uiBps, uiDecimal);
|
|
}
|
|
|
|
INT
|
|
FormatTransmittingReceivingSpeed(
|
|
UINT nTransmitSpeed,
|
|
UINT nRecieveSpeed,
|
|
WCHAR* pchBuf)
|
|
{
|
|
WCHAR* pch = pchBuf;
|
|
|
|
pch += FormatBytesPerSecond(nTransmitSpeed, pch);
|
|
|
|
if (nTransmitSpeed != nRecieveSpeed)
|
|
{
|
|
// Separate with a backslash.
|
|
//
|
|
lstrcatW(pch, L"\\");
|
|
pch += 1;
|
|
|
|
pch += FormatBytesPerSecond(nRecieveSpeed, pch);
|
|
}
|
|
|
|
return lstrlenW(pchBuf);
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Function: FormatTimeDuration
|
|
//
|
|
// Purpose: Takes a millisecond count and formats a string with the
|
|
// duration represented by the millisecond count.
|
|
//
|
|
// Arguments:
|
|
// uiMilliseconds []
|
|
// pstrOut []
|
|
//
|
|
// Returns: nothing
|
|
//
|
|
VOID FormatTimeDuration(UINT uiSeconds, tstring* pstrOut)
|
|
{
|
|
WCHAR achSep[4];
|
|
WCHAR achBuf[64];
|
|
UINT uiNumTemp;
|
|
|
|
AssertSz(pstrOut, "We should have a pstrOut");
|
|
|
|
// Get the seperator for the locale.
|
|
//
|
|
SideAssert(GetLocaleInfo(
|
|
LOCALE_USER_DEFAULT,
|
|
LOCALE_STIME,
|
|
achSep,
|
|
celems(achSep)));
|
|
|
|
//
|
|
// Concatenate the strings together
|
|
//
|
|
|
|
// Add the days if there are more than zero
|
|
//
|
|
uiNumTemp = (uiSeconds / c_cmsDay);
|
|
if (uiNumTemp > 0)
|
|
{
|
|
pstrOut->append(_itow(uiNumTemp, achBuf, 10));
|
|
uiSeconds %= c_cmsDay;
|
|
|
|
if (uiNumTemp>1)
|
|
pstrOut->append(SzLoadIds(IDS_Days));
|
|
else
|
|
pstrOut->append(SzLoadIds(IDS_Day));
|
|
|
|
pstrOut->append(c_szSpace);
|
|
}
|
|
|
|
// Append hours
|
|
//
|
|
uiNumTemp = (uiSeconds / c_cmsHour);
|
|
if (10 > uiNumTemp)
|
|
{
|
|
pstrOut->append(c_szZero);
|
|
}
|
|
pstrOut->append(_itow(uiNumTemp, achBuf, 10));
|
|
pstrOut->append(achSep);
|
|
uiSeconds %= c_cmsHour;
|
|
|
|
// Append minutes
|
|
//
|
|
uiNumTemp = (uiSeconds / c_cmsMinute);
|
|
if (10 > uiNumTemp)
|
|
{
|
|
pstrOut->append(c_szZero);
|
|
}
|
|
pstrOut->append(_itow(uiNumTemp, achBuf, 10));
|
|
pstrOut->append(achSep);
|
|
uiSeconds %= c_cmsMinute;
|
|
|
|
// Append seconds
|
|
//
|
|
uiNumTemp = (uiSeconds / c_cmsSecond);
|
|
if (10 > uiNumTemp)
|
|
{
|
|
pstrOut->append(c_szZero);
|
|
}
|
|
pstrOut->append(_itow(uiNumTemp, achBuf, 10));
|
|
}
|