2012-07-13 22:27:12 +02:00
/* HexChat
* Copyright ( c ) 2011 - 2012 Berke Viktor .
2011-11-27 19:38:37 +01:00
*
* Permission is hereby granted , free of charge , to any person obtaining a copy
* of this software and associated documentation files ( the " Software " ) , to deal
* in the Software without restriction , including without limitation the rights
* to use , copy , modify , merge , publish , distribute , sublicense , and / or sell
* copies of the Software , and to permit persons to whom the Software is
* furnished to do so , subject to the following conditions :
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software .
*
* THE SOFTWARE IS PROVIDED " AS IS " , WITHOUT WARRANTY OF ANY KIND , EXPRESS OR
* IMPLIED , INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY ,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT . IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM , DAMAGES OR OTHER
* LIABILITY , WHETHER IN AN ACTION OF CONTRACT , TORT OR OTHERWISE , ARISING FROM ,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE .
*/
# include <stdio.h>
# include <windows.h>
2011-11-28 20:22:59 +01:00
# include <comutil.h>
# include <wbemidl.h>
2011-11-27 19:38:37 +01:00
# include "xchat-plugin.h"
static xchat_plugin * ph ; /* plugin handle */
2012-10-21 06:40:28 +02:00
static char name [ ] = " SysInfo " ;
2011-12-02 01:09:52 +01:00
static char desc [ ] = " Display info about your hardware and OS " ;
2011-12-06 02:36:26 +01:00
static char version [ ] = " 1.1 " ;
2011-12-01 23:01:52 +01:00
static int firstRun ;
static char * wmiOs ;
static char * wmiCpu ;
static char * wmiVga ;
2011-11-27 19:38:37 +01:00
2011-11-29 01:10:57 +01:00
static int
getCpuArch ( void )
{
OSVERSIONINFOEX osvi ;
SYSTEM_INFO si ;
osvi . dwOSVersionInfoSize = sizeof ( OSVERSIONINFOEX ) ;
GetVersionEx ( ( LPOSVERSIONINFOW ) & osvi ) ;
GetSystemInfo ( & si ) ;
if ( si . wProcessorArchitecture = = 9 )
{
return 64 ;
}
else
{
return 86 ;
}
}
#if 0
2011-12-06 02:35:00 +01:00
/* use WMI instead, wProcessorArchitecture displays current binary arch instead of OS arch anyway */
2011-11-27 19:38:37 +01:00
static char *
getOsName ( void )
{
static char winver [ 32 ] ;
double mhz ;
OSVERSIONINFOEX osvi ;
SYSTEM_INFO si ;
osvi . dwOSVersionInfoSize = sizeof ( OSVERSIONINFOEX ) ;
2011-11-28 22:54:17 +01:00
GetVersionEx ( ( LPOSVERSIONINFOW ) & osvi ) ;
2011-11-27 19:38:37 +01:00
GetSystemInfo ( & si ) ;
strcpy ( winver , " Windows " ) ;
switch ( osvi . dwMajorVersion )
{
case 5 :
switch ( osvi . dwMinorVersion )
{
case 1 :
strcat ( winver , " XP " ) ;
break ;
case 2 :
if ( osvi . wProductType = = VER_NT_WORKSTATION )
{
strcat ( winver , " XP x64 Edition " ) ;
}
else
{
if ( GetSystemMetrics ( SM_SERVERR2 ) = = 0 )
{
strcat ( winver , " Server 2003 " ) ;
}
else
{
strcat ( winver , " Server 2003 R2 " ) ;
}
}
break ;
}
break ;
case 6 :
switch ( osvi . dwMinorVersion )
{
case 0 :
if ( osvi . wProductType = = VER_NT_WORKSTATION )
{
strcat ( winver , " Vista " ) ;
}
else
{
strcat ( winver , " Server 2008 " ) ;
}
break ;
case 1 :
if ( osvi . wProductType = = VER_NT_WORKSTATION )
{
strcat ( winver , " 7 " ) ;
}
else
{
strcat ( winver , " Server 2008 R2 " ) ;
}
break ;
case 2 :
if ( osvi . wProductType = = VER_NT_WORKSTATION )
{
strcat ( winver , " 8 " ) ;
}
else
{
strcat ( winver , " 8 Server " ) ;
}
break ;
}
break ;
}
if ( si . wProcessorArchitecture = = 9 )
{
strcat ( winver , " (x64) " ) ;
}
else
{
strcat ( winver , " (x86) " ) ;
}
return winver ;
}
2011-11-29 01:10:57 +01:00
/* x86-only, SDK-only, use WMI instead */
2011-11-28 22:54:17 +01:00
static char *
2011-11-27 19:38:37 +01:00
getCpuName ( void )
{
// Get extended ids.
unsigned int nExIds ;
unsigned int i ;
int CPUInfo [ 4 ] = { - 1 } ;
static char CPUBrandString [ 128 ] ;
__cpuid ( CPUInfo , 0x80000000 ) ;
nExIds = CPUInfo [ 0 ] ;
/* Get the information associated with each extended ID. */
for ( i = 0x80000000 ; i < = nExIds ; + + i )
{
__cpuid ( CPUInfo , i ) ;
if ( i = = 0x80000002 )
{
memcpy ( CPUBrandString , CPUInfo , sizeof ( CPUInfo ) ) ;
}
else if ( i = = 0x80000003 )
{
memcpy ( CPUBrandString + 16 , CPUInfo , sizeof ( CPUInfo ) ) ;
}
else if ( i = = 0x80000004 )
{
memcpy ( CPUBrandString + 32 , CPUInfo , sizeof ( CPUInfo ) ) ;
}
}
return CPUBrandString ;
}
2011-11-28 20:22:59 +01:00
# endif
2011-11-27 19:38:37 +01:00
2011-11-28 22:54:17 +01:00
static char *
2011-11-27 19:38:37 +01:00
getCpuMhz ( void )
{
HKEY hKey ;
int result ;
int data ;
int dataSize ;
double cpuspeed ;
static char buffer [ 16 ] ;
const char * cpuspeedstr ;
if ( RegOpenKeyEx ( HKEY_LOCAL_MACHINE , TEXT ( " Hardware \\ Description \\ System \\ CentralProcessor \\ 0 " ) , 0 , KEY_QUERY_VALUE , & hKey ) = = ERROR_SUCCESS )
{
dataSize = sizeof ( data ) ;
result = RegQueryValueEx ( hKey , TEXT ( " ~MHz " ) , 0 , 0 , ( LPBYTE ) & data , ( LPDWORD ) & dataSize ) ;
RegCloseKey ( hKey ) ;
if ( result = = ERROR_SUCCESS )
{
cpuspeed = ( data > 1000 ) ? data / 1000 : data ;
cpuspeedstr = ( data > 1000 ) ? " GHz " : " MHz " ;
sprintf ( buffer , " %.2f %s " , cpuspeed , cpuspeedstr ) ;
}
}
return buffer ;
}
2011-11-28 22:54:17 +01:00
static char *
2011-11-27 19:38:37 +01:00
getMemoryInfo ( void )
{
2011-11-28 23:11:43 +01:00
static char buffer [ 32 ] ;
2011-11-27 19:38:37 +01:00
MEMORYSTATUSEX meminfo ;
meminfo . dwLength = sizeof ( meminfo ) ;
GlobalMemoryStatusEx ( & meminfo ) ;
2011-11-28 23:41:17 +01:00
sprintf ( buffer , " %I64d MB Total (%I64d MB Free) " , meminfo . ullTotalPhys / 1024 / 1024 , meminfo . ullAvailPhys / 1024 / 1024 ) ;
2011-11-27 19:38:37 +01:00
return buffer ;
}
2011-11-28 22:54:17 +01:00
static char *
2011-11-28 20:22:59 +01:00
getWmiInfo ( int mode )
2011-11-27 19:38:37 +01:00
{
/* for more details about this wonderful API, see
http : //msdn.microsoft.com/en-us/site/aa394138
http : //msdn.microsoft.com/en-us/site/aa390423
http : //msdn.microsoft.com/en-us/library/windows/desktop/aa394138%28v=vs.85%29.aspx
http : //social.msdn.microsoft.com/forums/en-US/vcgeneral/thread/d6420012-e432-4964-8506-6f6b65e5a451
*/
2011-12-01 23:01:52 +01:00
char * buffer = ( char * ) malloc ( 128 ) ;
2011-11-27 19:38:37 +01:00
HRESULT hres ;
HRESULT hr ;
IWbemLocator * pLoc = NULL ;
IWbemServices * pSvc = NULL ;
IEnumWbemClassObject * pEnumerator = NULL ;
IWbemClassObject * pclsObj ;
ULONG uReturn = 0 ;
2011-11-28 22:54:17 +01:00
hres = CoInitializeEx ( 0 , COINIT_APARTMENTTHREADED | COINIT_SPEED_OVER_MEMORY ) ;
2011-11-27 19:38:37 +01:00
if ( FAILED ( hres ) )
{
2011-11-28 22:54:17 +01:00
strcpy ( buffer , " Error Code 0 " ) ;
2011-11-27 19:38:37 +01:00
return buffer ;
}
hres = CoInitializeSecurity ( NULL , - 1 , NULL , NULL , RPC_C_AUTHN_LEVEL_DEFAULT , RPC_C_IMP_LEVEL_IMPERSONATE , NULL , EOAC_NONE , NULL ) ;
2011-11-28 22:54:17 +01:00
/* mysteriously failing after the first execution, but only when used as a plugin, skip it */
/*if (FAILED (hres))
2011-11-27 19:38:37 +01:00
{
CoUninitialize ( ) ;
2011-11-28 22:54:17 +01:00
strcpy ( buffer , " Error Code 1 " ) ;
2011-11-27 19:38:37 +01:00
return buffer ;
2011-11-28 22:54:17 +01:00
} */
2011-11-27 19:38:37 +01:00
hres = CoCreateInstance ( CLSID_WbemLocator , 0 , CLSCTX_INPROC_SERVER , IID_IWbemLocator , ( LPVOID * ) & pLoc ) ;
if ( FAILED ( hres ) )
{
CoUninitialize ( ) ;
2011-11-28 22:54:17 +01:00
strcpy ( buffer , " Error Code 2 " ) ;
2011-11-27 19:38:37 +01:00
return buffer ;
}
hres = pLoc - > ConnectServer ( _bstr_t ( L " root \\ CIMV2 " ) , NULL , NULL , 0 , NULL , 0 , 0 , & pSvc ) ;
if ( FAILED ( hres ) )
{
pLoc - > Release ( ) ;
CoUninitialize ( ) ;
2011-11-28 22:54:17 +01:00
strcpy ( buffer , " Error Code 3 " ) ;
2011-11-27 19:38:37 +01:00
return buffer ;
}
hres = CoSetProxyBlanket ( pSvc , RPC_C_AUTHN_WINNT , RPC_C_AUTHZ_NONE , NULL , RPC_C_AUTHN_LEVEL_CALL , RPC_C_IMP_LEVEL_IMPERSONATE , NULL , EOAC_NONE ) ;
if ( FAILED ( hres ) )
{
pSvc - > Release ( ) ;
pLoc - > Release ( ) ;
CoUninitialize ( ) ;
2011-11-28 22:54:17 +01:00
strcpy ( buffer , " Error Code 4 " ) ;
2011-11-27 19:38:37 +01:00
return buffer ;
}
2011-11-29 01:10:57 +01:00
switch ( mode )
2011-11-28 20:22:59 +01:00
{
2011-11-29 01:10:57 +01:00
case 0 :
hres = pSvc - > ExecQuery ( _bstr_t ( " WQL " ) , _bstr_t ( " SELECT * FROM Win32_OperatingSystem " ) , WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY , NULL , & pEnumerator ) ;
break ;
case 1 :
hres = pSvc - > ExecQuery ( _bstr_t ( " WQL " ) , _bstr_t ( " SELECT * FROM Win32_Processor " ) , WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY , NULL , & pEnumerator ) ;
break ;
case 2 :
hres = pSvc - > ExecQuery ( _bstr_t ( " WQL " ) , _bstr_t ( " SELECT * FROM Win32_VideoController " ) , WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY , NULL , & pEnumerator ) ;
break ;
2011-11-28 20:22:59 +01:00
}
2011-11-27 19:38:37 +01:00
if ( FAILED ( hres ) )
{
pSvc - > Release ( ) ;
pLoc - > Release ( ) ;
CoUninitialize ( ) ;
2011-11-28 22:54:17 +01:00
strcpy ( buffer , " Error Code 5 " ) ;
2011-11-27 19:38:37 +01:00
return buffer ;
}
while ( pEnumerator )
{
hr = pEnumerator - > Next ( WBEM_INFINITE , 1 , & pclsObj , & uReturn ) ;
if ( 0 = = uReturn )
{
break ;
}
VARIANT vtProp ;
2011-11-29 01:10:57 +01:00
switch ( mode )
{
case 0 :
hr = pclsObj - > Get ( L " Caption " , 0 , & vtProp , 0 , 0 ) ;
break ;
case 1 :
hr = pclsObj - > Get ( L " Name " , 0 , & vtProp , 0 , 0 ) ;
break ;
case 2 :
hr = pclsObj - > Get ( L " Name " , 0 , & vtProp , 0 , 0 ) ;
break ;
}
2011-11-27 19:38:37 +01:00
WideCharToMultiByte ( CP_ACP , 0 , vtProp . bstrVal , - 1 , buffer , SysStringLen ( vtProp . bstrVal ) + 1 , NULL , NULL ) ;
VariantClear ( & vtProp ) ;
}
pSvc - > Release ( ) ;
pLoc - > Release ( ) ;
pEnumerator - > Release ( ) ;
pclsObj - > Release ( ) ;
CoUninitialize ( ) ;
return buffer ;
}
static int
2011-11-28 22:54:17 +01:00
printInfo ( char * word [ ] , char * word_eol [ ] , void * user_data )
2011-11-27 19:38:37 +01:00
{
2012-10-21 06:40:28 +02:00
/* query WMI info only at the first time SysInfo is called, then cache it to save time */
2011-12-01 23:01:52 +01:00
if ( firstRun )
{
2011-12-02 01:05:59 +01:00
xchat_printf ( ph , " %s first execution, querying and caching WMI info... \n " , name ) ;
2011-12-01 23:01:52 +01:00
wmiOs = getWmiInfo ( 0 ) ;
wmiCpu = getWmiInfo ( 1 ) ;
wmiVga = getWmiInfo ( 2 ) ;
firstRun = 0 ;
}
2011-11-29 01:10:57 +01:00
if ( xchat_list_int ( ph , NULL , " type " ) > = 2 )
{
2011-12-03 18:52:13 +01:00
/* uptime will work correctly for up to 50 days, should be enough */
2012-10-21 06:40:28 +02:00
xchat_commandf ( ph , " ME ** SysInfo ** Client: HexChat %s (x%d) ** OS: %s ** CPU: %s (%s) ** RAM: %s ** VGA: %s ** Uptime: %.2f Hours ** " ,
2012-07-12 18:39:52 +02:00
xchat_get_info ( ph , " version " ) ,
2011-12-03 18:52:13 +01:00
getCpuArch ( ) ,
wmiOs ,
wmiCpu ,
getCpuMhz ( ) ,
getMemoryInfo ( ) ,
wmiVga , ( float ) GetTickCount ( ) / 1000 / 60 / 60 ) ;
2011-11-29 01:10:57 +01:00
}
else
{
2012-07-12 18:39:52 +02:00
xchat_printf ( ph , " * Client: HexChat %s (x%d) \n " , xchat_get_info ( ph , " version " ) , getCpuArch ( ) ) ;
2011-12-01 23:01:52 +01:00
xchat_printf ( ph , " * OS: %s \n " , wmiOs ) ;
xchat_printf ( ph , " * CPU: %s (%s) \n " , wmiCpu , getCpuMhz ( ) ) ;
2011-11-29 04:05:54 +01:00
xchat_printf ( ph , " * RAM: %s \n " , getMemoryInfo ( ) ) ;
2011-12-01 23:01:52 +01:00
xchat_printf ( ph , " * VGA: %s \n " , wmiVga ) ;
2011-11-29 04:05:54 +01:00
xchat_printf ( ph , " * Uptime: %.2f Hours \n " , ( float ) GetTickCount ( ) / 1000 / 60 / 60 ) ;
2011-11-29 01:10:57 +01:00
}
2011-11-29 04:05:54 +01:00
2011-11-27 19:38:37 +01:00
return XCHAT_EAT_XCHAT ;
}
int
xchat_plugin_init ( xchat_plugin * plugin_handle , char * * plugin_name , char * * plugin_desc , char * * plugin_version , char * arg )
{
ph = plugin_handle ;
2011-12-02 01:05:59 +01:00
* plugin_name = name ;
* plugin_desc = desc ;
* plugin_version = version ;
2011-11-27 19:38:37 +01:00
2011-12-01 23:01:52 +01:00
firstRun = 1 ;
2012-10-21 06:40:28 +02:00
xchat_hook_command ( ph , " SYSINFO " , XCHAT_PRI_NORM , printInfo , NULL , NULL ) ;
xchat_command ( ph , " MENU -ietc \\ system.png ADD \" Window/Display System Info \" \" SYSINFO \" " ) ;
2011-11-27 19:38:37 +01:00
2011-12-02 01:05:59 +01:00
xchat_printf ( ph , " %s plugin loaded \n " , name ) ;
2011-11-27 19:38:37 +01:00
return 1 ; /* return 1 for success */
}
2011-11-28 22:54:17 +01:00
2011-11-27 19:38:37 +01:00
int
xchat_plugin_deinit ( void )
{
xchat_command ( ph , " MENU DEL \" Window/Display System Info \" " ) ;
2011-12-02 01:05:59 +01:00
xchat_printf ( ph , " %s plugin unloaded \n " , name ) ;
2011-11-27 19:38:37 +01:00
return 1 ;
}