//+--------------------------------------------------------------------------- // // Microsoft Windows // Copyright (C) Microsoft Corporation, 1998. // // File: S M G E N P S P . C P P // // Contents: The rendering of the UI for the network status monitor. // // Notes: // // Author: CWill 6 Oct 1997 // //---------------------------------------------------------------------------- #include "pch.h" #pragma hdrstop #include "foldinc.h" #include "ncatlui.h" #include "ncnetcon.h" #include "ncperms.h" #include "ncui.h" #include "ncreg.h" #include "nsres.h" #include "sminc.h" #include "smpsh.h" #include "windutil.h" #include "conprops.h" #include "oncommand.h" #include "pidlutil.h" #include "openfold.h" #include "..\folder\confold.h" #include "cfpidl.h" DWORD MapRSSIToWirelessSignalStrength(int iRSSI); PCWSTR PszGetRSSIString(int iRSSI); // // Function Prototypes // VOID CompressionToSz(UINT uiCompression, WCHAR* pchbuffer); // // Common Strings // extern const WCHAR c_szNetShellDll[]; // // Constants // const UINT c_unLocalRefreshTimerID = 817; // // ShowLanErrors // static const WCHAR c_szRegKeyStatmonRoot[] = L"System\\CurrentControlSet\\Control\\Network\\Connections\\StatMon"; static const WCHAR c_szShowLanErrors[] = L"ShowLanErrors"; // forward declaration DWORD PropertyThread(CNetStatisticsEngine * pnse); //+--------------------------------------------------------------------------- // // Member: CPspStatusMonitorGen::CPspStatusMonitorGen // // Purpose: Creator // // Arguments: None // // Returns: Nil // CPspStatusMonitorGen::CPspStatusMonitorGen() : m_psmEngineData(NULL), m_pnseStat(NULL), m_dwConPointCookie(0), m_fStats(FALSE), m_ncmType(NCM_LAN), m_ncsmType(NCSM_LAN), m_dwCharacter(0), m_dwLastUpdateStatusDisplayTick(0), m_fProcessingTimerEvent(FALSE), m_fIsFirstPage(FALSE), m_iLastSignalStrength(-100) { TraceFileFunc(ttidStatMon); } //+--------------------------------------------------------------------------- // // Member: CPspStatusMonitorGen::FinalRelease // // Purpose: Called after last Release. // // Arguments: None // // Returns: Nil // VOID CPspStatusMonitorGen::FinalRelease(VOID) { TraceFileFunc(ttidStatMon); (VOID) HrCleanupGenPage(); } //+--------------------------------------------------------------------------- // // Member: CPspStatusMonitorGen::HrInitGenPage // // Purpose: Before the property page is populated, we have to make sure // that we have some of the required data. This method // initializes the page so that it is ready to be shown. // // Arguments: pnseNew - The statistics engine associated with this page // pncNew - The connection the page is being created for // // Returns: Error code // HRESULT CPspStatusMonitorGen::HrInitGenPage ( CNetStatisticsEngine* pnseNew, INetConnection* pncNew, const DWORD * adwHelpIDs) { TraceFileFunc(ttidStatMon); HRESULT hr = S_OK; INetStatisticsEngine* pnseInter = pnseNew; AssertSz(pnseNew, "We don't have a pnseNew"); // Set context help ID m_adwHelpIDs = adwHelpIDs; // Initialize the engine data // AssertSz(!m_psmEngineData, "We should't have a m_psmEngineData"); DWORD dwBytes = sizeof(STATMON_ENGINEDATA); PVOID pbBuf; hr = HrCoTaskMemAlloc(dwBytes, &pbBuf); if (SUCCEEDED(hr)) { m_psmEngineData = reinterpret_cast(pbBuf); ZeroMemory(m_psmEngineData, sizeof(STATMON_ENGINEDATA)); } // Advise the interface // if (SUCCEEDED(hr)) { IConnectionPoint* pcpStat = NULL; hr = ::HrGetPcpFromPnse(pnseInter, &pcpStat); if (SUCCEEDED(hr)) { INetConnectionStatisticsNotifySink* pncsThis = this; hr = pcpStat->Advise(pncsThis, &m_dwConPointCookie); ::ReleaseObj(pcpStat); } } // Keep track of our owner // if (SUCCEEDED(hr)) { AssertSz(!m_pnseStat, "We should't have a m_pnseStat"); m_pnseStat = pnseNew; ::AddRefObj(pnseInter); } TraceError("CPspStatusMonitorGen::HrInitGenPage", hr); return hr; } //+--------------------------------------------------------------------------- // // Member: CPspStatusMonitorGen::OnInitDialog // // Purpose: When the page comes up, initialize the fields // // Arguments: Standard command parameters // // Returns: Standard return // LRESULT CPspStatusMonitorGen::OnInitDialog ( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) { TraceFileFunc(ttidStatMon); // initialize data member m_iStatTrans = Stat_Unknown; // Initialize the icon in the dialog by forcing it to change // UpdatePageIcon(SMDCF_TRANSMITTING | SMDCF_RECEIVING); UpdatePageIcon(SMDCF_NULL); UpdateSignalStrengthIcon(0); // Tell the CNetStatisticsEngine about our parent property sheet // so if someone attempts to bring up a statistics monitor we // can utilize the existing one // Assert(m_pnseStat); m_pnseStat->SetPropsheetWindow(GetParent()); // Start our local refresh timer with a 1 second period. // SetTimer (c_unLocalRefreshTimerID, 1000, NULL); // leaving creating mode m_pnseStat->UnSetCreatingDialog(); BOOL fEnableDisconnect = TRUE; // Should we disable the Disconnect button BOOL fEnableProperties = TRUE; // Should we disable the Properties button BOOL fShowErrorCount = TRUE; switch(m_ncmType) { case NCM_LAN: case NCM_BRIDGE: fEnableDisconnect = FHasPermission(NCPERM_LanConnect); fEnableProperties = FHasPermission(NCPERM_LanProperties); if(!FIsShowLanErrorRegKeySet()) { fShowErrorCount = FALSE; } ::ShowWindow(GetDlgItem(IDC_TXT_ERROR), fShowErrorCount); ::ShowWindow(GetDlgItem(IDC_TXT_SM_ERROR_TRANS), fShowErrorCount); ::ShowWindow(GetDlgItem(IDC_TXT_SM_ERROR_RECV), fShowErrorCount); ::ShowWindow(GetDlgItem(IDC_FRM_LONG), fShowErrorCount); ::ShowWindow(GetDlgItem(IDC_FRM_SHORT), !fShowErrorCount); // reversed... break; case NCM_SHAREDACCESSHOST_RAS: ::SetWindowText(GetDlgItem(IDC_PSB_DISCONNECT), ::SzLoadIds(IDS_SM_PSH_DISCONNECT)); // If RAS connection, change the "Disable" button to "Disconnect" //fallthru case NCM_SHAREDACCESSHOST_LAN: { // TODO fEnableDisconnect // TODO fEnableProperties HRESULT hr; fShowErrorCount = FALSE; // no error stuff in spec } break; case NCM_TUNNEL: ::ShowWindow(GetDlgItem(IDC_TXT_SM_SPEED_LABEL), FALSE); ::ShowWindow(GetDlgItem(IDC_TXT_SM_SPEED), FALSE); //fallthru case NCM_DIRECT: // REVIEW correct? case NCM_ISDN: case NCM_PHONE: case NCM_PPPOE: fEnableDisconnect = FHasPermission(NCPERM_RasConnect); if ( (m_dwCharacter & NCCF_INCOMING_ONLY) || ((m_dwCharacter & NCCF_ALL_USERS) && !FHasPermission(NCPERM_RasAllUserProperties)) || (!(m_dwCharacter & NCCF_ALL_USERS) && !FHasPermission(NCPERM_RasMyProperties)) ) { fEnableProperties = FALSE; } ::SetWindowText(GetDlgItem(IDC_PSB_DISCONNECT), ::SzLoadIds(IDS_SM_PSH_DISCONNECT)); // If RAS connection, change the "Disable" button to "Disconnect" ::ShowWindow(GetDlgItem(IDC_TXT_ERROR), fShowErrorCount); ::ShowWindow(GetDlgItem(IDC_TXT_SM_ERROR_TRANS), fShowErrorCount); ::ShowWindow(GetDlgItem(IDC_TXT_SM_ERROR_RECV), fShowErrorCount); ::ShowWindow(GetDlgItem(IDC_FRM_LONG), fShowErrorCount); ::ShowWindow(GetDlgItem(IDC_FRM_SHORT), !fShowErrorCount); // reversed... break; default: AssertSz(FALSE, "Unknown media type"); break; } ::EnableWindow(::GetDlgItem(m_hWnd, IDC_PSB_DISCONNECT), fEnableDisconnect); ::EnableWindow(::GetDlgItem(m_hWnd, IDC_PSB_PROPERTIES), fEnableProperties); if (m_fIsFirstPage) { // get window handle to propertysheet HWND hwndParent=GetParent(); Assert(hwndParent); // center the property sheet on desktop FCenterWindow (hwndParent, NULL); // hide the "ok" button // ::ShowWindow(::GetDlgItem(hwndParent, IDOK), FALSE); } return TRUE; } //+--------------------------------------------------------------------------- // // Member: CPspStatusMonitorGen::OnSetActive // // Purpose: Enable statistics when the page has focus // // Arguments: Standard notification parameters // // Returns: Standard return // LRESULT CPspStatusMonitorGen::OnSetActive ( INT idCtrl, LPNMHDR pnmh, BOOL& bHandled) { TraceFileFunc(ttidStatMon); HRESULT hr = S_OK; // Only turn them on if they are not running // if (!m_fStats) { hr = m_pnseStat->StartStatistics(); m_fStats = TRUE; } // User's intent is to view statistics, so give them an immediate // refreshed view of them. // ::PostMessage (m_hWnd, PWM_UPDATE_STATUS_DISPLAY, 0, SMDCF_NULL); TraceError("CPspStatusMonitorGen::OnSetActive", hr); return LresFromHr(hr); } //+--------------------------------------------------------------------------- // // Member: CPspStatusMonitorGen::OnKillActive // // Purpose: Disable statistics when the page is changed // // Arguments: Standard notification parameters // // Returns: Standard return // LRESULT CPspStatusMonitorGen::OnKillActive ( INT idCtrl, LPNMHDR pnmh, BOOL& bHandled) { TraceFileFunc(ttidStatMon); HRESULT hr = S_OK; // Only turn them off if they are running // if (m_fStats) { hr = m_pnseStat->StopStatistics(); m_fStats = FALSE; } TraceError("CPspStatusMonitorGen::OnKillActive", hr); return LresFromHr(hr); } //+--------------------------------------------------------------------------- // // Member: CPspStatusMonitorGen::OnClose // // Purpose: Cleans up the items in the page when the dialog is being // closed // // Arguments: Standard command parameters // // Returns: Standard return // LRESULT CPspStatusMonitorGen::OnClose ( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) { return DestroyWindow(); } //+--------------------------------------------------------------------------- // // Member: CPspStatusMonitorGen::OnDestroy // // Purpose: Cleans up the items in the page when the dialog is being // destroyed // // Arguments: Standard command parameters // // Returns: Standard return // LRESULT CPspStatusMonitorGen::OnDestroy ( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) { TraceFileFunc(ttidStatMon); HWND hwndIcon = ::GetDlgItem(m_hWnd, IDI_SM_STATUS_ICON); HICON hOldIcon = reinterpret_cast(::SendMessage( hwndIcon, STM_GETICON, 0, 0)); if (hOldIcon) { DestroyIcon(hOldIcon); } HRESULT hr = S_OK; AssertSz(m_pnseStat, "We should have a m_pnseStat"); // Make sure we don't get released during our destroy // ::AddRefObj(this); // Stop our local refresh timer // KillTimer (c_unLocalRefreshTimerID); // Make sure stats are in a happy state // if (m_fStats) { (VOID) m_pnseStat->StopStatistics(); m_fStats = FALSE; } // // *** Do this last *** // // It is very likely this will result in the this page being destroyed // if it is the window closing // m_pnseStat->SetPropsheetWindow(NULL); // Clean up all the interfaces // hr = HrCleanupGenPage(); ::ReleaseObj(this); TraceError("CPspStatusMonitorGen::OnDestroy", hr); return 0; } //+--------------------------------------------------------------------------- // // Member: CPspStatusMonitorGen::HrCleanupGenPage // // Purpose: Cleans out all the interfaces that are used by the open page // // Arguments: None // // Returns: Error code // HRESULT CPspStatusMonitorGen::HrCleanupGenPage ( VOID) { TraceFileFunc(ttidStatMon); HRESULT hr = S_OK; INetStatisticsEngine* pnseStat = m_pnseStat; // Only disconnect if we haven't already. // if (pnseStat) { // Unadvise the interface // IConnectionPoint* pcpStat = NULL; if (m_dwConPointCookie && (SUCCEEDED(::HrGetPcpFromPnse(pnseStat, &pcpStat)))) { (VOID) pcpStat->Unadvise(m_dwConPointCookie); ::ReleaseObj(pcpStat); // Very important to zero the cookie. This tells // OnStatisticsChanged that we're no longer interested in updates. // m_dwConPointCookie = 0; } if (m_psmEngineData) { CoTaskMemFree(m_psmEngineData); m_psmEngineData = NULL; } // // *** Do this last *** // // It is very likely this will result in the this page being destroyed // if it is the window closing // m_pnseStat = NULL; ::ReleaseObj(pnseStat); } TraceError("CPspStatusMonitorGen::HrCleanupGenPage", hr); return hr; } //+--------------------------------------------------------------------------- // // Member: CPspStatusMonitorGen::OnContextMenu // // Purpose: When right click a control, bring up help // // Arguments: Standard command parameters // // Returns: Standard return // LRESULT CPspStatusMonitorGen::OnContextMenu(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& fHandled) { TraceFileFunc(ttidStatMon); if (m_adwHelpIDs != NULL) { ::WinHelp(m_hWnd, c_szNetCfgHelpFile, HELP_CONTEXTMENU, (ULONG_PTR)m_adwHelpIDs); } return 0; } //+--------------------------------------------------------------------------- // // Member: CPspStatusMonitorGen::OnHelp // // Purpose: When drag context help icon over a control, bring up help // // Arguments: Standard command parameters // // Returns: Standard return // LRESULT CPspStatusMonitorGen::OnHelp(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& fHandled) { TraceFileFunc(ttidStatMon); LPHELPINFO lphi = reinterpret_cast(lParam); Assert(lphi); if ((m_adwHelpIDs != NULL) && (HELPINFO_WINDOW == lphi->iContextType)) { ::WinHelp(static_cast(lphi->hItemHandle), c_szNetCfgHelpFile, HELP_WM_HELP, (ULONG_PTR)m_adwHelpIDs); } return 0; } //+--------------------------------------------------------------------------- // // Member: CPspStatusMonitorGen::OnDisconnect // // Purpose: When the disconnect button is hit, disconnect the connection // and closes the dialog // // Arguments: Standard notification parameters // // Returns: Standard return // LRESULT CPspStatusMonitorGen::OnDisconnect(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& fHandled) { TraceFileFunc(ttidStatMon); HRESULT hr = S_OK; switch (wNotifyCode) { case BN_CLICKED: case BN_DOUBLECLICKED: { hr = HrDisconnectConnection(); } } TraceError("CPspStatusMonitorGen::OnDisconnect", hr); return 0; } //+--------------------------------------------------------------------------- // // Member: CPspStatusMonitorGen::OnRaiseproperties // // Purpose: Bring up the property of this connection // // Arguments: Standard notification parameters // // Returns: Standard return // LRESULT CPspStatusMonitorGen::OnRaiseProperties(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& fHandled) { TraceFileFunc(ttidStatMon); HRESULT hr = S_OK; switch (wNotifyCode) { case BN_CLICKED: case BN_DOUBLECLICKED: { // Addref m_pnseStat object // AddRefObj(static_cast(m_pnseStat)); // Make sure the netshell.dll is not unloaded // HINSTANCE hInst = LoadLibrary(c_szNetShellDll); HANDLE hthrd = NULL; // Create the property sheet on a different thread // if (hInst) { DWORD dwThreadId; hthrd = CreateThread(NULL, STACK_SIZE_TINY, (LPTHREAD_START_ROUTINE)PropertyThread, (LPVOID)m_pnseStat, 0, &dwThreadId); } if (NULL != hthrd) { CloseHandle(hthrd); } else { /// Release m_pnseStat object on failure // ReleaseObj(static_cast(m_pnseStat)); // release the dll // if (hInst) FreeLibrary(hInst); hr = HrFromLastWin32Error(); } } } TraceError("CPspStatusMonitorGen::OnRaiseproperties", hr); return 0; } DWORD PropertyThread(CNetStatisticsEngine * pnse) { TraceFileFunc(ttidStatMon); HRESULT hr = S_OK; BOOL fUninitCom = TRUE; // Initialize COM on this thread // hr = CoInitializeEx(NULL, COINIT_DISABLE_OLE1DDE | COINIT_APARTMENTTHREADED); if (RPC_E_CHANGED_MODE == hr) { hr = S_OK; fUninitCom = FALSE; } if (SUCCEEDED(hr)) { INetConnection* pncMonitor = NULL; // Get the INetConnection // Assert (pnse); hr = pnse->HrGetConnectionFromBlob(&pncMonitor); if (SUCCEEDED(hr)) { hr = HrRaiseConnectionProperties(NULL, pncMonitor); } ReleaseObj(pncMonitor); } if (fUninitCom) { CoUninitialize(); } // release input interface ReleaseObj(static_cast(pnse)); // release the library we loaded FreeLibraryAndExitThread(GetModuleHandle(c_szNetShellDll), hr); TraceError("PropertyThread", hr); return 1; } //+--------------------------------------------------------------------------- // // Member: CPspStatusMonitorGen::HrDisconnectConnection // // Purpose: disconnect the connection and closes the dialog if succeeded // // Arguments: fConfirmed TRUE if the user has confirmed to disconnect the connection // // Returns: Standard return // HRESULT CPspStatusMonitorGen::HrDisconnectConnection(BOOL fConfirmed) { TraceFileFunc(ttidStatMon); HRESULT hr; Assert (m_pnseStat); // Get the INetConnection // INetConnection* pncMonitor; hr = m_pnseStat->HrGetConnectionFromBlob(&pncMonitor); if (SUCCEEDED(hr)) { PCONFOLDPIDL pidlConnection; hr = HrCreateConFoldPidl(WIZARD_NOT_WIZARD, pncMonitor, pidlConnection); if (SUCCEEDED(hr)) { CONFOLDENTRY ccfe; hr = pidlConnection.ConvertToConFoldEntry(ccfe); if (SUCCEEDED(hr)) { // Get the pidl for the Connections Folder // PCONFOLDPIDLFOLDER pidlFolder; hr = HrGetConnectionsFolderPidl(pidlFolder); if (SUCCEEDED(hr)) { // Get the Connections Folder object // LPSHELLFOLDER psfConnections; hr = HrGetConnectionsIShellFolder(pidlFolder, &psfConnections); if (SUCCEEDED(hr)) { hr = HrOnCommandDisconnectInternal(ccfe, m_hWnd, psfConnections); ReleaseObj(psfConnections); } } } } // release INetConnection interface ReleaseObj(pncMonitor); } // If anything above failed. // if (SUCCEEDED(hr)) { if (S_OK == hr) { // close the property sheet HWND hwndPS = ::GetParent(m_hWnd); // Push the Close ("Cancel") button to close dialog // ::PostMessage(hwndPS, WM_COMMAND, MAKEWPARAM(IDCANCEL, 0), (LPARAM)::GetDlgItem(hwndPS, IDCANCEL)); } else { // Disconnect confirmation canceled. Do nothing (don't close // statmon, anyway). // AssertSz(S_FALSE == hr, "Disconnect != S_OK or S_FALSE, but succeeded? What is it then?"); } } else { TraceError("pncMonitor->Disconnect", hr); // Warn the user and don't close if we couldn't disconnect // ::NcMsgBox( m_hWnd, IDS_SM_ERROR_CAPTION, IDS_SM_ERROR_CANNOT_DISCONNECT, MB_ICONWARNING); } TraceError("CPspStatusMonitorGen::HrDisconnectConnection", hr); return hr; } //+--------------------------------------------------------------------------- // // Member: CPspStatusMonitorGen::OnSetCursor // // Purpose: Ensure the mouse cursor over the Property Sheet is an Arrow. // // Arguments: Standard command parameters // // Returns: Standard return // LRESULT CPspStatusMonitorGen::OnSetCursor ( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) { TraceFileFunc(ttidStatMon); if (LOWORD(lParam) == HTCLIENT) { SetCursor(LoadCursor(NULL, IDC_ARROW)); } return FALSE; } LRESULT CPspStatusMonitorGen::OnTimer ( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) { TraceFileFunc(ttidStatMon); // Prevent same-thread re-entrancy. Any Win32 call made while // processing this event that return control to the message // loop may cause this timer to fire again. // if (!m_fProcessingTimerEvent) { m_fProcessingTimerEvent = TRUE; // If we're within 200 milliseconds of the last time we updated the // status display, don't bother doing it again. This covers the case // where our timer coincides with the timer in smcent which would // would cause us to update the status display twice in rapid // succession each time the timers fire. // DWORD dwTick = GetTickCount (); if (dwTick > m_dwLastUpdateStatusDisplayTick + 200) { OnUpdateStatusDisplay (uMsg, 0, m_dwChangeFlags, bHandled); } m_fProcessingTimerEvent = FALSE; } return 0; } LRESULT CPspStatusMonitorGen::OnUpdateStatusDisplay( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) { TraceFileFunc(ttidStatMon); HRESULT hr = S_OK; DWORD dwChangeFlags = lParam; // We may be in the process of disconnecting the statistics page in // which case m_dwConPointCookie will be zero. // if (m_dwConPointCookie) { Assert (m_psmEngineData); STATMON_ENGINEDATA* psmNewData = NULL; hr = m_pnseStat->GetStatistics(&psmNewData); if (SUCCEEDED(hr) && psmNewData) { if (m_psmEngineData) { // // Display the new stats // UpdatePage(m_psmEngineData, psmNewData); // Update the icon image // UpdatePageIcon(dwChangeFlags); UpdateSignalStrengthIcon(psmNewData->SMED_802_11_SIGNAL_STRENGTH); // Note the clock tick of when we last updated // the status display. // m_dwLastUpdateStatusDisplayTick = GetTickCount(); // Replace the old data with the new // CoTaskMemFree(m_psmEngineData); } m_psmEngineData = psmNewData; } } else { TraceTag (ttidStatMon, "CPspStatusMonitorGen::OnStatisticsChanged called but we've " "been closed. Ignoring."); } TraceError("CPspStatusMonitorGen::OnUpdateStatusDisplay", hr); return 0; } //+--------------------------------------------------------------------------- // // Member: CPspStatusMonitorGen::OnStatisticsChanged // // Purpose: This is the callback that tell the property page that the // data on the page has changed // // Arguments: dwCookie - The cookie of the connection that has changed // dwChangeFlags - What has changed // // Returns: Error code // STDMETHODIMP CPspStatusMonitorGen::OnStatisticsChanged( DWORD dwChangeFlags) { TraceFileFunc(ttidStatMon); ::PostMessage (m_hWnd, PWM_UPDATE_STATUS_DISPLAY, 0, dwChangeFlags); return S_OK; } //+--------------------------------------------------------------------------- // // Member: CPspStatusMonitorGen::UpdatePage // // Purpose: Fill the fields on the page with new data // // Arguments: pseOldData - The old stats being displayed on the page // pseNewData - The new stats being displayed on the page // // Returns: Nothing // VOID CPspStatusMonitorGen::UpdatePage ( STATMON_ENGINEDATA* pseOldData, const STATMON_ENGINEDATA* pseNewData) { TraceFileFunc(ttidStatMon); AssertSz(pseOldData, "We don't have a puiOld"); AssertSz(pseNewData, "We don't have a puiNew"); // // Update the dialog fields // UpdatePageConnectionStatus(pseOldData, pseNewData); UpdatePageDuration(pseOldData, pseNewData); UpdatePageSpeed(pseOldData, pseNewData); // If the StatMon is not getting any bytes (a common problem with net // cards), display packets instead // if (ShouldShowPackets(pseNewData)) { // Only change the label if we have to // if (Stat_Packets != m_iStatTrans) { SetDlgItemText(IDC_TXT_SM_BYTES_LABEL, ::SzLoadIds(IDS_SM_PACKETS)); m_iStatTrans = Stat_Packets; // Force a refresh // pseOldData->SMED_PACKETSTRANSMITTING = 0; pseOldData->SMED_PACKETSRECEIVING = 0; } UpdatePageBytesTransmitting(pseOldData, pseNewData, Stat_Packets); UpdatePageBytesReceiving(pseOldData, pseNewData, Stat_Packets); } else { // Only change the label if we have to // if (Stat_Bytes != m_iStatTrans) { SetDlgItemText(IDC_TXT_SM_BYTES_LABEL, ::SzLoadIds(IDS_SM_BYTES)); m_iStatTrans = Stat_Bytes; // Force a refresh // pseOldData->SMED_BYTESTRANSMITTING = 0; pseOldData->SMED_BYTESRECEIVING = 0; } UpdatePageBytesTransmitting(pseOldData, pseNewData, Stat_Bytes); UpdatePageBytesReceiving(pseOldData, pseNewData, Stat_Bytes); } UpdatePageCompTransmitting(pseOldData, pseNewData); UpdatePageCompReceiving(pseOldData, pseNewData); UpdatePageErrorsTransmitting(pseOldData, pseNewData); UpdatePageErrorsReceiving(pseOldData, pseNewData); } //+--------------------------------------------------------------------------- // // Member: CPspStatusMonitorGen::ShouldShowPackets // // Purpose: Decided whether to show bytes or packets // // Arguments: pseNewData - The new stats being displayed on the page // // Returns: Nothing // BOOL CPspStatusMonitorGen::ShouldShowPackets(const STATMON_ENGINEDATA* pseNewData) { TraceFileFunc(ttidStatMon); return (0 == pseNewData->SMED_BYTESTRANSMITTING) && (0 == pseNewData->SMED_BYTESRECEIVING); } //+--------------------------------------------------------------------------- // // Member: CPspStatusMonitorGen::UpdatePageSpeed // // Purpose: Updates the speed display on the general page // // Arguments: pseOldData - The old stats being displayed on the page // pseNewData - The new stats being displayed on the page // // Returns: Nothing // VOID CPspStatusMonitorGen::UpdatePageSpeed( const STATMON_ENGINEDATA* pseOldData, const STATMON_ENGINEDATA* pseNewData) { TraceFileFunc(ttidStatMon); AssertSz(pseOldData, "We don't have a pseOldData"); AssertSz(pseNewData, "We don't have a pseNewData"); // Get the data and see if either is different // if ((pseOldData->SMED_SPEEDTRANSMITTING != pseNewData->SMED_SPEEDTRANSMITTING) || (pseOldData->SMED_SPEEDRECEIVING != pseNewData->SMED_SPEEDRECEIVING)) { WCHAR achBuffer[MAX_PATH]; FormatTransmittingReceivingSpeed ( pseNewData->SMED_SPEEDTRANSMITTING, pseNewData->SMED_SPEEDRECEIVING, achBuffer); // Set the control text. // SetDlgItemText(IDC_TXT_SM_SPEED, achBuffer); } } //+--------------------------------------------------------------------------- // // Member: CPspStatusMonitorGen::UpdatePageConnectionStatus // // Purpose: Update the connections field on the property page // // Arguments: puiOldData - The old stats being displayed on the page // puiNewData - The new stats being displayed on the page // // Returns: Nothing // VOID CPspStatusMonitorGen::UpdatePageConnectionStatus( const STATMON_ENGINEDATA* pseOldData, const STATMON_ENGINEDATA* pseNewData) { TraceFileFunc(ttidStatMon); AssertSz(pseOldData, "We don't have a pseOldData"); AssertSz(pseNewData, "We don't have a pseNewdata"); // Update the Connection Status // if ((pseNewData->SMED_CONNECTIONSTATUS == NCS_DISCONNECTED) || (pseOldData->SMED_CONNECTIONSTATUS != pseNewData->SMED_CONNECTIONSTATUS)) { INT idsConnection = IDS_SM_CS_DISCONNECTED; // Make sure our strings are still intact AssertSz((((IDS_SM_CS_DISCONNECTED + 1) == IDS_SM_CS_CONNECTING) && ((IDS_SM_CS_DISCONNECTED + 2) == IDS_SM_CS_CONNECTED) && ((IDS_SM_CS_DISCONNECTED + 3) == IDS_SM_CS_DISCONNECTING) && ((IDS_SM_CS_DISCONNECTED + 4) == IDS_SM_CS_HARDWARE_NOT_PRESENT) && ((IDS_SM_CS_DISCONNECTED + 5) == IDS_SM_CS_HARDWARE_DISABLED) && ((IDS_SM_CS_DISCONNECTED + 6) == IDS_SM_CS_HARDWARE_MALFUNCTION)), "Some one has been messing with connection status strings"); idsConnection = (IDS_SM_CS_DISCONNECTED + pseNewData->SMED_CONNECTIONSTATUS); if (idsConnection == IDS_SM_CS_DISCONNECTED) { // close the property sheet HWND hwndPS = ::GetParent(m_hWnd); TraceTag(ttidStatMon, "Closing Status Monitor page because status was: DISCONNECTED"); // Push the Close ("Cancel") button to close dialog // ::PostMessage(hwndPS, WM_COMMAND, MAKEWPARAM(IDCANCEL, 0), (LPARAM)::GetDlgItem(hwndPS, IDCANCEL)); } else { SetDlgItemText(IDC_TXT_SM_STATUS, ::SzLoadIds(idsConnection)); } } } //+--------------------------------------------------------------------------- // // Member: CPspStatusMonitorGen::UpdatePageIcon // // Purpose: Update the icon on the property page // // Arguments: dwChangeFlags - The new changed state // // Returns: Nothing // VOID CPspStatusMonitorGen::UpdatePageIcon ( DWORD dwChangeFlags) { TraceFileFunc(ttidStatMon); // If either of these have changed, change the icon // so we'll know to update the icon // if (((SMDCF_TRANSMITTING | SMDCF_RECEIVING) & m_dwChangeFlags) != ((SMDCF_TRANSMITTING | SMDCF_RECEIVING) & dwChangeFlags)) { HICON hStatusIcon = 0; HWND hwndIcon = NULL; // Get the new icon // hStatusIcon = GetCurrentConnectionStatusIconId(m_ncmType, m_ncsmType, m_dwCharacter, dwChangeFlags); if (hStatusIcon) { hwndIcon = ::GetDlgItem(m_hWnd, IDI_SM_STATUS_ICON); // Set the icon to the new one // HICON hOldIcon = reinterpret_cast(::SendMessage( hwndIcon, STM_SETICON, (WPARAM)hStatusIcon, 0)); DestroyIcon(hOldIcon); } } // Keep the flags for the next update // m_dwChangeFlags = dwChangeFlags; } //+--------------------------------------------------------------------------- // // Member: CPspStatusMonitorGen::UpdateSignalStrengthIcon // // Purpose: Update the icon on the property page // // Arguments: iRSSI - The new signal strenghth // // Returns: Nothing // inline VOID CPspStatusMonitorGen::UpdateSignalStrengthIcon ( INT iRSSI) { TraceFileFunc(ttidStatMon); if (0 == iRSSI) { if (0 != m_iLastSignalStrength) { ::ShowWindow(::GetDlgItem(m_hWnd, IDC_TXT_SM_SIGNAL_STRENGTH), SW_HIDE); ::ShowWindow(::GetDlgItem(m_hWnd, IDI_SM_SIGNAL_STRENGTH_ICON), SW_HIDE); } m_iLastSignalStrength = iRSSI; return; } else { if (0 == m_iLastSignalStrength) { ::ShowWindow(::GetDlgItem(m_hWnd, IDC_TXT_SM_SIGNAL_STRENGTH), SW_SHOW); ::ShowWindow(::GetDlgItem(m_hWnd, IDI_SM_SIGNAL_STRENGTH_ICON), SW_SHOW); } } INT idStatusIcon = 0; m_iLastSignalStrength = iRSSI; // Get the new icon // idStatusIcon = IDI_802_11_LEVEL0 + MapRSSIToWirelessSignalStrength(iRSSI); HWND hwndSignalStrength = ::GetDlgItem(m_hWnd, IDI_SM_SIGNAL_STRENGTH_ICON); Assert(hwndSignalStrength); if (hwndSignalStrength) { HDC hdcSignalStrength = ::GetDC(hwndSignalStrength); Assert(hdcSignalStrength); if (hdcSignalStrength) { HICON hIconSignalStrength = LoadIconTile(_Module.GetResourceInstance(), MAKEINTRESOURCE(idStatusIcon)); Assert(hIconSignalStrength); if (hIconSignalStrength) { ::DrawIconEx(hdcSignalStrength, 0, 0, hIconSignalStrength, 48, 48, 0, NULL, DI_IMAGE | DI_MASK); DestroyIcon(hIconSignalStrength); } ::ReleaseDC(hwndSignalStrength, hdcSignalStrength); } } } //+--------------------------------------------------------------------------- // // Member: CPspStatusMonitorGen::UpdateSignalStrengthIcon // // Purpose: Update the icon on the property page // // Arguments: iRSSI - The new signal strenghth // // Returns: Nothing // LRESULT CPspStatusMonitorGen::OnPaint ( UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) { TraceFileFunc(ttidStatMon); PAINTSTRUCT ps; BeginPaint(&ps); UpdateSignalStrengthIcon(m_iLastSignalStrength); EndPaint(&ps); bHandled = TRUE; return 0; } //+--------------------------------------------------------------------------- // // Member: CPspStatusMonitorGen::UpdatePageDuration // // Purpose: Updates the duration display on the general page // // Arguments: pseOldData - The old stats being displayed on the page // pseNewData - The new stats being displayed on the page // // Returns: Nothing // VOID CPspStatusMonitorGen::UpdatePageDuration( const STATMON_ENGINEDATA* pseOldData, const STATMON_ENGINEDATA* pseNewData) { TraceFileFunc(ttidStatMon); AssertSz(pseOldData, "We don't have a pseOldData"); AssertSz(pseNewData, "We don't have a pseNewData"); // Get the see if either is different // if (pseOldData->SMED_DURATION != pseNewData->SMED_DURATION) { tstring strDuration; // Format the time duration as a string // FormatTimeDuration(pseNewData->SMED_DURATION, &strDuration); // Set the control // SetDlgItemText(IDC_TXT_SM_DURATION, strDuration.c_str()); } } //+--------------------------------------------------------------------------- // // Member: CPspStatusMonitorGen::UpdatePageBytesTransmitting // // Purpose: Updates the bytes Transmitting display on the general page // // Arguments: pseOldData - The old stats being displayed on the page // pseNewData - The new stats being displayed on the page // iStat - The which stats to display // // Returns: Nothing // VOID CPspStatusMonitorGen::UpdatePageBytesTransmitting( const STATMON_ENGINEDATA* pseOldData, const STATMON_ENGINEDATA* pseNewData, StatTrans iStat) { TraceFileFunc(ttidStatMon); AssertSz(pseOldData, "We don't have a pseOldData"); AssertSz(pseNewData, "We don't have a pseNewData"); AssertSz(((Stat_Packets == iStat) || (Stat_Bytes == iStat)), "We have an invalid iStat"); UINT64 ui64Old; UINT64 ui64New; if (Stat_Bytes == iStat) { ui64Old = pseOldData->SMED_BYTESTRANSMITTING; ui64New = pseNewData->SMED_BYTESTRANSMITTING; } else { ui64Old = pseOldData->SMED_PACKETSTRANSMITTING; ui64New = pseNewData->SMED_PACKETSTRANSMITTING; } // See if either is different // if (ui64Old != ui64New) { SetDlgItemFormatted64bitInteger( m_hWnd, IDC_TXT_SM_BYTES_TRANS, ui64New, FALSE); } } //+--------------------------------------------------------------------------- // // Member: CPspStatusMonitorGen::UpdatePageBytesReceiving // // Purpose: Updates the bytes receiving display on the general page // // Arguments: puiOld - The old stats being displayed on the page // puiNew - The new stats being displayed on the page // iStat - The which stats to display // // Returns: Nothing // VOID CPspStatusMonitorGen::UpdatePageBytesReceiving( const STATMON_ENGINEDATA* pseOldData, const STATMON_ENGINEDATA* pseNewData, StatTrans iStat) { TraceFileFunc(ttidStatMon); AssertSz(pseOldData, "We don't have a puiOld"); AssertSz(pseNewData, "We don't have a puiNew"); AssertSz(((Stat_Packets == iStat) || (Stat_Bytes == iStat)), "We have an invalid iStat"); UINT64 ui64Old; UINT64 ui64New; if (Stat_Bytes == iStat) { ui64Old = pseOldData->SMED_BYTESRECEIVING; ui64New = pseNewData->SMED_BYTESRECEIVING; } else { ui64Old = pseOldData->SMED_PACKETSRECEIVING; ui64New = pseNewData->SMED_PACKETSRECEIVING; } // See if either is different // if (ui64Old != ui64New) { SetDlgItemFormatted64bitInteger( m_hWnd, IDC_TXT_SM_BYTES_RCVD, ui64New, FALSE); } } //+--------------------------------------------------------------------------- // // Member: CPspStatusMonitorGen::UpdatePageCompTransmitting // // Purpose: Updates the compression transmitting display on the general // page // // Arguments: pseOldData - The old stats being displayed on the page // pseNewData - The new stats being displayed on the page // // Returns: Nothing // VOID CPspStatusMonitorGen::UpdatePageCompTransmitting( const STATMON_ENGINEDATA* pseOldData, const STATMON_ENGINEDATA* pseNewData) { TraceFileFunc(ttidStatMon); AssertSz(pseOldData, "We don't have a pseOldData"); AssertSz(pseNewData, "We don't have a pseNewData"); // See if either is different // if (pseOldData->SMED_COMPRESSIONTRANSMITTING != pseNewData->SMED_COMPRESSIONTRANSMITTING) { WCHAR achBuf[20]; CompressionToSz(pseNewData->SMED_COMPRESSIONTRANSMITTING, achBuf); SetDlgItemText(IDC_TXT_SM_COMP_TRANS, achBuf); } } //+--------------------------------------------------------------------------- // // Member: CPspStatusMonitorGen::UpdatePageCompReceiving // // Purpose: Updates the compression receiving display on the general page // // Arguments: pseOldData - The old stats being displayed on the page // pseNewData - The new stats being displayed on the page // // Returns: Nothing // VOID CPspStatusMonitorGen::UpdatePageCompReceiving( const STATMON_ENGINEDATA* pseOldData, const STATMON_ENGINEDATA* pseNewData) { TraceFileFunc(ttidStatMon); AssertSz(pseOldData, "We don't have a puiOld"); AssertSz(pseNewData, "We don't have a puiNew"); // see if either is different // if (pseOldData->SMED_COMPRESSIONRECEIVING != pseNewData->SMED_COMPRESSIONRECEIVING) { WCHAR achBuf[20]; CompressionToSz(pseNewData->SMED_COMPRESSIONRECEIVING, achBuf); SetDlgItemText(IDC_TXT_SM_COMP_RCVD, achBuf); } } //+--------------------------------------------------------------------------- // // Member: CPspStatusMonitorGen::UpdatePageErrorsTransmitting // // Purpose: Updates the compression transmitting display on the general // page // // Arguments: pseOldData - The old stats being displayed on the page // pseNewData - The new stats being displayed on the page // // Returns: Nothing // VOID CPspStatusMonitorGen::UpdatePageErrorsTransmitting( const STATMON_ENGINEDATA* pseOldData, const STATMON_ENGINEDATA* pseNewData) { TraceFileFunc(ttidStatMon); AssertSz(pseOldData, "We don't have a pseOldData"); AssertSz(pseNewData, "We don't have a pseNewData"); // See if either is different // if (pseOldData->SMED_ERRORSTRANSMITTING != pseNewData->SMED_ERRORSTRANSMITTING) { SetDlgItemFormatted32bitInteger ( m_hWnd, IDC_TXT_SM_ERROR_TRANS, pseNewData->SMED_ERRORSTRANSMITTING, FALSE); } } //+--------------------------------------------------------------------------- // // Member: CPspStatusMonitorGen::UpdatePageErrorsReceiving // // Purpose: Updates the compression receiving display on the general page // // Arguments: pseOldData - The old stats being displayed on the page // pseNewData - The new stats being displayed on the page // // Returns: Nothing // VOID CPspStatusMonitorGen::UpdatePageErrorsReceiving( const STATMON_ENGINEDATA* pseOldData, const STATMON_ENGINEDATA* pseNewData) { TraceFileFunc(ttidStatMon); AssertSz(pseOldData, "We don't have a pseOldData"); AssertSz(pseNewData, "We don't have a pseNewData"); // see if either is different // if (pseOldData->SMED_ERRORSRECEIVING != pseNewData->SMED_ERRORSRECEIVING) { SetDlgItemFormatted32bitInteger ( m_hWnd, IDC_TXT_SM_ERROR_RECV, pseNewData->SMED_ERRORSRECEIVING, FALSE); } } //+--------------------------------------------------------------------------- // // Function: CompressionToSz // // Purpose: To format nicely BPS into a readable string // // Arguments: uiCompression - The amount of compression // pchBuffer - The Buffer to receive the string // // Returns: Nothing // VOID CompressionToSz ( UINT uiCompression, WCHAR* pchBuffer) { TraceFileFunc(ttidStatMon); AssertSz((((INT)uiCompression >= 0) && ((INT)uiCompression <= 100)), "Invalid compression"); wsprintfW(pchBuffer, L"%lu %%", uiCompression); } //+--------------------------------------------------------------------------- // // Function: FIsShowLanErrorRegKeySet // // Purpose: Check if the registry key is set: // System\CurrentControlSet\Control\Network\Connections\StatMon\ShowLanErrors // // Arguments: // // Returns: Nothing // BOOL CPspStatusMonitorGen::FIsShowLanErrorRegKeySet() { TraceFileFunc(ttidStatMon); BOOL fRet = FALSE; HKEY hkeyStatmonRoot = NULL; HRESULT hr = S_OK; // "System\\CurrentControlSet\\Control\\Network\\Connections\\StatMon\\ShowLanErrors" hr = ::HrRegOpenKeyEx( HKEY_LOCAL_MACHINE, c_szRegKeyStatmonRoot, KEY_READ, &hkeyStatmonRoot); if (SUCCEEDED(hr)) { Assert(hkeyStatmonRoot); DWORD dwValue =0; hr = HrRegQueryDword(hkeyStatmonRoot, c_szShowLanErrors, &dwValue); if SUCCEEDED(hr) { fRet = !!dwValue; } RegCloseKey(hkeyStatmonRoot); } return fRet; }