From be3b4114bbf6660b2fd19ab7e775529d97b6bfc5 Mon Sep 17 00:00:00 2001 From: spx Date: Sat, 13 Feb 2010 03:07:34 +0000 Subject: [PATCH] - Added the function that measures the CPU usage for multi core/processors. For instance: [MeasureCPU] Measure=CPU [MeasureCPU1] Measure=CPU Processor=1 [MeasureCPU2] Measure=CPU Processor=2 MeasureCPU returns the average of the CPU usage across all core/processors. This is same as Processor=0. MeasureCPU1/2 returns the CPU usage of each core/processor. ----- - Fixed the problem that the correct value is not returned if the Interface=0 in NetIn/NetOut/NetTotal measure. The cause of this problem is because the value of all filter devices is summed in Vista or newer. ----- - Added the option (Debug) for debug logging. This must be put under [Rainmeter]-section in Rainmeter.ini. This option specifies whether extra debugging log from Rainmeter.dll is output to Rainmeter.log. [Rainmeter] Debug=1 Default is 0. ----- - Application: Fixed a wrong return value type from MainWndProc. --- Application/Application.cpp | 6 +- Library/ConfigParser.cpp | 5 +- Library/MeasureCPU.cpp | 247 +++++++++++++++++--- Library/MeasureCPU.h | 38 ++-- Library/MeasureNet.cpp | 440 +++++++++++++++++++++++++++++------- Library/MeasureNet.h | 154 ++++++++++++- Library/MeasureNetIn.cpp | 8 +- Library/MeasureNetIn.h | 2 +- Library/MeasureNetOut.cpp | 8 +- Library/MeasureNetOut.h | 2 +- Library/MeasureNetTotal.cpp | 8 +- Library/MeasureNetTotal.h | 2 +- Library/MeterWindow.cpp | 235 +++++++++++-------- Library/Rainmeter.cpp | 10 + Library/Rainmeter.h | 2 + 15 files changed, 910 insertions(+), 257 deletions(-) diff --git a/Application/Application.cpp b/Application/Application.cpp index f640abe8..e530b9e4 100644 --- a/Application/Application.cpp +++ b/Application/Application.cpp @@ -29,7 +29,7 @@ */ BOOL InitApplication(HINSTANCE hInstance, const WCHAR* WinClass); HWND InitInstance(HINSTANCE hInstance, const WCHAR* WinClass, const WCHAR* WinName); -LONG APIENTRY MainWndProc(HWND, UINT, UINT, LONG); +LRESULT CALLBACK MainWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam); void Bang(const WCHAR* command); /* @@ -193,7 +193,7 @@ void Bang(const WCHAR* command) ** The main window procedure ** */ -LONG APIENTRY MainWndProc(HWND hWnd, UINT message, UINT wParam, LONG lParam) +LRESULT CALLBACK MainWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { switch(message) { @@ -215,7 +215,7 @@ LONG APIENTRY MainWndProc(HWND hWnd, UINT message, UINT wParam, LONG lParam) break; default: - return (LONG)DefWindowProc(hWnd, message, wParam, lParam); + return DefWindowProc(hWnd, message, wParam, lParam); } return 0; diff --git a/Library/ConfigParser.cpp b/Library/ConfigParser.cpp index 9f066a5a..d37f29b6 100644 --- a/Library/ConfigParser.cpp +++ b/Library/ConfigParser.cpp @@ -767,7 +767,10 @@ Color CConfigParser::ParseColor(LPCTSTR string) */ void CConfigParser::ReadIniFile(const std::wstring& iniFile, int depth) { - // DebugLog(L"Reading file: %s", iniFile.c_str()); + if (CRainmeter::GetDebug()) + { + DebugLog(L"Reading file: %s", iniFile.c_str()); + } if (depth > 100) // Is 100 enough to assume the include loop never ends? { diff --git a/Library/MeasureCPU.cpp b/Library/MeasureCPU.cpp index 2b68a7f6..de6a1dbb 100644 --- a/Library/MeasureCPU.cpp +++ b/Library/MeasureCPU.cpp @@ -19,12 +19,15 @@ #include "StdAfx.h" #include "MeasureCPU.h" #include "Rainmeter.h" +#include "Error.h" -#define SystemBasicInformation 0 -#define SystemPerformanceInformation 2 -#define SystemTimeInformation 3 +#define STATUS_SUCCESS 0 +#define STATUS_INFO_LENGTH_MISMATCH 0xC0000004 + +#define SystemProcessorPerformanceInformation 8 #define Li2Double(x) ((double)((x).HighPart) * 4.294967296E9 + (double)((x).LowPart)) +#define Ft2Double(x) ((double)((x).dwHighDateTime) * 4.294967296E9 + (double)((x).dwLowDateTime)) // ntdll!NtQuerySystemInformation (NT specific!) // @@ -57,16 +60,20 @@ CMeasureCPU::CMeasureCPU(CMeterWindow* meterWindow) : CMeasure(meterWindow) m_MinValue = 0.0; m_FirstTime = true; - m_NtQuerySystemInformation = NULL; - m_OldIdleTime.QuadPart = 0; - m_OldSystemTime.QuadPart = 0; + m_Processor = 0; m_NtQuerySystemInformation = (PROCNTQSI)GetProcAddress( GetModuleHandle(L"ntdll"), "NtQuerySystemInformation" ); + m_GetSystemTimes = (PROCGST)GetProcAddress( + GetModuleHandle(L"kernel32"), + "GetSystemTimes" + ); - GetSystemInfo(&m_SystemInfo); + SYSTEM_INFO systemInfo = {0}; + GetSystemInfo(&systemInfo); + m_NumOfProcessors = (int)systemInfo.dwNumberOfProcessors; } /* @@ -92,6 +99,44 @@ CMeasureCPU::~CMeasureCPU() } } +/* +** ReadConfig +** +** Reads the measure specific configs. +** +*/ +void CMeasureCPU::ReadConfig(CConfigParser& parser, const WCHAR* section) +{ + CMeasure::ReadConfig(parser, section); + + int processor = parser.ReadInt(section, L"Processor", 0); + + if (processor < 0 || processor > m_NumOfProcessors) + { + DebugLog(L"[%s] Invalid Processor: %i", section, processor); + + processor = 0; + } + + if (processor != m_Processor) + { + m_Processor = processor; + m_FirstTime = true; + } + + if (m_FirstTime) + { + if (m_Processor == 0 && m_GetSystemTimes == NULL) + { + m_OldTime.assign(m_NumOfProcessors * 2, 0.0); + } + else + { + m_OldTime.assign(2, 0.0); + } + } +} + /* ** Update ** @@ -105,41 +150,95 @@ bool CMeasureCPU::Update() if (CRainmeter::IsNT() != PLATFORM_9X) { - if (m_NtQuerySystemInformation) + if (m_Processor == 0 && m_GetSystemTimes) + { + BOOL status; + FILETIME ftIdleTime, ftKernelTime, ftUserTime; + + // get new CPU's idle/kernel/user time + status = m_GetSystemTimes(&ftIdleTime, &ftKernelTime, &ftUserTime); + if (status == 0) return false; + + CalcUsage(Ft2Double(ftIdleTime), + Ft2Double(ftKernelTime) + Ft2Double(ftUserTime)); + } + else if (m_NtQuerySystemInformation) { - // This code is 'borrowed' from http://www.codepile.com/tric21.shtml - double dbIdleTime; - double dbSystemTime; LONG status; + BYTE* buf = NULL; + ULONG bufSize = 0; - // get new system time - status = m_NtQuerySystemInformation(SystemTimeInformation, &m_SysTimeInfo, sizeof(m_SysTimeInfo), 0); - if (status != NO_ERROR) return false; + int loop = 0; - // get new CPU's idle time - status = m_NtQuerySystemInformation(SystemPerformanceInformation, &m_SysPerfInfo, sizeof(m_SysPerfInfo),NULL); - if (status != NO_ERROR) return false; - - // if it's a first call - skip it - if(!m_FirstTime) + do { - // CurrentValue = NewValue - OldValue - dbIdleTime = Li2Double(m_SysPerfInfo.liIdleTime) - Li2Double(m_OldIdleTime); - dbSystemTime = Li2Double(m_SysTimeInfo.liKeSystemTime) - Li2Double(m_OldSystemTime); + ULONG size = 0; - // CurrentCpuIdle = IdleTime / SystemTime - dbIdleTime = dbIdleTime / dbSystemTime; + status = m_NtQuerySystemInformation(SystemProcessorPerformanceInformation, buf, bufSize, &size); + if (status == STATUS_SUCCESS) break; - // CurrentCpuUsage% = 100 - (CurrentCpuIdle * 100) / NumberOfProcessors - dbIdleTime = 100.0 - dbIdleTime * 100.0 / (double)m_SystemInfo.dwNumberOfProcessors + 0.5; + if (status == STATUS_INFO_LENGTH_MISMATCH) + { + if (size == 0) // Returned required buffer size is always 0 on Windows 2000/XP. + { + if (bufSize == 0) + { + bufSize = sizeof(SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION) * m_NumOfProcessors; + } + else + { + bufSize += sizeof(SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION); + } + } + else + { + if (size != bufSize) + { + bufSize = size; + } + else // ?? + { + bufSize += sizeof(SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION); + } + } - m_Value = min(dbIdleTime, 100.0); - m_Value = max(m_Value, 0.0); - } + if (buf) delete [] buf; + buf = new BYTE[bufSize]; + } + else // failed + { + if (buf) delete [] buf; + return false; + } - // store new CPU's idle and system time - m_OldIdleTime = m_SysPerfInfo.liIdleTime; - m_OldSystemTime = m_SysTimeInfo.liKeSystemTime; + loop++; + } while (loop < 10); + + if (status != STATUS_SUCCESS) // failed + { + if (buf) delete [] buf; + return false; + } + + SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION* systemPerfInfo = (SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION*)buf; + + if (m_Processor == 0) + { + CalcAverageUsage(systemPerfInfo); + } + else + { + int processor = m_Processor - 1; + + CalcUsage(Li2Double(systemPerfInfo[processor].IdleTime), + Li2Double(systemPerfInfo[processor].KernelTime) + Li2Double(systemPerfInfo[processor].UserTime)); + } + + delete [] buf; + } + else + { + return false; } } else @@ -155,7 +254,9 @@ bool CMeasureCPU::Update() RegOpenKeyEx(HKEY_DYN_DATA, L"PerfStats\\StartStat", 0, KEY_ALL_ACCESS, &hkey); dwDataSize = sizeof(dwCpuUsage); RegQueryValueEx(hkey, L"KERNEL\\CPUUsage", NULL, &dwType, (LPBYTE)&dwCpuUsage, &dwDataSize); - RegCloseKey(hkey); + RegCloseKey(hkey); + + m_FirstTime = false; } RegOpenKeyEx(HKEY_DYN_DATA, L"PerfStats\\StatData", 0, KEY_ALL_ACCESS, &hkey); @@ -167,7 +268,81 @@ bool CMeasureCPU::Update() m_CPUFromRegistry = true; } - m_FirstTime = false; - return PostUpdate(); } + +/* +** CalcUsage +** +** Calculates the current CPU utilization value. +** +*/ +void CMeasureCPU::CalcUsage(double idleTime, double systemTime) +{ + if (!m_FirstTime) + { + double dbCpuUsage; + + // CurrentCpuUsage% = 100 - ((IdleTime / SystemTime) * 100) + dbCpuUsage = 100.0 - ((idleTime - m_OldTime[0]) / (systemTime - m_OldTime[1])) * 100.0; + + dbCpuUsage = min(dbCpuUsage, 100.0); + m_Value = max(dbCpuUsage, 0.0); + } + else + { + m_FirstTime = false; + } + + // store new CPU's idle and system time + m_OldTime[0] = idleTime; + m_OldTime[1] = systemTime; +} + +/* +** CalcAverageUsage +** +** Calculates the current CPU average utilization value. +** This function is used if GetSystemTimes function is not available. +** +*/ +void CMeasureCPU::CalcAverageUsage(SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION* systemPerfInfo) +{ + if(!m_FirstTime) + { + double dbIdleTimeDiff = 0, dbSystemTimeDiff = 0; + double dbCpuUsage; + + for (int i = 0; i < m_NumOfProcessors; i++) + { + double dbIdleTime, dbSystemTime; + + dbIdleTime = Li2Double(systemPerfInfo[i].IdleTime); + dbSystemTime = Li2Double(systemPerfInfo[i].KernelTime) + Li2Double(systemPerfInfo[i].UserTime); + + dbIdleTimeDiff += dbIdleTime - m_OldTime[i * 2 + 0]; + dbSystemTimeDiff += dbSystemTime - m_OldTime[i * 2 + 1]; + + // store new CPU's idle and system time + m_OldTime[i * 2 + 0] = dbIdleTime; + m_OldTime[i * 2 + 1] = dbSystemTime; + } + + // CurrentCpuUsage% = 100 - ((IdleTime / SystemTime) * 100) + dbCpuUsage = 100.0 - (dbIdleTimeDiff / dbSystemTimeDiff) * 100.0; + + dbCpuUsage = min(dbCpuUsage, 100.0); + m_Value = max(dbCpuUsage, 0.0); + } + else + { + // store new CPU's idle and system time + for (int i = 0; i < m_NumOfProcessors; i++) + { + m_OldTime[i * 2 + 0] = Li2Double(systemPerfInfo[i].IdleTime); + m_OldTime[i * 2 + 1] = Li2Double(systemPerfInfo[i].KernelTime) + Li2Double(systemPerfInfo[i].UserTime); + } + + m_FirstTime = false; + } +} diff --git a/Library/MeasureCPU.h b/Library/MeasureCPU.h index 7389dc93..6bcb4ed5 100644 --- a/Library/MeasureCPU.h +++ b/Library/MeasureCPU.h @@ -21,22 +21,16 @@ #include "Measure.h" -typedef struct -{ - LARGE_INTEGER liIdleTime; - DWORD dwSpare[76]; -} SYSTEM_PERFORMANCE_INFORMATION; - -typedef struct -{ - LARGE_INTEGER liKeBootTime; - LARGE_INTEGER liKeSystemTime; - LARGE_INTEGER liExpTimeZoneBias; - ULONG uCurrentTimeZoneId; - DWORD dwReserved; -} SYSTEM_TIME_INFORMATION; +typedef struct _SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION { + LARGE_INTEGER IdleTime; + LARGE_INTEGER KernelTime; + LARGE_INTEGER UserTime; + LARGE_INTEGER Reserved1[2]; + ULONG Reserved2; +} SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION, *PSYSTEM_PROCESSOR_PERFORMANCE_INFORMATION; typedef LONG (WINAPI *PROCNTQSI)(UINT,PVOID,ULONG,PULONG); +typedef BOOL (WINAPI *PROCGST)(LPFILETIME lpIdleTime, LPFILETIME lpKernelTime, LPFILETIME lpUserTime); class CMeasureCPU : public CMeasure { @@ -44,19 +38,23 @@ public: CMeasureCPU(CMeterWindow* meterWindow); virtual ~CMeasureCPU(); + virtual void ReadConfig(CConfigParser& parser, const WCHAR* section); virtual bool Update(); protected: + void CalcUsage(double idleTime, double systemTime); + void CalcAverageUsage(SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION* systemPerfInfo); + bool m_CPUFromRegistry; bool m_FirstTime; - PROCNTQSI m_NtQuerySystemInformation; + int m_Processor; + int m_NumOfProcessors; - SYSTEM_PERFORMANCE_INFORMATION m_SysPerfInfo; - SYSTEM_TIME_INFORMATION m_SysTimeInfo; - SYSTEM_INFO m_SystemInfo; - LARGE_INTEGER m_OldIdleTime; - LARGE_INTEGER m_OldSystemTime; + PROCNTQSI m_NtQuerySystemInformation; + PROCGST m_GetSystemTimes; + + std::vector m_OldTime; }; #endif diff --git a/Library/MeasureNet.cpp b/Library/MeasureNet.cpp index ec565a7e..88c4c271 100644 --- a/Library/MeasureNet.cpp +++ b/Library/MeasureNet.cpp @@ -20,10 +20,15 @@ #include "MeasureNet.h" #include "Rainmeter.h" -MIB_IFTABLE* CMeasureNet::c_Table = NULL; +BYTE* CMeasureNet::c_Table = NULL; UINT CMeasureNet::c_NumOfTables = 0; -std::vector CMeasureNet::c_StatValues; -std::vector CMeasureNet::c_OldStatValues; +std::vector CMeasureNet::c_StatValues; +std::vector CMeasureNet::c_OldStatValues; + +HINSTANCE CMeasureNet::c_IpHlpApiLibrary = NULL; +FPGETIFTABLE2EX CMeasureNet::c_GetIfTable2Ex = NULL; +FPFREEMIBTABLE CMeasureNet::c_FreeMibTable = NULL; +bool CMeasureNet::c_UseNewApi = false; extern CRainmeter* Rainmeter; @@ -49,8 +54,6 @@ CMeasureNet::CMeasureNet(CMeterWindow* meterWindow) : CMeasure(meterWindow) */ CMeasureNet::~CMeasureNet() { - delete [] c_Table; - c_Table = NULL; } /* @@ -88,34 +91,169 @@ bool CMeasureNet::Update() */ void CMeasureNet::UpdateIFTable() { - if(c_Table == NULL) - { - // Gotta reserve few bytes for the tables - DWORD value; - if(GetNumberOfInterfaces(&value) == NO_ERROR) - { - c_NumOfTables = value; + bool logging = false; - if(c_NumOfTables > 0) + if (c_UseNewApi) + { + if (c_Table) + { + c_FreeMibTable(c_Table); + c_Table = NULL; + } + + if (c_GetIfTable2Ex(MibIfTableRaw, (MIB_IF_TABLE2**)&c_Table) == NO_ERROR) + { + MIB_IF_TABLE2* ifTable = (MIB_IF_TABLE2*)c_Table; + + if (c_NumOfTables != ifTable->NumEntries) { - DWORD size = sizeof(MIB_IFTABLE) + sizeof(MIB_IFROW) * c_NumOfTables; - c_Table = (MIB_IFTABLE*)new char[size]; + c_NumOfTables = ifTable->NumEntries; + logging = true; + } + + if (CRainmeter::GetDebug() && logging) + { + DebugLog(L"------------------------------"); + DebugLog(L"* NETWORK-INTERFACE: Count=%i", c_NumOfTables); + + for (size_t i = 0; i < c_NumOfTables; i++) + { + std::wstring type; + switch (ifTable->Table[i].Type) + { + case IF_TYPE_ETHERNET_CSMACD: + type += L"Ethernet"; + break; + case IF_TYPE_PPP: + type += L"PPP"; + break; + case IF_TYPE_SOFTWARE_LOOPBACK: + type += L"Loopback"; + break; + case IF_TYPE_IEEE80211: + type += L"IEEE802.11"; + break; + case IF_TYPE_TUNNEL: + type += L"Tunnel"; + break; + case IF_TYPE_IEEE1394: + type += L"IEEE1394"; + break; + default: + type += L"Other"; + break; + } + + DebugLog(L"%i: %s", i + 1, ifTable->Table[i].Description); + DebugLog(L" Type=%s(%i), Hardware=%s, Filter=%s", + type.c_str(), ifTable->Table[i].Type, + (ifTable->Table[i].InterfaceAndOperStatusFlags.HardwareInterface == 1) ? L"Yes" : L"No", + (ifTable->Table[i].InterfaceAndOperStatusFlags.FilterInterface == 1) ? L"Yes" : L"No"); + } + DebugLog(L"------------------------------"); } } - } - - if(c_Table) - { - DWORD size = sizeof(MIB_IFTABLE) + sizeof(MIB_IFROW) * c_NumOfTables; - if(GetIfTable(c_Table, &size, false) != NO_ERROR) + else { - delete [] c_Table; - c_Table = (MIB_IFTABLE*)new char[size]; - if(GetIfTable(c_Table, &size, false) != NO_ERROR) + // Something's wrong. Unable to get the table. + c_Table = NULL; + c_NumOfTables = 0; + } + } + else + { + if (c_Table == NULL) + { + // Gotta reserve few bytes for the tables + DWORD value = 0; + if (GetNumberOfInterfaces(&value) == NO_ERROR) + { + if (c_NumOfTables != value) + { + c_NumOfTables = value; + logging = true; + } + + if (c_NumOfTables > 0) + { + DWORD size = sizeof(MIB_IFTABLE) + sizeof(MIB_IFROW) * c_NumOfTables; + c_Table = new BYTE[size]; + } + } + } + + if (c_Table) + { + DWORD ret, size = 0; + + MIB_IFTABLE* ifTable = (MIB_IFTABLE*)c_Table; + + if ((ret = GetIfTable(ifTable, &size, FALSE)) == ERROR_INSUFFICIENT_BUFFER) + { + delete [] c_Table; + c_Table = new BYTE[size]; + + ifTable = (MIB_IFTABLE*)c_Table; + + ret = GetIfTable(ifTable, &size, FALSE); + } + + if (ret == NO_ERROR) + { + if (c_NumOfTables != ifTable->dwNumEntries) + { + c_NumOfTables = ifTable->dwNumEntries; + logging = true; + } + + if (CRainmeter::GetDebug() && logging) + { + DebugLog(L"------------------------------"); + DebugLog(L"* NETWORK-INTERFACE: Count=%i", c_NumOfTables); + + for (size_t i = 0; i < c_NumOfTables; i++) + { + std::string desc((char*)ifTable->table[i].bDescr, ifTable->table[i].dwDescrLen); + + std::wstring type; + switch (ifTable->table[i].dwType) + { + case IF_TYPE_ETHERNET_CSMACD: + type += L"Ethernet"; + break; + case IF_TYPE_PPP: + type += L"PPP"; + break; + case IF_TYPE_SOFTWARE_LOOPBACK: + type += L"Loopback"; + break; + case IF_TYPE_IEEE80211: + type += L"IEEE802.11"; + break; + case IF_TYPE_TUNNEL: + type += L"Tunnel"; + break; + case IF_TYPE_IEEE1394: + type += L"IEEE1394"; + break; + default: + type += L"Other"; + break; + } + + DebugLog(L"%i: %s", i + 1, ConvertToWide(desc.c_str()).c_str()); + DebugLog(L" Type=%s(%i)", + type.c_str(), ifTable->table[i].dwType); + } + DebugLog(L"------------------------------"); + } + } + else { // Something's wrong. Unable to get the table. delete [] c_Table; c_Table = NULL; + c_NumOfTables = 0; } } } @@ -128,31 +266,58 @@ void CMeasureNet::UpdateIFTable() ** the net-parameter informs which inherited class called this method. ** */ -DWORD CMeasureNet::GetNetOctets(NET net) +ULONG64 CMeasureNet::GetNetOctets(NET net) { - DWORD value = 0; + ULONG64 value = 0; - if (m_Interface == 0) + if (c_UseNewApi) { - // Get all interfaces - for(UINT i = 0; i < c_NumOfTables; i++) + MIB_IF_ROW2* table = (MIB_IF_ROW2*)((MIB_IF_TABLE2*)c_Table)->Table; + + if (m_Interface == 0) { - // Ignore the loopback - if(strcmp((char*)c_Table->table[i].bDescr, "MS TCP Loopback interface") != 0) + // Get all interfaces + for (UINT i = 0; i < c_NumOfTables; i++) + { + // Ignore the loopback and non-hardware interfaces + if (table[i].Type == IF_TYPE_SOFTWARE_LOOPBACK || + table[i].InterfaceAndOperStatusFlags.HardwareInterface == 0) continue; + + switch (net) + { + case NET_IN: + value += table[i].InOctets; + break; + + case NET_OUT: + value += table[i].OutOctets; + break; + + case NET_TOTAL: + value += table[i].InOctets; + value += table[i].OutOctets; + break; + } + } + } + else + { + // Get the selected interface + if (m_Interface <= c_NumOfTables) { switch (net) { case NET_IN: - value += c_Table->table[i].dwInOctets; + value += table[m_Interface - 1].InOctets; break; case NET_OUT: - value += c_Table->table[i].dwOutOctets; + value += table[m_Interface - 1].OutOctets; break; case NET_TOTAL: - value += c_Table->table[i].dwInOctets; - value += c_Table->table[i].dwOutOctets; + value += table[m_Interface - 1].InOctets; + value += table[m_Interface - 1].OutOctets; break; } } @@ -160,23 +325,53 @@ DWORD CMeasureNet::GetNetOctets(NET net) } else { - // Get the selected interface - if (m_Interface <= c_NumOfTables) + MIB_IFROW* table = (MIB_IFROW*)((MIB_IFTABLE*)c_Table)->table; + + if (m_Interface == 0) { - switch (net) + // Get all interfaces + for (UINT i = 0; i < c_NumOfTables; i++) { - case NET_IN: - value += c_Table->table[m_Interface - 1].dwInOctets; - break; + // Ignore the loopback + if (table[i].dwType == IF_TYPE_SOFTWARE_LOOPBACK) continue; - case NET_OUT: - value += c_Table->table[m_Interface - 1].dwOutOctets; - break; + switch (net) + { + case NET_IN: + value += table[i].dwInOctets; + break; - case NET_TOTAL: - value += c_Table->table[m_Interface - 1].dwInOctets; - value += c_Table->table[m_Interface - 1].dwOutOctets; - break; + case NET_OUT: + value += table[i].dwOutOctets; + break; + + case NET_TOTAL: + value += table[i].dwInOctets; + value += table[i].dwOutOctets; + break; + } + } + } + else + { + // Get the selected interface + if (m_Interface <= c_NumOfTables) + { + switch (net) + { + case NET_IN: + value += table[m_Interface - 1].dwInOctets; + break; + + case NET_OUT: + value += table[m_Interface - 1].dwOutOctets; + break; + + case NET_TOTAL: + value += table[m_Interface - 1].dwInOctets; + value += table[m_Interface - 1].dwOutOctets; + break; + } } } } @@ -190,29 +385,42 @@ DWORD CMeasureNet::GetNetOctets(NET net) ** Returns the stats value of the interface ** */ -LARGE_INTEGER CMeasureNet::GetNetStatsValue(NET net) +ULONG64 CMeasureNet::GetNetStatsValue(NET net) { - LARGE_INTEGER value; - value.QuadPart = 0; + ULONG64 value = 0; if (m_Interface == 0) { // Get all interfaces for(size_t i = 0; i < c_StatValues.size() / 2; i++) { + // Ignore the loopback and non-hardware interfaces + if (c_NumOfTables == c_StatValues.size() / 2) + { + if (c_UseNewApi) + { + if (((MIB_IF_TABLE2*)c_Table)->Table[i].Type == IF_TYPE_SOFTWARE_LOOPBACK || + ((MIB_IF_TABLE2*)c_Table)->Table[i].InterfaceAndOperStatusFlags.HardwareInterface == 0) continue; + } + else + { + if (((MIB_IFTABLE*)c_Table)->table[i].dwType == IF_TYPE_SOFTWARE_LOOPBACK) continue; + } + } + switch (net) { case NET_IN: - value.QuadPart += c_StatValues[i * 2 + 0].QuadPart; + value += c_StatValues[i * 2 + 0]; break; case NET_OUT: - value.QuadPart += c_StatValues[i * 2 + 1].QuadPart; + value += c_StatValues[i * 2 + 1]; break; case NET_TOTAL: - value.QuadPart += c_StatValues[i * 2 + 0].QuadPart; - value.QuadPart += c_StatValues[i * 2 + 1].QuadPart; + value += c_StatValues[i * 2 + 0]; + value += c_StatValues[i * 2 + 1]; break; } } @@ -225,16 +433,16 @@ LARGE_INTEGER CMeasureNet::GetNetStatsValue(NET net) switch (net) { case NET_IN: - value.QuadPart += c_StatValues[m_Interface * 2 + 0].QuadPart; + value += c_StatValues[(m_Interface - 1) * 2 + 0]; break; case NET_OUT: - value.QuadPart += c_StatValues[m_Interface * 2 + 1].QuadPart; + value += c_StatValues[(m_Interface - 1) * 2 + 1]; break; case NET_TOTAL: - value.QuadPart += c_StatValues[m_Interface * 2 + 0].QuadPart; - value.QuadPart += c_StatValues[m_Interface * 2 + 1].QuadPart; + value += c_StatValues[(m_Interface - 1) * 2 + 0]; + value += c_StatValues[(m_Interface - 1) * 2 + 1]; break; } } @@ -309,34 +517,40 @@ void CMeasureNet::UpdateStats() if (c_Table) { // Fill the vectors - while (c_StatValues.size() < c_Table->dwNumEntries * 2) + while (c_StatValues.size() < c_NumOfTables * 2) { - LARGE_INTEGER value; - value.QuadPart = 0; - c_StatValues.push_back(value); + c_StatValues.push_back(0); } - while (c_OldStatValues.size() < c_Table->dwNumEntries * 2) + while (c_OldStatValues.size() < c_NumOfTables * 2) { c_OldStatValues.push_back(0); } - for (UINT i = 0; i < c_Table->dwNumEntries; i++) + for (UINT i = 0; i < c_NumOfTables; i++) { - DWORD in, out; + ULONG64 in, out; - in = c_Table->table[i].dwInOctets; - out = c_Table->table[i].dwOutOctets; + if (c_UseNewApi) + { + in = (DWORD)((MIB_IF_TABLE2*)c_Table)->Table[i].InOctets; + out = (DWORD)((MIB_IF_TABLE2*)c_Table)->Table[i].OutOctets; + } + else + { + in = ((MIB_IFTABLE*)c_Table)->table[i].dwInOctets; + out = ((MIB_IFTABLE*)c_Table)->table[i].dwOutOctets; + } if (c_OldStatValues[i * 2 + 0] != 0 && c_OldStatValues[i * 2 + 1] != 0) { if (in > c_OldStatValues[i * 2 + 0]) { - c_StatValues[i * 2 + 0].QuadPart += in - c_OldStatValues[i * 2 + 0]; + c_StatValues[i * 2 + 0] += in - c_OldStatValues[i * 2 + 0]; } if (out > c_OldStatValues[i * 2 + 1]) { - c_StatValues[i * 2 + 1].QuadPart += out - c_OldStatValues[i * 2 + 1]; + c_StatValues[i * 2 + 1] += out - c_OldStatValues[i * 2 + 1]; } } @@ -358,9 +572,7 @@ void CMeasureNet::ResetStats() { for (size_t i = 0; i < c_StatValues.size(); i++) { - LARGE_INTEGER value; - value.QuadPart = 0; - c_StatValues[i] = value; + c_StatValues[i] = 0; } } } @@ -380,19 +592,23 @@ void CMeasureNet::ReadStats(const std::wstring& iniFile) for (int i = 0; i < count; i++) { - LARGE_INTEGER value; + ULARGE_INTEGER value; wsprintf(buffer, L"NetStatsInHigh%i", i + 1); value.HighPart = (DWORD)GetPrivateProfileInt(L"Statistics", buffer, 0, iniFile.c_str()); + wsprintf(buffer, L"NetStatsInLow%i", i + 1); value.LowPart = (DWORD)GetPrivateProfileInt(L"Statistics", buffer, 0, iniFile.c_str()); - c_StatValues.push_back(value); + + c_StatValues.push_back(value.QuadPart); wsprintf(buffer, L"NetStatsOutHigh%i", i + 1); value.HighPart = (DWORD)GetPrivateProfileInt(L"Statistics", buffer, 0, iniFile.c_str()); + wsprintf(buffer, L"NetStatsOutLow%i", i + 1); value.LowPart = (DWORD)GetPrivateProfileInt(L"Statistics", buffer, 0, iniFile.c_str()); - c_StatValues.push_back(value); + + c_StatValues.push_back(value.QuadPart); } } @@ -412,21 +628,85 @@ void CMeasureNet::WriteStats(const std::wstring& iniFile) for (size_t i = 0; i < c_StatValues.size() / 2; i++) { + ULARGE_INTEGER value; + + value.QuadPart = c_StatValues[i * 2]; + wsprintf(buffer2, L"NetStatsInHigh%i", i + 1); - wsprintf(buffer, L"%u", c_StatValues[i * 2].HighPart); + wsprintf(buffer, L"%u", value.HighPart); WritePrivateProfileString(L"Statistics", buffer2, buffer, iniFile.c_str()); wsprintf(buffer2, L"NetStatsInLow%i", i + 1); - wsprintf(buffer, L"%u", c_StatValues[i * 2].LowPart); + wsprintf(buffer, L"%u", value.LowPart); WritePrivateProfileString(L"Statistics", buffer2, buffer, iniFile.c_str()); + value.QuadPart = c_StatValues[i * 2 + 1]; + wsprintf(buffer2, L"NetStatsOutHigh%i", i + 1); - wsprintf(buffer, L"%u", c_StatValues[i * 2 + 1].HighPart); + wsprintf(buffer, L"%u", value.HighPart); WritePrivateProfileString(L"Statistics", buffer2, buffer, iniFile.c_str()); wsprintf(buffer2, L"NetStatsOutLow%i", i + 1); - wsprintf(buffer, L"%u", c_StatValues[i * 2 + 1].LowPart); + wsprintf(buffer, L"%u", value.LowPart); WritePrivateProfileString(L"Statistics", buffer2, buffer, iniFile.c_str()); } } +/* +** InitializeNewApi +** +** Prepares in order to use the new APIs which are available on Vista or newer. +** +*/ +void CMeasureNet::InitializeNewApi() +{ + if (c_IpHlpApiLibrary == NULL) + { + c_IpHlpApiLibrary = LoadLibrary(L"IpHlpApi.dll"); + if (c_IpHlpApiLibrary) + { + c_GetIfTable2Ex = (FPGETIFTABLE2EX)GetProcAddress(c_IpHlpApiLibrary, "GetIfTable2Ex"); + c_FreeMibTable = (FPFREEMIBTABLE)GetProcAddress(c_IpHlpApiLibrary, "FreeMibTable"); + } + + c_UseNewApi = (c_IpHlpApiLibrary && c_GetIfTable2Ex && c_FreeMibTable); + + if (!c_UseNewApi) + { + if (c_IpHlpApiLibrary) + { + FreeLibrary(c_IpHlpApiLibrary); + c_IpHlpApiLibrary = NULL; + } + c_GetIfTable2Ex = NULL; + c_FreeMibTable = NULL; + } + } +} + +/* +** FinalizeNewApi +** +** Frees the resources. +** +*/ +void CMeasureNet::FinalizeNewApi() +{ + if (c_UseNewApi) + { + c_FreeMibTable(c_Table); + + FreeLibrary(c_IpHlpApiLibrary); + c_IpHlpApiLibrary = NULL; + c_GetIfTable2Ex = NULL; + c_FreeMibTable = NULL; + } + else + { + delete [] c_Table; + } + c_Table = NULL; + c_NumOfTables = 0; + + c_UseNewApi = false; +} diff --git a/Library/MeasureNet.h b/Library/MeasureNet.h index 7ed1053e..11384ed7 100644 --- a/Library/MeasureNet.h +++ b/Library/MeasureNet.h @@ -22,6 +22,142 @@ #include "Measure.h" #include +// +// Medium the Ndis Driver is running on (OID_GEN_MEDIA_SUPPORTED/ OID_GEN_MEDIA_IN_USE). +// +typedef enum _NDIS_MEDIUM +{ + NdisMedium802_3, + NdisMedium802_5, + NdisMediumFddi, + NdisMediumWan, + NdisMediumLocalTalk, + NdisMediumDix, // defined for convenience, not a real medium + NdisMediumArcnetRaw, + NdisMediumArcnet878_2, + NdisMediumAtm, + NdisMediumWirelessWan, + NdisMediumIrda, + NdisMediumBpc, + NdisMediumCoWan, + NdisMedium1394, + NdisMediumInfiniBand, +#if ((NTDDI_VERSION >= NTDDI_LONGHORN) || NDIS_SUPPORT_NDIS6) + NdisMediumTunnel, + NdisMediumNative802_11, + NdisMediumLoopback, +#endif // (NTDDI_VERSION >= NTDDI_LONGHORN) + NdisMediumMax // Not a real medium, defined as an upper-bound +} NDIS_MEDIUM, *PNDIS_MEDIUM; + +// +// Physical Medium Type definitions. Used with OID_GEN_PHYSICAL_MEDIUM. +// +typedef enum _NDIS_PHYSICAL_MEDIUM +{ + NdisPhysicalMediumUnspecified, + NdisPhysicalMediumWirelessLan, + NdisPhysicalMediumCableModem, + NdisPhysicalMediumPhoneLine, + NdisPhysicalMediumPowerLine, + NdisPhysicalMediumDSL, // includes ADSL and UADSL (G.Lite) + NdisPhysicalMediumFibreChannel, + NdisPhysicalMedium1394, + NdisPhysicalMediumWirelessWan, + NdisPhysicalMediumNative802_11, + NdisPhysicalMediumBluetooth, + NdisPhysicalMediumInfiniband, + NdisPhysicalMediumWiMax, + NdisPhysicalMediumUWB, + NdisPhysicalMedium802_3, + NdisPhysicalMedium802_5, + NdisPhysicalMediumIrda, + NdisPhysicalMediumWiredWAN, + NdisPhysicalMediumWiredCoWan, + NdisPhysicalMediumOther, + NdisPhysicalMediumMax // Not a real physical type, defined as an upper-bound +} NDIS_PHYSICAL_MEDIUM, *PNDIS_PHYSICAL_MEDIUM; + +typedef struct _MIB_IF_ROW2 { + // + // Key structure. Sorted by preference. + // + NET_LUID InterfaceLuid; + NET_IFINDEX InterfaceIndex; + + // + // Read-Only fields. + // + GUID InterfaceGuid; + WCHAR Alias[IF_MAX_STRING_SIZE + 1]; + WCHAR Description[IF_MAX_STRING_SIZE + 1]; + ULONG PhysicalAddressLength; + UCHAR PhysicalAddress[IF_MAX_PHYS_ADDRESS_LENGTH]; + UCHAR PermanentPhysicalAddress[IF_MAX_PHYS_ADDRESS_LENGTH]; + + ULONG Mtu; + IFTYPE Type; // Interface Type. + TUNNEL_TYPE TunnelType; // Tunnel Type, if Type = IF_TUNNEL. + NDIS_MEDIUM MediaType; + NDIS_PHYSICAL_MEDIUM PhysicalMediumType; + NET_IF_ACCESS_TYPE AccessType; + NET_IF_DIRECTION_TYPE DirectionType; + struct { + BOOLEAN HardwareInterface : 1; + BOOLEAN FilterInterface : 1; + BOOLEAN ConnectorPresent : 1; + BOOLEAN NotAuthenticated : 1; + BOOLEAN NotMediaConnected : 1; + BOOLEAN Paused : 1; + BOOLEAN LowPower : 1; + BOOLEAN EndPointInterface : 1; + } InterfaceAndOperStatusFlags; + + IF_OPER_STATUS OperStatus; + NET_IF_ADMIN_STATUS AdminStatus; + NET_IF_MEDIA_CONNECT_STATE MediaConnectState; + NET_IF_NETWORK_GUID NetworkGuid; + NET_IF_CONNECTION_TYPE ConnectionType; + + // + // Statistics. + // + ULONG64 TransmitLinkSpeed; + ULONG64 ReceiveLinkSpeed; + + ULONG64 InOctets; + ULONG64 InUcastPkts; + ULONG64 InNUcastPkts; + ULONG64 InDiscards; + ULONG64 InErrors; + ULONG64 InUnknownProtos; + ULONG64 InUcastOctets; + ULONG64 InMulticastOctets; + ULONG64 InBroadcastOctets; + ULONG64 OutOctets; + ULONG64 OutUcastPkts; + ULONG64 OutNUcastPkts; + ULONG64 OutDiscards; + ULONG64 OutErrors; + ULONG64 OutUcastOctets; + ULONG64 OutMulticastOctets; + ULONG64 OutBroadcastOctets; + ULONG64 OutQLen; +} MIB_IF_ROW2, *PMIB_IF_ROW2; + +typedef struct _MIB_IF_TABLE2 { + ULONG NumEntries; + MIB_IF_ROW2 Table[ANY_SIZE]; +} MIB_IF_TABLE2, *PMIB_IF_TABLE2; + +typedef enum _MIB_IF_TABLE_LEVEL { + MibIfTableNormal, + MibIfTableRaw +} MIB_IF_TABLE_LEVEL, *PMIB_IF_TABLE_LEVEL; + +typedef NETIO_STATUS (NETIOAPI_API_ * FPGETIFTABLE2EX)(MIB_IF_TABLE_LEVEL Level, PMIB_IF_TABLE2* Table); +typedef VOID (NETIOAPI_API_ * FPFREEMIBTABLE)(PVOID Memory); + class CMeasureNet : public CMeasure { public: @@ -43,10 +179,13 @@ public: static void ReadStats(const std::wstring& iniFile); static void WriteStats(const std::wstring& iniFile); + static void InitializeNewApi(); + static void FinalizeNewApi(); + protected: void ReadConfig(CConfigParser& parser, const WCHAR* section, CMeasureNet::NET net); - DWORD GetNetOctets(NET net); - LARGE_INTEGER GetNetStatsValue(NET net); + ULONG64 GetNetOctets(NET net); + ULONG64 GetNetStatsValue(NET net); double m_CurrentTraffic; double m_TrafficValue; @@ -54,10 +193,15 @@ protected: bool m_Cumulative; std::wstring m_TrafficAction; - static std::vector c_OldStatValues; - static std::vector c_StatValues; - static MIB_IFTABLE* c_Table; + static std::vector c_OldStatValues; + static std::vector c_StatValues; + static BYTE* c_Table; static UINT c_NumOfTables; + + static HINSTANCE c_IpHlpApiLibrary; + static FPGETIFTABLE2EX c_GetIfTable2Ex; + static FPFREEMIBTABLE c_FreeMibTable; + static bool c_UseNewApi; }; #endif diff --git a/Library/MeasureNetIn.cpp b/Library/MeasureNetIn.cpp index fb15c8ef..7109617f 100644 --- a/Library/MeasureNetIn.cpp +++ b/Library/MeasureNetIn.cpp @@ -55,18 +55,18 @@ bool CMeasureNetIn::Update() if (m_Cumulative) { - m_Value = (double)GetNetStatsValue(NET_IN).QuadPart; + m_Value = (double)GetNetStatsValue(NET_IN); } else { - DWORD value = 0; + ULONG64 value = 0; if (!m_FirstTime) { value = GetNetOctets(NET_IN); if (value > m_InOctets) { - DWORD tmpValue = value; + ULONG64 tmpValue = value; value -= m_InOctets; m_InOctets = tmpValue; } @@ -82,7 +82,7 @@ bool CMeasureNetIn::Update() m_FirstTime = false; } - m_Value = value; + m_Value = (double)value; } return PostUpdate(); diff --git a/Library/MeasureNetIn.h b/Library/MeasureNetIn.h index 8f4aee6c..ba996a84 100644 --- a/Library/MeasureNetIn.h +++ b/Library/MeasureNetIn.h @@ -32,7 +32,7 @@ public: private: bool m_FirstTime; - DWORD m_InOctets; + ULONG64 m_InOctets; }; #endif diff --git a/Library/MeasureNetOut.cpp b/Library/MeasureNetOut.cpp index 66e06d34..d3f1e0f5 100644 --- a/Library/MeasureNetOut.cpp +++ b/Library/MeasureNetOut.cpp @@ -55,18 +55,18 @@ bool CMeasureNetOut::Update() if (m_Cumulative) { - m_Value = (double)GetNetStatsValue(NET_OUT).QuadPart; + m_Value = (double)GetNetStatsValue(NET_OUT); } else { - DWORD value = 0; + ULONG64 value = 0; if (!m_FirstTime) { value = GetNetOctets(NET_OUT); if (value > m_OutOctets) { - DWORD tmpValue = value; + ULONG64 tmpValue = value; value -= m_OutOctets; m_OutOctets = tmpValue; } @@ -82,7 +82,7 @@ bool CMeasureNetOut::Update() m_FirstTime = false; } - m_Value = value; + m_Value = (double)value; } return PostUpdate(); diff --git a/Library/MeasureNetOut.h b/Library/MeasureNetOut.h index 9e009cbb..d9f172ee 100644 --- a/Library/MeasureNetOut.h +++ b/Library/MeasureNetOut.h @@ -32,7 +32,7 @@ public: private: bool m_FirstTime; - DWORD m_OutOctets; + ULONG64 m_OutOctets; }; #endif diff --git a/Library/MeasureNetTotal.cpp b/Library/MeasureNetTotal.cpp index 3e051273..563a20a0 100644 --- a/Library/MeasureNetTotal.cpp +++ b/Library/MeasureNetTotal.cpp @@ -55,18 +55,18 @@ bool CMeasureNetTotal::Update() if (m_Cumulative) { - m_Value = (double)GetNetStatsValue(NET_TOTAL).QuadPart; + m_Value = (double)GetNetStatsValue(NET_TOTAL); } else { - DWORD value = 0; + ULONG64 value = 0; if (!m_FirstTime) { value = GetNetOctets(NET_TOTAL); if (value > m_TotalOctets) { - DWORD tmpValue = value; + ULONG64 tmpValue = value; value -= m_TotalOctets; m_TotalOctets = tmpValue; } @@ -82,7 +82,7 @@ bool CMeasureNetTotal::Update() m_FirstTime = false; } - m_Value = value; + m_Value = (double)value; } return PostUpdate(); diff --git a/Library/MeasureNetTotal.h b/Library/MeasureNetTotal.h index bcc76cdd..12cd3698 100644 --- a/Library/MeasureNetTotal.h +++ b/Library/MeasureNetTotal.h @@ -32,7 +32,7 @@ public: private: bool m_FirstTime; - DWORD m_TotalOctets; + ULONG64 m_TotalOctets; }; #endif diff --git a/Library/MeterWindow.cpp b/Library/MeterWindow.cpp index 89866a80..5809da77 100644 --- a/Library/MeterWindow.cpp +++ b/Library/MeterWindow.cpp @@ -936,16 +936,18 @@ BOOL CALLBACK MyInfoEnumProc(HMONITOR hMonitor, HDC hdcMonitor, LPRECT lprcMonit info.cbSize = sizeof(MONITORINFOEX); GetMonitorInfo(hMonitor, &info); - // for debug - DebugLog(info.szDevice); - DebugLog(L" Flags : %s(0x%08X)", (info.dwFlags & MONITORINFOF_PRIMARY) ? L"PRIMARY " : L"", info.dwFlags); - DebugLog(L" Handle : 0x%08X", hMonitor); - DebugLog(L" ScrArea : L=%i, T=%i, R=%i, B=%i (W=%i, H=%i)", - lprcMonitor->left, lprcMonitor->top, lprcMonitor->right, lprcMonitor->bottom, - lprcMonitor->right - lprcMonitor->left, lprcMonitor->bottom - lprcMonitor->top); - DebugLog(L" WorkArea : L=%i, T=%i, R=%i, B=%i (W=%i, H=%i)", - info.rcWork.left, info.rcWork.top, info.rcWork.right, info.rcWork.bottom, - info.rcWork.right - info.rcWork.left, info.rcWork.bottom - info.rcWork.top); + if (CRainmeter::GetDebug()) + { + DebugLog(info.szDevice); + DebugLog(L" Flags : %s(0x%08X)", (info.dwFlags & MONITORINFOF_PRIMARY) ? L"PRIMARY " : L"", info.dwFlags); + DebugLog(L" Handle : 0x%08X", hMonitor); + DebugLog(L" ScrArea : L=%i, T=%i, R=%i, B=%i (W=%i, H=%i)", + lprcMonitor->left, lprcMonitor->top, lprcMonitor->right, lprcMonitor->bottom, + lprcMonitor->right - lprcMonitor->left, lprcMonitor->bottom - lprcMonitor->top); + DebugLog(L" WorkArea : L=%i, T=%i, R=%i, B=%i (W=%i, H=%i)", + info.rcWork.left, info.rcWork.top, info.rcWork.right, info.rcWork.bottom, + info.rcWork.right - info.rcWork.left, info.rcWork.bottom - info.rcWork.top); + } if (m == NULL) return TRUE; if (m->useEnumDisplayDevices) @@ -1019,6 +1021,7 @@ size_t CMeterWindow::GetMonitorCount() void CMeterWindow::SetMultiMonitorInfo() { std::vector& monitors = c_Monitors.monitors; + bool logging = CRainmeter::GetDebug(); if (monitors.capacity() < 16) { monitors.reserve(16); } @@ -1032,8 +1035,11 @@ void CMeterWindow::SetMultiMonitorInfo() c_Monitors.useEnumDisplayDevices = true; c_Monitors.useEnumDisplayMonitors = false; - DebugLog(L"------------------------------"); - DebugLog(L"* EnumDisplayDevices / EnumDisplaySettings API"); + if (logging) + { + DebugLog(L"------------------------------"); + DebugLog(L"* EnumDisplayDevices / EnumDisplaySettings API"); + } DISPLAY_DEVICE dd = {0}; dd.cb = sizeof(DISPLAY_DEVICE); @@ -1044,44 +1050,48 @@ void CMeterWindow::SetMultiMonitorInfo() do { - DebugLog(dd.DeviceName); - std::wstring msg; - if (dd.StateFlags & DISPLAY_DEVICE_ACTIVE) + + if (logging) { - msg += L"ACTIVE "; - } - if (dd.StateFlags & DISPLAY_DEVICE_MULTI_DRIVER) - { - msg += L"MULTI "; - } - if (dd.StateFlags & DISPLAY_DEVICE_PRIMARY_DEVICE) - { - msg += L"PRIMARY "; - } - if (dd.StateFlags & DISPLAY_DEVICE_MIRRORING_DRIVER) - { - msg += L"MIRROR "; - } - if (dd.StateFlags & DISPLAY_DEVICE_VGA_COMPATIBLE) - { - msg += L"VGA "; - } - if (dd.StateFlags & DISPLAY_DEVICE_REMOVABLE) - { - msg += L"REMOVABLE "; - } - if (dd.StateFlags & DISPLAY_DEVICE_MODESPRUNED) - { - msg += L"PRUNED "; - } - if (dd.StateFlags & DISPLAY_DEVICE_REMOTE) - { - msg += L"REMOTE "; - } - if (dd.StateFlags & DISPLAY_DEVICE_DISCONNECT) - { - msg += L"DISCONNECT "; + DebugLog(dd.DeviceName); + + if (dd.StateFlags & DISPLAY_DEVICE_ACTIVE) + { + msg += L"ACTIVE "; + } + if (dd.StateFlags & DISPLAY_DEVICE_MULTI_DRIVER) + { + msg += L"MULTI "; + } + if (dd.StateFlags & DISPLAY_DEVICE_PRIMARY_DEVICE) + { + msg += L"PRIMARY "; + } + if (dd.StateFlags & DISPLAY_DEVICE_MIRRORING_DRIVER) + { + msg += L"MIRROR "; + } + if (dd.StateFlags & DISPLAY_DEVICE_VGA_COMPATIBLE) + { + msg += L"VGA "; + } + if (dd.StateFlags & DISPLAY_DEVICE_REMOVABLE) + { + msg += L"REMOVABLE "; + } + if (dd.StateFlags & DISPLAY_DEVICE_MODESPRUNED) + { + msg += L"PRUNED "; + } + if (dd.StateFlags & DISPLAY_DEVICE_REMOTE) + { + msg += L"REMOTE "; + } + if (dd.StateFlags & DISPLAY_DEVICE_DISCONNECT) + { + msg += L"DISCONNECT "; + } } if ((dd.StateFlags & DISPLAY_DEVICE_MIRRORING_DRIVER) == 0) @@ -1100,12 +1110,20 @@ void CMeterWindow::SetMultiMonitorInfo() if (ddm.StateFlags & DISPLAY_DEVICE_ACTIVE && ddm.StateFlags & DISPLAY_DEVICE_ATTACHED) { wcsncpy(monitor.monitorName, ddm.DeviceString, 128); - DebugLog(L" Name : %s", ddm.DeviceString); + + if (logging) + { + DebugLog(L" Name : %s", ddm.DeviceString); + } break; } } - DebugLog(L" Adapter : %s", dd.DeviceString); - DebugLog(L" Flags : %s(0x%08X)", msg.c_str(), dd.StateFlags); + + if (logging) + { + DebugLog(L" Adapter : %s", dd.DeviceString); + DebugLog(L" Flags : %s(0x%08X)", msg.c_str(), dd.StateFlags); + } if (dd.StateFlags & DISPLAY_DEVICE_ACTIVE) { @@ -1118,7 +1136,11 @@ void CMeterWindow::SetMultiMonitorInfo() { POINT pos = {dm.dmPosition.x, dm.dmPosition.y}; monitor.handle = MonitorFromPoint(pos, MONITOR_DEFAULTTONULL); - DebugLog(L" Handle : 0x%08X", monitor.handle); + + if (logging) + { + DebugLog(L" Handle : 0x%08X", monitor.handle); + } } if (monitor.handle != NULL) @@ -1130,12 +1152,15 @@ void CMeterWindow::SetMultiMonitorInfo() monitor.screen = info.rcMonitor; monitor.work = info.rcWork; - DebugLog(L" ScrArea : L=%i, T=%i, R=%i, B=%i (W=%i, H=%i)", - info.rcMonitor.left, info.rcMonitor.top, info.rcMonitor.right, info.rcMonitor.bottom, - info.rcMonitor.right - info.rcMonitor.left, info.rcMonitor.bottom - info.rcMonitor.top); - DebugLog(L" WorkArea : L=%i, T=%i, R=%i, B=%i (W=%i, H=%i)", - info.rcWork.left, info.rcWork.top, info.rcWork.right, info.rcWork.bottom, - info.rcWork.right - info.rcWork.left, info.rcWork.bottom - info.rcWork.top); + if (logging) + { + DebugLog(L" ScrArea : L=%i, T=%i, R=%i, B=%i (W=%i, H=%i)", + info.rcMonitor.left, info.rcMonitor.top, info.rcMonitor.right, info.rcMonitor.bottom, + info.rcMonitor.right - info.rcMonitor.left, info.rcMonitor.bottom - info.rcMonitor.top); + DebugLog(L" WorkArea : L=%i, T=%i, R=%i, B=%i (W=%i, H=%i)", + info.rcWork.left, info.rcWork.top, info.rcWork.right, info.rcWork.bottom, + info.rcWork.right - info.rcWork.left, info.rcWork.bottom - info.rcWork.top); + } } else // monitor not found { @@ -1157,8 +1182,11 @@ void CMeterWindow::SetMultiMonitorInfo() } else { - DebugLog(L" Adapter : %s", dd.DeviceString); - DebugLog(L" Flags : %s(0x%08X)", msg.c_str(), dd.StateFlags); + if (logging) + { + DebugLog(L" Adapter : %s", dd.DeviceString); + DebugLog(L" Flags : %s(0x%08X)", msg.c_str(), dd.StateFlags); + } } dwDevice++; } while (EnumDisplayDevices(NULL, dwDevice, &dd, 0)); @@ -1171,8 +1199,11 @@ void CMeterWindow::SetMultiMonitorInfo() c_Monitors.useEnumDisplayMonitors = true; } - DebugLog(L"------------------------------"); - DebugLog(L"* EnumDisplayMonitors API"); + if (logging) + { + DebugLog(L"------------------------------"); + DebugLog(L"* EnumDisplayMonitors API"); + } if (c_Monitors.useEnumDisplayMonitors) { @@ -1201,43 +1232,50 @@ void CMeterWindow::SetMultiMonitorInfo() } else { - EnumDisplayMonitors(NULL, NULL, MyInfoEnumProc, (LPARAM)NULL); // Only logging - } - - DebugLog(L"------------------------------"); - std::wstring method = L"* METHOD: "; - if (c_Monitors.useEnumDisplayDevices) - { - method += L"EnumDisplayDevices + "; - method += c_Monitors.useEnumDisplayMonitors ? L"EnumDisplayMonitors Mode" : L"EnumDisplaySettings Mode"; - } - else - { - method += c_Monitors.useEnumDisplayMonitors ? L"EnumDisplayMonitors Mode" : L"Dummy Mode"; - } - DebugLog(method.c_str()); - - DebugLog(L"* MONITORS: Count=%i, Primary=@%i", monitors.size(), c_Monitors.primary); - DebugLog(L"@0: Virtual screen"); - DebugLog(L" L=%i, T=%i, R=%i, B=%i (W=%i, H=%i)", - c_Monitors.vsL, c_Monitors.vsT, c_Monitors.vsL + c_Monitors.vsW, c_Monitors.vsT + c_Monitors.vsH, - c_Monitors.vsW, c_Monitors.vsH); - - for (size_t i = 0; i < monitors.size(); i++) - { - if (monitors[i].active) + if (logging) { - DebugLog(L"@%i: %s (active), MonitorName: %s", i + 1, monitors[i].deviceName, monitors[i].monitorName); - DebugLog(L" L=%i, T=%i, R=%i, B=%i (W=%i, H=%i)", - monitors[i].screen.left, monitors[i].screen.top, monitors[i].screen.right, monitors[i].screen.bottom, - monitors[i].screen.right - monitors[i].screen.left, monitors[i].screen.bottom - monitors[i].screen.top); + EnumDisplayMonitors(NULL, NULL, MyInfoEnumProc, (LPARAM)NULL); // Only logging + } + } + + if (logging) + { + DebugLog(L"------------------------------"); + + std::wstring method = L"* METHOD: "; + if (c_Monitors.useEnumDisplayDevices) + { + method += L"EnumDisplayDevices + "; + method += c_Monitors.useEnumDisplayMonitors ? L"EnumDisplayMonitors Mode" : L"EnumDisplaySettings Mode"; } else { - DebugLog(L"@%i: %s (inactive), MonitorName: %s", i + 1, monitors[i].deviceName, monitors[i].monitorName); + method += c_Monitors.useEnumDisplayMonitors ? L"EnumDisplayMonitors Mode" : L"Dummy Mode"; } + DebugLog(method.c_str()); + + DebugLog(L"* MONITORS: Count=%i, Primary=@%i", monitors.size(), c_Monitors.primary); + DebugLog(L"@0: Virtual screen"); + DebugLog(L" L=%i, T=%i, R=%i, B=%i (W=%i, H=%i)", + c_Monitors.vsL, c_Monitors.vsT, c_Monitors.vsL + c_Monitors.vsW, c_Monitors.vsT + c_Monitors.vsH, + c_Monitors.vsW, c_Monitors.vsH); + + for (size_t i = 0; i < monitors.size(); i++) + { + if (monitors[i].active) + { + DebugLog(L"@%i: %s (active), MonitorName: %s", i + 1, monitors[i].deviceName, monitors[i].monitorName); + DebugLog(L" L=%i, T=%i, R=%i, B=%i (W=%i, H=%i)", + monitors[i].screen.left, monitors[i].screen.top, monitors[i].screen.right, monitors[i].screen.bottom, + monitors[i].screen.right - monitors[i].screen.left, monitors[i].screen.bottom - monitors[i].screen.top); + } + else + { + DebugLog(L"@%i: %s (inactive), MonitorName: %s", i + 1, monitors[i].deviceName, monitors[i].monitorName); + } + } + DebugLog(L"------------------------------"); } - DebugLog(L"------------------------------"); } /* UpdateWorkareaInfo @@ -1265,10 +1303,13 @@ void CMeterWindow::UpdateWorkareaInfo() monitors[i].work = info.rcWork; - DebugLog(L"WorkArea @%i : L=%i, T=%i, R=%i, B=%i (W=%i, H=%i)", - i + 1, - info.rcWork.left, info.rcWork.top, info.rcWork.right, info.rcWork.bottom, - info.rcWork.right - info.rcWork.left, info.rcWork.bottom - info.rcWork.top); + if (CRainmeter::GetDebug()) + { + DebugLog(L"WorkArea @%i : L=%i, T=%i, R=%i, B=%i (W=%i, H=%i)", + i + 1, + info.rcWork.left, info.rcWork.top, info.rcWork.right, info.rcWork.bottom, + info.rcWork.right - info.rcWork.left, info.rcWork.bottom - info.rcWork.top); + } } } } diff --git a/Library/Rainmeter.cpp b/Library/Rainmeter.cpp index 2b4885f9..c9d667c8 100644 --- a/Library/Rainmeter.cpp +++ b/Library/Rainmeter.cpp @@ -598,6 +598,7 @@ void RainmeterSetVariable(HWND, const char* arg) // ----------------------------------------------------------------------------------------------- GlobalConfig CRainmeter::c_GlobalConfig; +bool CRainmeter::c_Debug = false; /* ** CRainmeter @@ -610,6 +611,8 @@ CRainmeter::CRainmeter() c_GlobalConfig.netInSpeed = 0; c_GlobalConfig.netOutSpeed = 0; + c_Debug = false; + m_DesktopWorkAreaChanged = false; m_DesktopWorkArea.left = m_DesktopWorkArea.top = m_DesktopWorkArea.right = m_DesktopWorkArea.bottom = 0; @@ -655,6 +658,8 @@ CRainmeter::~CRainmeter() WriteStats(true); + CMeasureNet::FinalizeNewApi(); + CMeterString::FreeFontCache(); GdiplusShutdown(m_GDIplusToken); @@ -879,6 +884,8 @@ int CRainmeter::Initialize(HWND Parent, HINSTANCE Instance, LPCSTR szPath) CheckUpdate(); } + CMeasureNet::InitializeNewApi(); + ResetStats(); ReadStats(); @@ -1771,6 +1778,9 @@ void CRainmeter::ExecuteCommand(const WCHAR* command, CMeterWindow* meterWindow) */ void CRainmeter::ReadGeneralSettings(std::wstring& iniFile) { + // Read Debug first + c_Debug = 0!=GetPrivateProfileInt(L"Rainmeter", L"Debug", 0, iniFile.c_str()); + CConfigParser parser; parser.Initialize(iniFile.c_str(), this); diff --git a/Library/Rainmeter.h b/Library/Rainmeter.h index c2eb22ef..ea69b3d6 100644 --- a/Library/Rainmeter.h +++ b/Library/Rainmeter.h @@ -136,6 +136,7 @@ public: static void SetCommandLine(LPCTSTR CmdLine) { c_CmdLine = CmdLine;}; static LPCTSTR GetCommandLine() { return c_CmdLine.c_str(); }; static GlobalConfig& GetGlobalConfig() { return c_GlobalConfig; }; + static bool GetDebug() { return c_Debug; } void ReloadSettings(); void SaveSettings(); @@ -227,6 +228,7 @@ private: static bool c_DummyLitestep; // true, if not a Litestep plugin static std::wstring c_CmdLine; // The command line arguments static GlobalConfig c_GlobalConfig; + static bool c_Debug; }; #ifdef LIBRARY_EXPORTS