mirror of https://github.com/tongzx/nt5src
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1122 lines
27 KiB
1122 lines
27 KiB
|
|
#include "precomp.h"
|
|
#include "arrtempl.h" // for CDeleteMe
|
|
#include "md5wbem.h" // for MD5
|
|
|
|
#include "winmgmt.h"
|
|
#include "wbemdelta.h"
|
|
|
|
#include <tchar.h>
|
|
#include <vector>
|
|
#include <map>
|
|
|
|
CPerfLib::CPerfLib(TCHAR * SvcName):
|
|
m_wstrServiceName(NULL),
|
|
m_wstrFull(NULL),
|
|
m_hKey(NULL),
|
|
m_bOK(FALSE),
|
|
m_pwcsLibrary(NULL),
|
|
m_pwcsOpenProc(NULL),
|
|
m_pwcsCollectProc(NULL),
|
|
m_pwcsCloseProc(NULL)
|
|
{
|
|
|
|
if (SvcName)
|
|
{
|
|
DWORD dwLen = _tcslen(SvcName);
|
|
DWORD dwLenPrefix = _tcslen(_T("SYSTEM\\CurrentControlSet\\Services\\"));
|
|
TCHAR * pStart = SvcName+dwLenPrefix;
|
|
TCHAR * pNameEnd = _tcschr(pStart,_T('\\'));
|
|
if (pNameEnd)
|
|
{
|
|
ULONG_PTR NameLength = (ULONG_PTR)pNameEnd-(ULONG_PTR)pStart;
|
|
NameLength/=sizeof(TCHAR);
|
|
m_wstrServiceName = new TCHAR[NameLength+1];
|
|
if (!m_wstrServiceName)
|
|
{
|
|
return; // OUT_OF_MEMORY
|
|
}
|
|
m_wstrServiceName[NameLength]=0;
|
|
memcpy(m_wstrServiceName,pStart,NameLength*sizeof(TCHAR));
|
|
|
|
m_wstrFull = new TCHAR[dwLen+1];
|
|
if (m_wstrFull)
|
|
{
|
|
lstrcpy(m_wstrFull, SvcName);
|
|
|
|
m_hKey = NULL;
|
|
|
|
if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE,
|
|
m_wstrFull,
|
|
NULL,
|
|
KEY_READ,
|
|
&m_hKey))
|
|
{
|
|
m_pwcsLibrary = NULL;
|
|
m_pwcsOpenProc = NULL;
|
|
m_pwcsCollectProc = NULL;
|
|
m_pwcsCloseProc = NULL;
|
|
m_bOK = TRUE;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
CPerfLib::~CPerfLib()
|
|
{
|
|
if (m_wstrServiceName)
|
|
delete [] m_wstrServiceName;
|
|
if (m_wstrFull)
|
|
delete [] m_wstrFull;
|
|
if (m_pwcsLibrary)
|
|
delete [] m_pwcsLibrary;
|
|
if (m_pwcsOpenProc)
|
|
delete [] m_pwcsOpenProc; // not needed as a member
|
|
if (m_pwcsCollectProc)
|
|
delete [] m_pwcsCollectProc; // not needed as a member
|
|
if (m_pwcsCloseProc)
|
|
delete [] m_pwcsCloseProc; // not needed as a member
|
|
|
|
if (m_hKey)
|
|
RegCloseKey(m_hKey);
|
|
}
|
|
|
|
HRESULT CPerfLib::GetFileSignature( CheckLibStruct * pCheckLib )
|
|
{
|
|
HRESULT hr = WBEM_S_NO_ERROR;
|
|
|
|
if (!pCheckLib){
|
|
return WBEM_E_INVALID_PARAMETER;
|
|
}
|
|
|
|
// Get the current library's file time
|
|
// ===================================
|
|
|
|
HANDLE hFile = NULL;
|
|
|
|
DWORD dwRet = 0;
|
|
WCHAR wszFullPath[MAX_PATH];
|
|
WCHAR* pwcsTemp = NULL;
|
|
|
|
if ( 0 != SearchPathW( NULL, m_pwcsLibrary, NULL, MAX_PATH, wszFullPath, &pwcsTemp ) )
|
|
{
|
|
hFile = CreateFileW( wszFullPath, GENERIC_READ,FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL );
|
|
|
|
if ( INVALID_HANDLE_VALUE != hFile )
|
|
{
|
|
DWORD dwFileSizeLow = 0;
|
|
DWORD dwFileSizeHigh = 0;
|
|
__int32 nFileSize = 0;
|
|
DWORD dwNumRead = 0;
|
|
BYTE* aBuffer = NULL;
|
|
|
|
dwFileSizeLow = GetFileSize( hFile, &dwFileSizeHigh );
|
|
nFileSize = ( dwFileSizeHigh << 32 ) + dwFileSizeLow;
|
|
|
|
FILETIME ft;
|
|
if (GetFileTime(hFile,&ft,NULL,NULL))
|
|
{
|
|
|
|
HANDLE hFileMap = NULL;
|
|
hFileMap = CreateFileMapping(hFile,NULL,PAGE_READONLY,dwFileSizeHigh,dwFileSizeLow,NULL);
|
|
if (hFileMap)
|
|
{
|
|
aBuffer = (BYTE *)MapViewOfFile(hFileMap,
|
|
FILE_MAP_READ,
|
|
0,0,0);
|
|
if (aBuffer)
|
|
{
|
|
//
|
|
// do the real work
|
|
//
|
|
MD5 md5;
|
|
BYTE aSignature[16];
|
|
md5.Transform( aBuffer, nFileSize, aSignature );
|
|
|
|
// return our data
|
|
memcpy(pCheckLib->Signature,aSignature,sizeof(aSignature));
|
|
pCheckLib->FileTime = ft;
|
|
pCheckLib->FileSize = nFileSize;
|
|
|
|
UnmapViewOfFile(aBuffer);
|
|
}
|
|
else
|
|
{
|
|
hr = WBEM_E_OUT_OF_MEMORY;
|
|
}
|
|
CloseHandle(hFileMap);
|
|
}
|
|
else
|
|
{
|
|
hr = WBEM_E_OUT_OF_MEMORY;
|
|
}
|
|
|
|
/*
|
|
aBuffer = new BYTE[nFileSize];
|
|
CDeleteMe<BYTE> dmBuffer( aBuffer );
|
|
|
|
if ( NULL != aBuffer )
|
|
{
|
|
if ( ReadFile( hFile, aBuffer, nFileSize, &dwNumRead, FALSE ) )
|
|
{
|
|
MD5 md5;
|
|
BYTE aSignature[16];
|
|
md5.Transform( aBuffer, dwNumRead, aSignature );
|
|
|
|
// return our data
|
|
memcpy(pCheckLib->Signature,aSignature,sizeof(aSignature));
|
|
pCheckLib->FileTime = ft;
|
|
pCheckLib->FileSize = nFileSize;
|
|
}
|
|
else
|
|
{
|
|
hr = WBEM_E_TOO_MUCH_DATA;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
hr = WBEM_E_OUT_OF_MEMORY;
|
|
}
|
|
*/
|
|
}
|
|
else
|
|
{
|
|
hr = WBEM_E_FAILED;
|
|
}
|
|
|
|
CloseHandle( hFile );
|
|
}
|
|
else
|
|
{
|
|
hr = WBEM_E_FAILED;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
hr = WBEM_E_NOT_FOUND;
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
LONG
|
|
GetBinary(HKEY hKey, TCHAR * Value, BYTE ** ppBuff, DWORD * pdwSize)
|
|
{
|
|
LONG lRet;
|
|
DWORD dwType;
|
|
DWORD dwSize = 0;
|
|
|
|
// null Value is allowed
|
|
if (!ppBuff || !pdwSize)
|
|
return ERROR_INVALID_PARAMETER;
|
|
|
|
lRet = RegQueryValueEx(hKey,
|
|
Value,
|
|
NULL,
|
|
&dwType,
|
|
NULL,
|
|
&dwSize);
|
|
|
|
if ((ERROR_SUCCESS == lRet) &&
|
|
(REG_BINARY == dwType))
|
|
{
|
|
*pdwSize = dwSize;
|
|
|
|
if (dwSize > 0)
|
|
{
|
|
*ppBuff = new BYTE[dwSize];
|
|
if (*ppBuff){
|
|
|
|
lRet = RegQueryValueEx(hKey,
|
|
Value,
|
|
NULL,
|
|
&dwType,
|
|
(BYTE *)(*ppBuff),
|
|
&dwSize);
|
|
} else {
|
|
lRet = ERROR_OUTOFMEMORY;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
lRet = ERROR_INVALID_PARAMETER;
|
|
}
|
|
|
|
return lRet;
|
|
}
|
|
|
|
LONG
|
|
GetDWORD(HKEY hKey, TCHAR * Value ,DWORD * pDword)
|
|
{
|
|
LONG lRet;
|
|
DWORD dwType = 0;
|
|
DWORD dwSize = sizeof(DWORD);
|
|
|
|
if (!pDword)
|
|
return ERROR_INVALID_PARAMETER;
|
|
|
|
lRet = RegQueryValueEx(hKey,
|
|
Value,
|
|
NULL,
|
|
&dwType,
|
|
(BYTE *)pDword,
|
|
&dwSize);
|
|
if ((REG_DWORD == dwType) &&
|
|
(ERROR_SUCCESS == lRet))
|
|
return lRet;
|
|
else
|
|
return ERROR_INVALID_PARAMETER;
|
|
}
|
|
|
|
LONG
|
|
GetStr(HKEY hKey, TCHAR * Value ,TCHAR ** ppStr)
|
|
{
|
|
LONG lRet;
|
|
DWORD dwType;
|
|
DWORD dwSize = 0;
|
|
|
|
if (!ppStr)
|
|
return ERROR_INVALID_PARAMETER;
|
|
|
|
lRet = RegQueryValueEx(hKey,
|
|
Value,
|
|
NULL,
|
|
&dwType,
|
|
NULL,
|
|
&dwSize);
|
|
if ((ERROR_SUCCESS == lRet) &&
|
|
((REG_SZ == dwType) || (REG_EXPAND_SZ == dwType)))
|
|
{
|
|
if (dwSize > 0)
|
|
{
|
|
TCHAR * pString = new TCHAR[dwSize];
|
|
if (pString)
|
|
{
|
|
lRet = RegQueryValueEx(hKey,
|
|
Value,
|
|
NULL,
|
|
&dwType,
|
|
(BYTE *)(pString),
|
|
&dwSize);
|
|
if (ERROR_SUCCESS == lRet)
|
|
{
|
|
if (REG_EXPAND_SZ == dwType)
|
|
{
|
|
TCHAR * pExpanded = new TCHAR[dwSize + MAX_PATH];
|
|
if (pExpanded)
|
|
{
|
|
if(ExpandEnvironmentStrings(pString,pExpanded,(dwSize + MAX_PATH)))
|
|
{
|
|
*ppStr = pExpanded;
|
|
delete [] pString;
|
|
|
|
}
|
|
else
|
|
{
|
|
delete [] pString;
|
|
lRet = ERROR_OUTOFMEMORY;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
delete [] pString;
|
|
lRet = ERROR_OUTOFMEMORY;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
*ppStr = pString;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
goto empty_string;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
lRet = ERROR_OUTOFMEMORY;
|
|
}
|
|
}
|
|
else // empty string
|
|
{
|
|
empty_string:
|
|
*ppStr = new TCHAR[sizeof(_T(""))];
|
|
if (*ppStr) {
|
|
lstrcpy(*ppStr,_T(""));
|
|
} else {
|
|
lRet = ERROR_OUTOFMEMORY;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
lRet = ERROR_INVALID_PARAMETER;
|
|
}
|
|
|
|
return lRet;
|
|
}
|
|
|
|
|
|
|
|
int CPerfLib::CheckFileSignature(HKEY hKey)
|
|
{
|
|
int hr = Perf_SeemsNew;
|
|
|
|
int nRet = 0;
|
|
BYTE cCurrentMD5[16];
|
|
BYTE* cStoredMD5 = NULL;
|
|
|
|
|
|
// Get the stored file signature
|
|
// =============================
|
|
CheckLibStruct StoredLibStruct;
|
|
int nRet1;
|
|
int nRet2;
|
|
int nRet3;
|
|
DWORD dwSize;
|
|
|
|
nRet1 = GetBinary( hKey, ADAP_PERFLIB_SIGNATURE, (PBYTE*)&cStoredMD5, &dwSize );
|
|
CDeleteMe<BYTE> dmStoredMD5( cStoredMD5 );
|
|
|
|
if (cStoredMD5 && (dwSize == sizeof(StoredLibStruct.Signature)))
|
|
{
|
|
memcpy(&StoredLibStruct.Signature,cStoredMD5,sizeof(StoredLibStruct.Signature));
|
|
|
|
BYTE * pFileTime = NULL;
|
|
nRet2 = GetBinary( hKey, ADAP_PERFLIB_TIME, (PBYTE*)&pFileTime, &dwSize );
|
|
CDeleteMe<BYTE> dmFileTime( pFileTime );
|
|
|
|
if (pFileTime)
|
|
{
|
|
memcpy(&StoredLibStruct.FileTime,pFileTime,sizeof(FILETIME));
|
|
}
|
|
|
|
nRet3 = GetDWORD(hKey, ADAP_PERFLIB_SIZE,&StoredLibStruct.FileSize);
|
|
|
|
if((ERROR_SUCCESS == nRet1) &&
|
|
(ERROR_SUCCESS == nRet2) &&
|
|
(ERROR_SUCCESS == nRet3))
|
|
{
|
|
// Get the current library's signature
|
|
// ===================================
|
|
CheckLibStruct CurrentLibStruct;
|
|
memset(&CurrentLibStruct,0,sizeof(CheckLibStruct));
|
|
|
|
if (SUCCEEDED(GetFileSignature( &CurrentLibStruct )))
|
|
{
|
|
if ( (StoredLibStruct.FileSize == CurrentLibStruct.FileSize) &&
|
|
(0 == memcmp( &StoredLibStruct.Signature, &CurrentLibStruct.Signature, sizeof(CurrentLibStruct.Signature) )) &&
|
|
(0 == memcmp( &StoredLibStruct.FileTime, &CurrentLibStruct.FileTime, sizeof(FILETIME))) )
|
|
{
|
|
hr = Perf_NotChanged;
|
|
}
|
|
else
|
|
{
|
|
hr = Perf_SeemsNew;
|
|
//DBG_PRINTFA((pBuff,"no FileSize or Signature or FIleSuze\n"));
|
|
}
|
|
}
|
|
else
|
|
{
|
|
hr = Perf_SeemsNew;
|
|
//DBG_PRINTFA((pBuff,"no GetFileSignature\n"));
|
|
}
|
|
}
|
|
else
|
|
{
|
|
hr = Perf_SeemsNew;
|
|
//DBG_PRINTFA((pBuff,"no triple regkey\n"));
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
//DBG_PRINTFA((pBuff,"no ADAP_PERFLIB_SIGNATURE\n"));
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
int
|
|
CPerfLib::VerifyLoaded()
|
|
{
|
|
|
|
int hr = Perf_Invalid;
|
|
LONG lRet;
|
|
|
|
{
|
|
DWORD dwFirstCtr = 0,
|
|
dwLastCtr = 0;
|
|
TCHAR * wszObjList = NULL;
|
|
|
|
if ( ( ERROR_SUCCESS == GetStr( GetHKey(), L"Object List", &wszObjList )) ||
|
|
( ( ERROR_SUCCESS == GetDWORD( GetHKey(), L"First Counter", &dwFirstCtr )) &&
|
|
( ERROR_SUCCESS == GetDWORD( GetHKey(), L"Last Counter", &dwLastCtr ))))
|
|
{
|
|
|
|
hr = InitializeEntryPoints(GetHKey());
|
|
|
|
if (wszObjList)
|
|
{
|
|
delete [] wszObjList;
|
|
}
|
|
|
|
} else { // more special cases
|
|
|
|
if ( (0 == _tcsicmp(m_wstrServiceName,_T("TCPIP"))) ||
|
|
(0 == _tcsicmp(m_wstrServiceName,_T("TAPISRV"))) ||
|
|
(0 == _tcsicmp(m_wstrServiceName,_T("PERFOS" ))) ||
|
|
(0 == _tcsicmp(m_wstrServiceName,_T("PERFPROC"))) ||
|
|
(0 == _tcsicmp(m_wstrServiceName,_T("PERFDISK"))) ||
|
|
(0 == _tcsicmp(m_wstrServiceName,_T("PERFNET"))) ||
|
|
(0 == _tcsicmp(m_wstrServiceName,_T("SPOOLER"))) ||
|
|
(0 == _tcsicmp(m_wstrServiceName,_T("MSFTPSvc"))) ||
|
|
(0 == _tcsicmp(m_wstrServiceName,_T("RemoteAccess"))) ||
|
|
(0 == _tcsicmp(m_wstrServiceName,_T("WINS"))) ||
|
|
(0 == _tcsicmp(m_wstrServiceName,_T("MacSrv"))) ||
|
|
(0 == _tcsicmp(m_wstrServiceName,_T("AppleTalk"))) ||
|
|
(0 == _tcsicmp(m_wstrServiceName,_T("NM"))) ||
|
|
(0 == _tcsicmp(m_wstrServiceName,_T("RSVP"))) )
|
|
{
|
|
|
|
hr = InitializeEntryPoints(GetHKey());
|
|
|
|
}
|
|
}
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
int
|
|
CPerfLib::InitializeEntryPoints(HKEY hKey)
|
|
{
|
|
int hr = Perf_SeemsNew;
|
|
|
|
// see if someone disabled this library
|
|
DWORD dwDisable = 0;
|
|
if ( ERROR_SUCCESS == GetDWORD( hKey, _T("Disable Performance Counters"), &dwDisable ) &&
|
|
(dwDisable != 0) )
|
|
{
|
|
hr = Perf_Disabled;
|
|
}
|
|
|
|
if ((ERROR_SUCCESS == GetDWORD( hKey, _T("WbemAdapStatus"), &dwDisable))
|
|
&& (0xFFFFFFFF == dwDisable))
|
|
{
|
|
hr = Perf_Disabled;
|
|
}
|
|
|
|
// the perflib is OK for the world, see if it os OK for US
|
|
|
|
if (SUCCEEDED(hr)){
|
|
|
|
if (!(( ERROR_SUCCESS == GetStr( hKey, _T("Library"), &m_pwcsLibrary ) ) &&
|
|
( ERROR_SUCCESS == GetStr( hKey, _T("Open"), &m_pwcsOpenProc ) )&&
|
|
( ERROR_SUCCESS == GetStr( hKey, _T("Collect"), &m_pwcsCollectProc ) ) &&
|
|
( ERROR_SUCCESS == GetStr( hKey, _T("Close"), &m_pwcsCloseProc ) ) ))
|
|
{
|
|
hr = Perf_Invalid;
|
|
}
|
|
else
|
|
{
|
|
hr = Perf_SetupOK;
|
|
}
|
|
}
|
|
|
|
return hr;
|
|
|
|
}
|
|
|
|
int
|
|
CPerfLib::VerifyLoadable()
|
|
{
|
|
if (!m_bOK)
|
|
return Perf_Invalid;
|
|
|
|
int hr;
|
|
|
|
hr = VerifyLoaded();
|
|
|
|
if ( Perf_SetupOK == hr )
|
|
{
|
|
hr = CheckFileSignature(GetHKey());
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
TCHAR * g_ExcludeList[] = {
|
|
_T("WMIAPRPL")
|
|
};
|
|
|
|
//
|
|
//
|
|
// GetListofSvcs
|
|
//
|
|
////////////////////////////////////////////////////////////
|
|
|
|
HRESULT
|
|
GetListOfSvcs(LIST_ENTRY * pListServices)
|
|
{
|
|
LONG lRet;
|
|
HKEY hKey;
|
|
HRESULT hRes = WBEM_NO_ERROR;
|
|
|
|
lRet = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
|
|
SVC_KEY,
|
|
0,KEY_READ,
|
|
&hKey);
|
|
|
|
if (ERROR_SUCCESS == lRet)
|
|
{
|
|
DWORD dwIndex = 0;
|
|
TCHAR KeyName[MAX_PATH];
|
|
TCHAR * pKeyName = KeyName;
|
|
DWORD dwKeyNameSize = (sizeof(KeyName)/sizeof(TCHAR));
|
|
FILETIME FileTime;
|
|
|
|
while (ERROR_SUCCESS == lRet)
|
|
{
|
|
if (pKeyName != KeyName)
|
|
{
|
|
delete [] pKeyName;
|
|
pKeyName = KeyName;
|
|
}
|
|
dwKeyNameSize = (sizeof(KeyName)/sizeof(TCHAR));
|
|
lRet = RegEnumKeyEx(hKey,
|
|
dwIndex,
|
|
pKeyName,
|
|
&dwKeyNameSize,
|
|
NULL,NULL,NULL,
|
|
&FileTime);
|
|
|
|
if (ERROR_INSUFFICIENT_BUFFER == lRet)
|
|
{
|
|
pKeyName = new TCHAR[dwKeyNameSize];
|
|
|
|
if (pKeyName)
|
|
{
|
|
lRet = RegEnumKeyEx(hKey,
|
|
dwIndex,
|
|
pKeyName,
|
|
&dwKeyNameSize,
|
|
NULL,NULL,NULL,
|
|
&FileTime);
|
|
}
|
|
else
|
|
{
|
|
lRet = ERROR_OUTOFMEMORY;
|
|
}
|
|
}
|
|
|
|
if (ERROR_SUCCESS == lRet)
|
|
{
|
|
dwIndex++;
|
|
DWORD i;
|
|
DWORD NumExcluded = sizeof(g_ExcludeList)/sizeof(TCHAR *);
|
|
|
|
for (i=0; i<NumExcluded; i++)
|
|
{
|
|
if (0 == _tcsicmp(g_ExcludeList[i],pKeyName)){
|
|
break;
|
|
}
|
|
}
|
|
|
|
// if we pass all the Excluded Array then we are OK to add
|
|
if (i == NumExcluded)
|
|
{
|
|
DWORD dwSize = _tcslen(pKeyName);
|
|
LinkString * pLinkString = (LinkString *)new BYTE[sizeof(LinkString) + dwSize*sizeof(TCHAR)];
|
|
|
|
if (pLinkString)
|
|
{
|
|
pLinkString->Size = dwSize;
|
|
_tcscpy(pLinkString->pString,pKeyName);
|
|
InsertTailList(pListServices,&pLinkString->Entry);
|
|
}
|
|
else
|
|
{
|
|
lRet = ERROR_OUTOFMEMORY;
|
|
}
|
|
}
|
|
}
|
|
//
|
|
// the lack of the else case here will prevent the loop
|
|
// from completing if only one key is BAD
|
|
//
|
|
}
|
|
|
|
if (pKeyName != KeyName)
|
|
{
|
|
delete [] pKeyName;
|
|
pKeyName = KeyName;
|
|
}
|
|
|
|
if (ERROR_NO_MORE_ITEMS != lRet)
|
|
{
|
|
hRes = WBEM_E_FAILED;
|
|
}
|
|
|
|
RegCloseKey(hKey);
|
|
}
|
|
else
|
|
{
|
|
hRes = WBEM_E_FAILED;
|
|
}
|
|
|
|
return hRes;
|
|
}
|
|
|
|
//
|
|
//
|
|
// GetSvcWithPerf
|
|
//
|
|
///////////////////////////////////////////////////////////
|
|
|
|
#define FIXED_SIZE (sizeof(_T("System\\CurrentControlSet\\Services\\%s\\Performance")))
|
|
|
|
HRESULT
|
|
GetSvcWithPerf(/*IN OUT*/ LIST_ENTRY * pListHead)
|
|
{
|
|
TCHAR KeyPath[MAX_PATH+1];
|
|
TCHAR * pKeyPath = KeyPath;
|
|
LIST_ENTRY LocalListHead;
|
|
InitializeListHead(&LocalListHead);
|
|
// now change the head to the list
|
|
// assume the list is NOT EMPTY
|
|
LIST_ENTRY * pEntry = pListHead->Flink; // point to the first item
|
|
RemoveEntryList(pListHead); // remove the head
|
|
InitializeListHead(pListHead); // clear the head
|
|
InsertTailList(pEntry,&LocalListHead); // put in the same place the New Local head
|
|
|
|
HRESULT hRes = WBEM_NO_ERROR;
|
|
DWORD i;
|
|
|
|
for (pEntry = LocalListHead.Flink;
|
|
pEntry != &LocalListHead;
|
|
pEntry = pEntry->Flink)
|
|
{
|
|
LinkString * pLinkString = (LinkString *) pEntry;
|
|
|
|
if ((FIXED_SIZE + pLinkString->Size) < MAX_PATH )
|
|
{
|
|
_stprintf(KeyPath,_T("System\\CurrentControlSet\\Services\\%s\\Performance"),pLinkString->pString);
|
|
}
|
|
else
|
|
{
|
|
if (pKeyPath != KeyPath && pKeyPath)
|
|
{
|
|
delete [] pKeyPath;
|
|
}
|
|
pKeyPath = new TCHAR[1 + FIXED_SIZE + pLinkString->Size];
|
|
if (pKeyPath)
|
|
{
|
|
_stprintf(pKeyPath,_T("System\\CurrentControlSet\\Services\\%s\\Performance"),pLinkString->pString);
|
|
}
|
|
else
|
|
{
|
|
hRes = WBEM_E_OUT_OF_MEMORY;
|
|
break;
|
|
}
|
|
}
|
|
LONG lRes;
|
|
HKEY hKey;
|
|
|
|
lRes = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
|
|
pKeyPath,
|
|
NULL,KEY_READ,
|
|
&hKey);
|
|
if (ERROR_SUCCESS == lRes)
|
|
{
|
|
DWORD nSize = _tcslen(pKeyPath);
|
|
LinkString * pLinkString2 = (LinkString *)new BYTE[sizeof(LinkString) + nSize*sizeof(TCHAR)];
|
|
if (pLinkString2)
|
|
{
|
|
pLinkString2->Size = nSize;
|
|
_tcscpy(pLinkString2->pString,pKeyPath);
|
|
InsertTailList(pListHead,&pLinkString2->Entry);
|
|
}
|
|
else
|
|
{
|
|
lRes = ERROR_OUTOFMEMORY;
|
|
}
|
|
RegCloseKey(hKey);
|
|
}
|
|
}
|
|
|
|
for (pEntry = LocalListHead.Flink;
|
|
pEntry != &LocalListHead;
|
|
pEntry = pEntry->Flink)
|
|
{
|
|
BYTE * pByte = (BYTE *)pEntry;
|
|
RemoveEntryList(pEntry);
|
|
pEntry = pEntry->Flink;
|
|
delete [] pByte;
|
|
};
|
|
|
|
if (pKeyPath != KeyPath)
|
|
{
|
|
delete [] pKeyPath;
|
|
}
|
|
|
|
return hRes;
|
|
}
|
|
|
|
|
|
|
|
|
|
//
|
|
//
|
|
// Known Service implementation
|
|
//
|
|
///////////////////////////////////////////////////////////
|
|
|
|
|
|
bool
|
|
WCmp::operator()(WString pFirst,WString pSec) const
|
|
{
|
|
if (!pFirst || !pSec)
|
|
return false;
|
|
|
|
int res = _wcsicmp(pFirst,pSec);
|
|
|
|
return (res<0);
|
|
}
|
|
|
|
|
|
|
|
CSvcs::CSvcs():
|
|
m_cRef(1)
|
|
{
|
|
}
|
|
|
|
CSvcs::~CSvcs()
|
|
{
|
|
}
|
|
|
|
DWORD
|
|
CSvcs::Add(WCHAR * pService)
|
|
{
|
|
if (pService)
|
|
{
|
|
try
|
|
{
|
|
MapSvc::iterator it = m_SetServices.find(pService);
|
|
|
|
if (it == m_SetServices.end()) // not in the std::map
|
|
{
|
|
m_SetServices[pService] = true; // add to the map
|
|
}
|
|
return 0;
|
|
}
|
|
catch (CX_MemoryException)
|
|
{
|
|
return ERROR_OUTOFMEMORY;
|
|
}
|
|
}
|
|
else
|
|
return ERROR_INVALID_PARAMETER;
|
|
}
|
|
|
|
BOOL
|
|
CSvcs::Find(WCHAR * pService)
|
|
{
|
|
if (pService)
|
|
{
|
|
MapSvc::iterator it = m_SetServices.find(pService);
|
|
if (it != m_SetServices.end())
|
|
{
|
|
return TRUE;
|
|
}
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
DWORD
|
|
CSvcs::Load()
|
|
{
|
|
// get the MULTI_SZ key
|
|
LONG lRet;
|
|
HKEY hKey;
|
|
|
|
lRet = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
|
|
WBEM_REG_WINMGMT,
|
|
NULL,
|
|
KEY_READ,
|
|
&hKey);
|
|
|
|
if (ERROR_SUCCESS == lRet)
|
|
{
|
|
DWORD dwSize = 0;
|
|
DWORD dwType = REG_MULTI_SZ;
|
|
|
|
lRet = RegQueryValueEx(hKey,
|
|
KNOWN_SERVICES,
|
|
NULL,
|
|
&dwType,
|
|
NULL,
|
|
&dwSize);
|
|
|
|
if (ERROR_SUCCESS == lRet && (dwSize > 0))
|
|
{
|
|
TCHAR * pStr = new TCHAR[dwSize];
|
|
|
|
if (pStr)
|
|
{
|
|
CDeleteMe<TCHAR> cdm(pStr);
|
|
|
|
lRet = RegQueryValueEx(hKey,
|
|
KNOWN_SERVICES,
|
|
NULL,
|
|
&dwType,
|
|
(BYTE *)pStr,
|
|
&dwSize);
|
|
if ((ERROR_SUCCESS == lRet) &&
|
|
(REG_MULTI_SZ == dwType))
|
|
{
|
|
DWORD dwLen = 0;
|
|
while(dwLen = lstrlen(pStr))
|
|
{
|
|
try
|
|
{
|
|
m_SetServices[pStr] = true;
|
|
}
|
|
catch (CX_MemoryException)
|
|
{
|
|
lRet = ERROR_OUTOFMEMORY;
|
|
break;
|
|
}
|
|
pStr += (dwLen+1);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
lRet = ERROR_OUTOFMEMORY;
|
|
}
|
|
}
|
|
|
|
RegCloseKey(hKey);
|
|
}
|
|
|
|
return lRet;
|
|
}
|
|
|
|
// already in winmgmt.h
|
|
/*
|
|
#define FULL_DREDGE 2
|
|
#define PARTIAL_DREDGE 1
|
|
#define NO_DREDGE 0
|
|
*/
|
|
|
|
//
|
|
//
|
|
// DeltaDredge
|
|
//
|
|
// both params are unused
|
|
// operation
|
|
// reads a registry key containing the known Services
|
|
// enumerates the registry keys, and figure-out which ones
|
|
// are the one with "performance" subkey
|
|
//
|
|
///////////////////////////////////////////////////////////
|
|
|
|
DWORD WINAPI
|
|
DeltaDredge(DWORD dwNumServicesArgs,
|
|
LPWSTR *lpServiceArgVectors)
|
|
{
|
|
|
|
DWORD bDredge = NO_DREDGE;
|
|
|
|
CSvcs KnownSvc;
|
|
|
|
if (ERROR_SUCCESS == KnownSvc.Load())
|
|
{
|
|
LIST_ENTRY ListServices;
|
|
InitializeListHead(&ListServices);
|
|
HRESULT hRes;
|
|
|
|
hRes = GetListOfSvcs(&ListServices);
|
|
|
|
if (SUCCEEDED(hRes))
|
|
{
|
|
hRes = GetSvcWithPerf(&ListServices);
|
|
|
|
if (SUCCEEDED(hRes))
|
|
{
|
|
DWORD Status = 0;
|
|
try
|
|
{
|
|
|
|
CSvcs OKServices; // this constructor throws
|
|
|
|
LIST_ENTRY * pListEntry;
|
|
DWORD i=0;
|
|
for (pListEntry = ListServices.Flink;
|
|
pListEntry != &ListServices;
|
|
pListEntry = pListEntry->Flink)
|
|
{
|
|
LinkString * pLString = (LinkString *)pListEntry;
|
|
CPerfLib PerfLib(pLString->pString);
|
|
|
|
if (!PerfLib.IsOK())
|
|
{
|
|
continue;
|
|
}
|
|
|
|
int PerfStatus = PerfLib.VerifyLoadable();
|
|
|
|
#ifdef DEBUG_ADAP
|
|
DBG_PRINTFA((pBuff,"%d Service %S status %d\n",i,pLString->pString,PerfStatus));
|
|
#endif
|
|
switch (PerfStatus)
|
|
{
|
|
case CPerfLib::Perf_Invalid:
|
|
case CPerfLib::Perf_Disabled:
|
|
//
|
|
// nothing to do with an invalid library
|
|
// or with a disabled library
|
|
//
|
|
|
|
#ifdef DEBUG_ADAP
|
|
DBG_PRINTFA((pBuff,"Invalid or Disabled Service %S\n",PerfLib.GetServiceName()));
|
|
#endif
|
|
DEBUGTRACE((LOG_WMIADAP,"Invalid registration or Disabled Service %S\n",PerfLib.GetServiceName()));
|
|
break;
|
|
case CPerfLib::Perf_NotChanged:
|
|
//
|
|
// this is what we want to hear
|
|
//
|
|
OKServices.Add(PerfLib.GetServiceName());
|
|
break;
|
|
case CPerfLib::Perf_SeemsNew:
|
|
//
|
|
// now we have to do a dredge
|
|
//
|
|
#ifdef DEBUG_ADAP
|
|
DBG_PRINTFA((pBuff,"NewOrChanged Service %S\n",PerfLib.GetServiceName()));
|
|
#endif
|
|
DEBUGTRACE((LOG_WMIADAP,"NewOrChanged Service %S\n",PerfLib.GetServiceName()));
|
|
bDredge = PARTIAL_DREDGE;
|
|
break;
|
|
default:
|
|
//
|
|
// never here
|
|
//
|
|
break;
|
|
}
|
|
i++;
|
|
}
|
|
|
|
if (NO_DREDGE == bDredge)
|
|
{
|
|
//
|
|
// if here, someone might have changed the registry directly
|
|
//
|
|
if (OKServices.GetMap().size() != KnownSvc.GetMap().size())
|
|
{
|
|
#ifdef DEBUG_ADAP
|
|
DBG_PRINTFA((pBuff,"Registry-listed Services and KnownSvcs are not of the same size\n"));
|
|
#endif
|
|
ERRORTRACE((LOG_WMIADAP,"Registry-listed Services and KnownSvcs are not of the same size\n"));
|
|
bDredge = PARTIAL_DREDGE;
|
|
}
|
|
else // same size -> are they the same ?
|
|
{
|
|
MapSvc::iterator it1 = OKServices.GetMap().begin();
|
|
MapSvc::iterator it2 = KnownSvc.GetMap().begin();
|
|
|
|
while (it1 != OKServices.GetMap().end())
|
|
{
|
|
#ifdef DEBUG_ADAP
|
|
DBG_PRINTFA((pBuff," %S =?= %S \n",(const WCHAR *)(*it1).first,(const WCHAR *)(*it2).first));
|
|
#endif
|
|
if (0 != _wcsicmp((*it1).first,(*it2).first))
|
|
{
|
|
bDredge = PARTIAL_DREDGE;
|
|
break;
|
|
}
|
|
++it1;
|
|
++it2;
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
catch (CX_MemoryException & )
|
|
{
|
|
bDredge = PARTIAL_DREDGE;
|
|
}
|
|
}
|
|
}
|
|
|
|
LIST_ENTRY * pListEntry;
|
|
for (pListEntry = ListServices.Flink;
|
|
pListEntry != &ListServices;
|
|
)
|
|
{
|
|
BYTE * pByte = (BYTE *)pListEntry;
|
|
RemoveEntryList(pListEntry);
|
|
pListEntry = pListEntry->Flink;
|
|
delete [] pByte;
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// There is no valid KNOWN_SERVICES key --- FULL Dredge
|
|
//
|
|
bDredge = FULL_DREDGE;
|
|
}
|
|
|
|
return bDredge;
|
|
}
|
|
|
|
DWORD WINAPI
|
|
DeltaDredge2(DWORD dwNumServicesArgs,
|
|
LPWSTR *lpServiceArgVectors)
|
|
{
|
|
|
|
DWORD bDredge = FULL_DREDGE;
|
|
|
|
// check the MULTI_SZ key
|
|
LONG lRet;
|
|
HKEY hKey;
|
|
|
|
lRet = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
|
|
WBEM_REG_WINMGMT,
|
|
NULL,
|
|
KEY_READ,
|
|
&hKey);
|
|
|
|
if (ERROR_SUCCESS == lRet)
|
|
{
|
|
DWORD dwSize = 0;
|
|
DWORD dwType = REG_MULTI_SZ;
|
|
|
|
lRet = RegQueryValueEx(hKey,
|
|
KNOWN_SERVICES,
|
|
NULL,
|
|
&dwType,
|
|
NULL,
|
|
&dwSize);
|
|
|
|
if (ERROR_SUCCESS == lRet && (dwSize > 2)) // empty MULTI_SZ is 2 bytes
|
|
{
|
|
bDredge = NO_DREDGE;
|
|
}
|
|
|
|
RegCloseKey(hKey);
|
|
}
|
|
|
|
return bDredge;
|
|
}
|
|
|