windows-nt/Source/XPSP1/NT/admin/wmi/wbem/common/wdmlib/wmimof.cpp
2020-09-26 16:20:57 +08:00

2259 lines
68 KiB
C++

/////////////////////////////////////////////////////////////////////
//
// BINMOF.CPP
//
// Module:
// Purpose:
//
// Copyright (c) 1997-2001 Microsoft Corporation, All Rights Reserved
//
/////////////////////////////////////////////////////////////////////
#include "wmicom.h"
#include "wmimof.h"
#include <wchar.h>
#include <stdio.h>
#include "wdmshell.h"
#include <cregcls.h>
#include <bmof.h>
#include <mrcicode.h>
#include <mofcomp.h>
#include <crc32.h>
#include <TCHAR.h>
//#define DBG_PRINTFA( a ) { char pBuff[128]; sprintf a ; OutputDebugStringA(pBuff); }
#define WDM_REG_KEY L"Software\\Microsoft\\WBEM\\WDM"
#define WDM_DREDGE_KEY L"Software\\Microsoft\\WBEM\\WDM\\DREDGE"
#define DREDGE_KEY L"DREDGE"
///////////////////////////////////////////////////////////////////////////////////////////
//***************************************************************************
//
// void * BMOFAlloc
//
// DESCRIPTION:
//
// Provides allocation service for BMOF.C. This allows users to choose
// the allocation method that is used.
//
// PARAMETERS:
//
// Size Input. Size of allocation in bytes.
//
// RETURN VALUE:
//
// pointer to new data. NULL if allocation failed.
//
//***************************************************************************
void * BMOFAlloc(size_t Size)
{
return malloc(Size);
}
//***************************************************************************
//
// void BMOFFree
//
// DESCRIPTION:
//
// Provides allocation service for BMOF.C. This frees what ever was
// allocated via BMOFAlloc.
//
// PARAMETERS:
//
// pointer to memory to be freed.
//
//***************************************************************************
void BMOFFree(void * pFree)
{
free(pFree);
}
///////////////////////////////////////////////////////////////////////////////////////////////////
void ConvertStringToCTypeString( WCHAR * Out, WCHAR * In )
{
WCHAR * token = NULL;
if(In)
{
CAutoWChar tmpBuf(_MAX_PATH*2);
if( tmpBuf.Valid() )
{
wcscpy((WCHAR*)tmpBuf,In);
token = wcstok( (WCHAR*)tmpBuf, L"\\" );
if( !token )
{
wcscpy(Out,In);
}
else
{
BOOL fFirst = TRUE;
while( token != NULL )
{
if( fFirst )
{
wcscpy(Out,token);
fFirst = FALSE;
}
else
{
wcscat(Out,L"\\\\");
wcscat(Out,token);
}
token = wcstok( NULL, L"\\" );
}
}
}
}
}
///////////////////////////////////////////////////////////////////////////////////////////
//*****************************************************************************************
// The binary mof class
//*****************************************************************************************
///////////////////////////////////////////////////////////////////////////////////////////
CWMIBinMof::CWMIBinMof()
{
m_pCompiler = NULL;
m_pWMI = NULL;
m_nInit = NOT_INITIALIZED;
m_pMofResourceInfo = NULL;
}
/////////////////////////////////////////////////////////////////////
HRESULT CWMIBinMof::InitializePtrs(CHandleMap * pList, IWbemServices __RPC_FAR * pServices,
IWbemObjectSink __RPC_FAR * pHandler, IWbemContext __RPC_FAR *pCtx)
{
HRESULT hr = WBEM_E_FAILED;
SAFE_DELETE_PTR(m_pWMI);
m_pWMI = new CWMIManagement;
if( m_pWMI )
{
m_pWMI->SetWMIPointers(pList, pServices, pHandler, pCtx);
m_nInit = FULLY_INITIALIZED;
hr = S_OK;
}
return hr;
}
/////////////////////////////////////////////////////////////////////
HRESULT CWMIBinMof::Initialize(CWMIManagement * p,BOOL fUpdateNamespace)
{
HRESULT hr = WBEM_E_FAILED;
if( p )
{
hr = InitializePtrs(p->HandleMap(),p->Services(),p->Handler(),p->Context());
}
else
{
m_nInit = PARTIALLY_INITIALIZED;
hr = S_OK;
}
m_fUpdateNamespace = fUpdateNamespace;
return hr;
}
/////////////////////////////////////////////////////////////////////
HRESULT CWMIBinMof::Initialize(CHandleMap * pList, BOOL fUpdateNamespace,ULONG uDesiredAccess,
IWbemServices __RPC_FAR * pServices, IWbemObjectSink __RPC_FAR * pHandler,
IWbemContext __RPC_FAR *pCtx)
{
HRESULT hr = WBEM_E_FAILED;
hr = InitializePtrs(pList,pServices,pHandler,pCtx);
m_fUpdateNamespace = fUpdateNamespace;
return hr;
}
/////////////////////////////////////////////////////////////////////
CWMIBinMof::~CWMIBinMof()
{
SAFE_RELEASE_PTR(m_pCompiler);
SAFE_DELETE_PTR(m_pWMI);
}
/////////////////////////////////////////////////////////////////////
HRESULT CWMIBinMof::OpenFileAndLookForItIfItDoesNotExist(TCHAR *& pFile, HANDLE & hFile )
{
HRESULT hr = S_OK;
//=========================================================================
// Ok, hopefully CreateFile will find it
//=========================================================================
hFile = CreateFile(pFile, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
if( hFile == INVALID_HANDLE_VALUE )
{
hr = WBEM_E_FAILED;
//=====================================================================
// CreateFile DIDN'T find it, so look in the Windows dir
//=====================================================================
TCHAR pszSysDir[MAX_PATH+4];
UINT uSize = GetSystemDirectory(pszSysDir, MAX_PATH);
if( uSize > 0)
{
TCHAR * pTmp = pFile;
pFile = new TCHAR[MAX_PATH*2 + 4];
if( pFile )
{
_stprintf(pFile,L"%s\\%s",pszSysDir,pTmp);
//=============================================================
// Ok, now try to open again
//=============================================================
hFile = CreateFile(pFile, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
if( hFile != INVALID_HANDLE_VALUE )
{
hr = S_OK;
}
}
SAFE_DELETE_ARRAY(pTmp);
}
}
return hr;
}
/////////////////////////////////////////////////////////////////////
BOOL CWMIBinMof::GetFileDateAndTime(ULONG & lLowDateTime,ULONG & lHighDateTime,WCHAR * wcsFileName)
{
HANDLE hFile = NULL;
FILETIME ftCreationTime, ftLastAccessTime, ftLastWriteTime,ftLocal;
BOOL fRc = FALSE;
TCHAR * pFile = NULL;
if( ExtractFileNameFromKey(pFile,wcsFileName) )
{
if( SUCCEEDED(OpenFileAndLookForItIfItDoesNotExist( pFile, hFile )))
{
if( GetFileTime( hFile, &ftCreationTime, &ftLastAccessTime, &ftLastWriteTime ))
{
//==========================================================
// Pick up the path of the file while we are here....
//==========================================================
TCHAR sFullPath[MAX_PATH * 4];
TCHAR *sFilename = NULL;
if (GetFullPathName(pFile, MAX_PATH * 4, sFullPath, &sFilename) != 0)
{
#ifndef UNICODE
CAnsiUnicode XLate;
WCHAR * pTmp = NULL;
if( SUCCEEDED(XLate.AllocateAndConvertAnsiToUnicode(sFullPath,pTmp)))
{
wcscpy(wcsFileName,pTmp);
SAFE_DELETE_ARRAY( pTmp );
}
#else
wcscpy(wcsFileName,sFullPath);
#endif
}
else
{
DWORD dwTest = GetLastError();
ERRORTRACE((THISPROVIDER,"GetFullPathName FAILED for filename: \n"));
TranslateAndLog(wcsFileName);
ERRORTRACE((THISPROVIDER,": GetlastError returned %ld\n",dwTest));
}
FileTimeToLocalFileTime( &ftLastWriteTime, &ftLocal);
lLowDateTime = (ULONG)ftLocal.dwLowDateTime;
lHighDateTime = (ULONG)ftLocal.dwHighDateTime;
fRc = TRUE;
}
else
{
DWORD dwTest = GetLastError();
ERRORTRACE((THISPROVIDER,"GetFileTime FAILED for filename:\n"));
TranslateAndLog(wcsFileName);
ERRORTRACE((THISPROVIDER,": GetlastError returned %ld\n",dwTest));
}
CloseHandle(hFile);
}
else
{
DWORD dwTest = GetLastError();
ERRORTRACE((THISPROVIDER,"CreateFile FAILED for filename:\n"));
TranslateAndLog(wcsFileName);
ERRORTRACE((THISPROVIDER,": GetlastError returned %ld\n",dwTest));
}
}
else
{
DWORD dwTest = GetLastError();
ERRORTRACE((THISPROVIDER,"Can't extract filename: \n"));
TranslateAndLog(wcsFileName);
ERRORTRACE((THISPROVIDER,": GetlastError returned %ld\n",dwTest));
}
SAFE_DELETE_ARRAY( pFile )
return fRc;
}
/////////////////////////////////////////////////////////////////////
BOOL CWMIBinMof::NeedToProcessThisMof( WCHAR * wcsFileName,ULONG & lLowDateTime, ULONG & lHighDateTime )
{
BOOL fNeedToProcessThisMof = TRUE;
HRESULT hr = WBEM_E_OUT_OF_MEMORY;
IWbemClassObject * pClass=NULL;
CAutoWChar wcsBuf(_MAX_PATH*4);
CAutoWChar wcsTmp(_MAX_PATH*4);
if( wcsTmp.Valid() && wcsBuf.Valid() )
{
//==================================================
// Change all \ to \\
//==================================================
ConvertStringToCTypeString( wcsTmp,wcsFileName );
swprintf(wcsBuf,L"WmiBinaryMofResource.HighDateTime=%lu,LowDateTime=%lu,Name=\"%s\"",lHighDateTime,lLowDateTime,wcsTmp);
//==================================================
// Get a pointer to a IWbemClassObject object
// Have we ever processed this mof before?
// if not, then return TRUE
//==================================================
if( m_fUpdateNamespace )
{
CBSTR cbstr(wcsBuf);
hr = SERVICES->GetObject(cbstr, 0,CONTEXT, &pClass, NULL);
if(WBEM_NO_ERROR == hr)
{
fNeedToProcessThisMof = FALSE;
CVARIANT vSuccess;
hr = pClass->Get(L"MofProcessed", 0, &vSuccess, 0, 0);
if( hr == WBEM_NO_ERROR )
{
//=========================================================================
// make sure it is added to the registry
//=========================================================================
AddThisMofToRegistryIfNeeded(WDM_REG_KEY,wcsFileName,lLowDateTime,lHighDateTime,vSuccess.GetBool());
}
SAFE_RELEASE_PTR( pClass);
}
//==============================================================================
// Delete any old instances that might be hanging around for this driver
//==============================================================================
IEnumWbemClassObject* pEnum = NULL;
CAutoWChar wcsQuery(MEMSIZETOALLOCATE);
if( wcsQuery.Valid() )
{
ULONG uReturned = 0;
swprintf(wcsQuery,L"select * from WMIBinaryMofResource where Name = \"%s\"",wcsTmp);
CBSTR bstrTemp = wcsQuery;
CBSTR strQryLang(L"WQL");
hr = SERVICES->ExecQuery(strQryLang, bstrTemp, WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY,CONTEXT,&pEnum);
if( hr == WBEM_NO_ERROR )
{
IWbemClassObject * pClass = NULL;
while( TRUE )
{
if( WBEM_NO_ERROR == (hr = pEnum->Next(2000, 1, &pClass, &uReturned)))
{
CVARIANT vPath, vDriver;
hr = pClass->Get(L"__RELPATH", 0, &vPath, 0, 0);
if( hr == WBEM_NO_ERROR )
{
if( _wcsicmp(vPath.GetStr(),wcsBuf) != 0 )
{
hr = SERVICES->DeleteInstance(vPath.GetStr(),WBEM_FLAG_OWNER_UPDATE,CONTEXT,NULL);
ERRORTRACE((THISPROVIDER,"We have been requested to delete this mof, :%ld\n",hr));
TranslateAndLog(vPath.GetStr());
if( hr == WBEM_NO_ERROR )
{
//=====================================================
// Duplicate change in registry
//=====================================================
DeleteMofFromRegistry( vPath.GetStr() );
//==========================================================================
// Gets rid of the old classes for the old versions of this driver
//==========================================================================
hr = pClass->Get(L"Driver", 0, &vDriver, 0, 0);
if( hr == WBEM_NO_ERROR )
{
CNamespaceManagement Namespace(this);
Namespace.DeleteOldClasses(vDriver.GetStr(),CVARIANT((long)lLowDateTime),CVARIANT((long)lHighDateTime), TRUE);
}
}
}
}
}
SAFE_RELEASE_PTR( pClass );
if( hr != WBEM_NO_ERROR )
{
break;
}
}
SAFE_RELEASE_PTR(pEnum);
}
}
}
else
{
if( ThisMofExistsInRegistry(WDM_DREDGE_KEY,wcsFileName, lLowDateTime, lHighDateTime, TRUE) )
{
fNeedToProcessThisMof = FALSE;
}
}
}
return fNeedToProcessThisMof;
}
/////////////////////////////////////////////////////////////////////
BOOL CWMIBinMof::UpdateMofTimestampInHMOM(WCHAR * wcsKey,ULONG & lLowDateTime, ULONG & lHighDateTime, BOOL fSuccess )
{
BOOL fRc = FALSE;
IWbemClassObject * pNewInst = NULL;
IWbemClassObject * pIWbemClassObject = NULL;
//==================================================
// Get a pointer to a IWbemClassObject object
//==================================================
HRESULT hr = WBEM_NO_ERROR;
if( m_fUpdateNamespace )
{
CVARIANT cvarName;
cvarName.SetStr(L"WMIBinaryMofResource");
hr = SERVICES->GetObject(cvarName, 0,CONTEXT, &pIWbemClassObject, NULL);
if(WBEM_NO_ERROR == hr)
{
//=============================================================
// Spawn a new instance
//=============================================================
hr = pIWbemClassObject->SpawnInstance(0, &pNewInst);
SAFE_RELEASE_PTR(pIWbemClassObject);
if( WBEM_NO_ERROR == hr )
{
CVARIANT vLow, vHigh, vName, vSuccess;
vSuccess.SetBool(fSuccess);
vName.SetStr(wcsKey);
vLow.SetLONG(lLowDateTime);
vHigh.SetLONG(lHighDateTime);
hr = pNewInst->Put(L"Name", 0, &vName, NULL);
if( S_OK == hr )
{
hr = pNewInst->Put(L"LowDateTime", 0, &vLow, NULL);
if( S_OK == hr )
{
hr = pNewInst->Put(L"HighDateTime", 0, &vHigh, NULL);
if( S_OK == hr )
{
hr = pNewInst->Put(L"MofProcessed", 0, &vSuccess, NULL);
if( S_OK == hr )
{
CVARIANT vActive;
vActive.SetBool(TRUE);
pNewInst->Put(L"Active", 0, &vActive, NULL);
}
hr = SERVICES->PutInstance(pNewInst,WBEM_FLAG_OWNER_UPDATE,CONTEXT,NULL);
SAFE_RELEASE_PTR(pNewInst);
}
}
}
}
}
}
if( hr == WBEM_NO_ERROR )
{
//==========================================
// Make sure this really is in the registry
// too
//==========================================
if( WBEM_NO_ERROR == AddThisMofToRegistryIfNeeded(WDM_REG_KEY,wcsKey,lLowDateTime,lHighDateTime,fSuccess))
{
fRc = TRUE;
}
}
return fRc;
}
///////////////////////////////////////////////////////////////////
BOOL CWMIBinMof::GetNextSectionFromTheEnd(WCHAR * pwcsTempPath, WCHAR * pwcsEnd )
{
BOOL fReturn = FALSE;
WCHAR * pc = wcsrchr(pwcsTempPath,'\\');
if(pc)
{
//==================================================
// Copy what was there and set the end to NULL
//==================================================
pc++;
wcscpy( pwcsEnd, pc );
pc--;
*(pc) = NULL;
fReturn = TRUE;
}
return fReturn;
}
///////////////////////////////////////////////////////////////////
BOOL CWMIBinMof::UseDefaultLocaleId(WCHAR * wcsFile, WORD & wLocalId)
{
BOOL fLoadDefaultLocale = TRUE;
//=============================================================
// Parse paths - get the locale id from paths of this format:
//
// check for path beginning with %windir% and with MUI in second to last position
// if not found, check for fixed directory: %windir%\MUI\Fallback
// if not found - assume it is not MUI related and try it with FindResource
//
//=============================================================
TCHAR szWindowsDir[_MAX_PATH];
if ( GetWindowsDirectory ( szWindowsDir , sizeof ( szWindowsDir ) / sizeof(TCHAR)) )
{
//==========================================================
// if these are windows directories
//==========================================================
if( 0 == _wcsnicmp( szWindowsDir, wcsFile, wcslen(szWindowsDir)))
{
CAutoWChar wcsTempPath(_MAX_PATH);
CAutoWChar wcsBuffer(_MAX_PATH);
if( wcsTempPath.Valid() && wcsBuffer.Valid() )
{
//======================================================
// Find last \ in the string, and trim off filename
//======================================================
wcscpy(wcsTempPath,wcsFile);
if( GetNextSectionFromTheEnd( wcsTempPath, wcsBuffer ))
{
//==================================================
// Now, get the potential locale id
//==================================================
if( GetNextSectionFromTheEnd( wcsTempPath, wcsBuffer ))
{
wLocalId = (WORD) _wtoi(wcsBuffer);
//==============================================
// Now, get the next bit to see if it says MUI
// or Fallback
//==============================================
if( GetNextSectionFromTheEnd( wcsTempPath, wcsBuffer ))
{
if( 0 == _wcsicmp( L"MUI", wcsBuffer ))
{
fLoadDefaultLocale = FALSE;
}
else if( 0 == _wcsicmp( L"Fallback", wcsBuffer ) )
{
//==============================================
// If it says Fallback, then check to make
// sure the next bit says MUI
//==============================================
if( GetNextSectionFromTheEnd( wcsTempPath, wcsBuffer ))
{
if( 0 == _wcsicmp( L"MUI", wcsBuffer ) )
{
fLoadDefaultLocale = FALSE;
}
}
}
}
}
}
}
}
}
return fLoadDefaultLocale;
}
///////////////////////////////////////////////////////////////////
BOOL CWMIBinMof::GetPointerToBinaryResource(BYTE *& pRes,
DWORD & dwSize,
HGLOBAL & hResource,
HINSTANCE & hInst,
WCHAR * wcsResource,
WCHAR * wcsFile)
{
TCHAR * pResource = NULL;
BOOL fRc = FALSE;
CAnsiUnicode xLate;
DWORD dwError = 0;
TCHAR * pFile = NULL;
if( ExtractFileNameFromKey(pFile,wcsFile) ){
#ifndef UNICODE
xLate.UnicodeToAnsi(wcsResource,pResource);
#else
pResource = wcsResource;
#endif
if( pResource )
{
hInst = LoadLibraryEx(pFile,NULL,LOAD_LIBRARY_AS_DATAFILE);
if( hInst != NULL )
{
HRSRC hSrc = NULL;
WORD wLocaleId = 0;
if( UseDefaultLocaleId(wcsResource, wLocaleId ))
{
hSrc = FindResource(hInst,pResource, _T("MOFDATA"));
}
else
{
hSrc = FindResourceEx(hInst,pResource, _T("MOFDATA"),wLocaleId);
}
if( hSrc == NULL )
{
FreeLibrary(hInst);
dwError = GetLastError();
}
if( NULL != hSrc)
{
hResource = LoadResource( hInst,hSrc);
if( hResource )
{
pRes = (BYTE *)LockResource(hResource);
dwSize = SizeofResource(hInst,hSrc);
fRc = TRUE;
}
}
}
}
#ifndef UNICODE
SAFE_DELETE_ARRAY(pResource );
#endif
SAFE_DELETE_ARRAY(pFile );
}
return fRc;
}
/////////////////////////////////////////////////////////////////////
BYTE * CWMIBinMof::DecompressBinaryMof(BYTE * pRes)
{
DWORD dwCompType, dwCompressedSize, dwExpandedSize, dwSig, dwResSize;
BYTE * pExpanded = NULL;
//=========================================================
// get the signature, compression type, and the sizes
//=========================================================
memcpy(&dwSig,pRes,sizeof(DWORD));
pRes += sizeof( DWORD );
memcpy(&dwCompType,pRes,sizeof(DWORD));
pRes += sizeof( DWORD );
memcpy(&dwCompressedSize,pRes,sizeof(DWORD));
pRes += sizeof( DWORD );
memcpy(&dwExpandedSize,pRes,sizeof(DWORD));
pRes += sizeof( DWORD );
//=========================================================
// make sure the signature is valid and that the compression type is one
// we understand!
//=========================================================
if(dwSig != BMOF_SIG ||dwCompType != 1){
return NULL;
}
//=========================================================
// Allocate storage for the compressed data and
// expanded data
//=========================================================
try
{
pExpanded = (BYTE*)malloc(dwExpandedSize);
if( pExpanded == NULL)
{
goto ExitDecompression;
}
}
catch(...)
{
throw;
}
//=========================================================
// Decompress the data
//=========================================================
CBaseMrciCompression * pMrci = new CBaseMrciCompression;
if( pMrci )
{
dwResSize = pMrci->Mrci1Decompress(pRes, dwCompressedSize, pExpanded, dwExpandedSize);
if(dwResSize != dwExpandedSize)
{
SAFE_DELETE_PTR(pMrci);
goto ExitDecompression;
}
SAFE_DELETE_PTR(pMrci);
}
//=========================================================
// Now, get out of here
//=========================================================
return pExpanded;
ExitDecompression:
if( pExpanded )
free(pExpanded);
return NULL;
}
/////////////////////////////////////////////////////////////////////
BOOL CWMIBinMof::ExtractFileNameFromKey(TCHAR *& pKey,WCHAR * wcsKey)
{
WCHAR *wcsToken = NULL;
CAutoWChar wcsTmp(MAX_PATH * 4);
BOOL fRc = FALSE;
if( wcsTmp.Valid() )
{
if(wcsKey)
{
//======================================================
// Get a ptr to the first [ , if there isn't one, then
// just copy the whole thing.
//======================================================
wcscpy(wcsTmp,wcsKey);
wcsToken = wcstok(wcsTmp, L"[" );
if( wcsToken != NULL )
{
wcscpy(wcsTmp,wcsToken);
}
#ifndef UNICODE
CAnsiUnicode XLate;
if( SUCCEEDED(XLate.UnicodeToAnsi(wcsTmp,pKey)))
{
fRc = TRUE;
}
#else
pKey = new TCHAR[_tcslen(wcsTmp) + 1];
if(pKey)
{
_tcscpy(pKey,wcsTmp);
fRc = TRUE;
}
#endif
}
}
return fRc;
}
/////////////////////////////////////////////////////////////////////
void CWMIBinMof::CreateKey(WCHAR * wcsFileName, WCHAR * wcsResource,WCHAR * wcsKey)
{
swprintf(wcsKey,L"%s[%s]",wcsFileName, wcsResource );
}
/////////////////////////////////////////////////////////////////////
HRESULT CWMIBinMof::SendToMofComp(DWORD dwSize,BYTE * pRes,WCHAR * wcsKey)
{
HRESULT hr = WBEM_NO_ERROR;
if(m_pCompiler == NULL)
{
hr = CoCreateInstance(CLSID_WinmgmtMofCompiler, 0, CLSCTX_INPROC_SERVER,IID_IWinmgmtMofCompiler, (LPVOID *) &m_pCompiler);
}
if(hr == WBEM_NO_ERROR)
{
WBEM_COMPILE_STATUS_INFO Info;
memset(&Info,0,sizeof(WBEM_COMPILE_STATUS_INFO));
hr = m_pCompiler->WinmgmtCompileBuffer(dwSize, pRes, 0, 65536, 0,SERVICES,CONTEXT , &Info);
if( hr != WBEM_NO_ERROR )
{
ERRORTRACE((THISPROVIDER,"***************\n"));
ERRORTRACE((THISPROVIDER,"Mofcomp of binary mof failed for:\n"));
TranslateAndLog(wcsKey);
ERRORTRACE((THISPROVIDER,"WinmgmtCompileBuffer return value: %ld\n",hr));
ERRORTRACE((THISPROVIDER,"Size of Mof: %ld\n",dwSize));
ERRORTRACE((THISPROVIDER,"***************\n"));
}
else
{
ERRORTRACE((THISPROVIDER,"***************\n"));
ERRORTRACE((THISPROVIDER,"Binary mof succeeded for:\n"));
TranslateAndLog(wcsKey);
ERRORTRACE((THISPROVIDER,"***************\n"));
}
}
return hr;
}
/////////////////////////////////////////////////////////////////////
BOOL CWMIBinMof::ExtractBinaryMofFromFile(WCHAR * wcsFile, WCHAR * wcsResource,WCHAR * wcsKey, BOOL & fMofHasChanged)
{
HRESULT hr;
BOOL fSuccess = TRUE;
CAutoWChar wcsTmp(MAX_PATH*4);
if( wcsTmp.Valid() )
{
ULONG lLowDateTime=0,lHighDateTime=0;
//=====================================
// As long as we have a list, process
// one at a time
//=====================================
lLowDateTime = 0l;
lHighDateTime = 0L;
fMofHasChanged = FALSE;
//==============================================
// Compare the file date/timestamp the date/timestamp is different, change
// it.
//==============================================
wcscpy(wcsTmp,wcsFile);
if( GetFileDateAndTime(lLowDateTime,lHighDateTime,wcsTmp) )
{
CreateKey(wcsTmp,wcsResource,wcsKey);
// DBG_PRINTFA((pBuff,"Event:%S\n",wcsKey));
if( NeedToProcessThisMof(wcsKey,lLowDateTime,lHighDateTime) )
{
fMofHasChanged = TRUE;
if( m_fUpdateNamespace )
{
DWORD dwSize = 0;
BYTE * pRes = NULL;
HGLOBAL hResource = NULL;
HINSTANCE hInst = NULL;
if( GetPointerToBinaryResource(pRes,dwSize,hResource,hInst,wcsResource,wcsKey) )
{
hr = SendToMofComp(dwSize,pRes,wcsKey);
if(hr == WBEM_S_NO_ERROR )
{
if( UpdateMofTimestampInHMOM(wcsKey,lLowDateTime,lHighDateTime, TRUE) )
{
CNamespaceManagement Namespace(this);
Namespace.CreateClassAssociationsToDriver(wcsKey,pRes,lLowDateTime,lHighDateTime);
Namespace.DeleteOldClasses(wcsKey,CVARIANT((long)lLowDateTime),CVARIANT((long)lHighDateTime), TRUE);
fSuccess = TRUE;
}
else
{
UpdateMofTimestampInHMOM(wcsKey,lLowDateTime,lHighDateTime,FALSE);
}
}
else
{
UpdateMofTimestampInHMOM(wcsKey,lLowDateTime,lHighDateTime,FALSE);
}
UnlockResource(hResource);
FreeResource(hResource);
FreeLibrary(hInst);
}
else
{
ERRORTRACE((THISPROVIDER,"***************\n"));
ERRORTRACE((THISPROVIDER,"Could not get pointer to binary resource for file:\n"));
TranslateAndLog(wcsKey);
ERRORTRACE((THISPROVIDER,"***************\n"));
UpdateMofTimestampInHMOM(wcsKey,lLowDateTime,lHighDateTime,FALSE);
}
}
}
else
{
fSuccess = TRUE;
}
}
else
{
DWORD dwTest = GetLastError();
ERRORTRACE((THISPROVIDER,"Something FAILED for filename: %s\n",wcsFile));
ERRORTRACE((THISPROVIDER,": GetlastError returned %ld\n",dwTest));
ERRORTRACE((THISPROVIDER,"***************\n"));
ERRORTRACE((THISPROVIDER,"Invalid File:\n"));
TranslateAndLog(wcsFile);
ERRORTRACE((THISPROVIDER,"***************\n"));
UpdateMofTimestampInHMOM(wcsFile,lLowDateTime,lHighDateTime,FALSE);
wcscpy(wcsKey, wcsFile);
}
}
return fSuccess;
}
//////////////////////////////////////////////////////////////////////////
#define WDMPROV_REG_KEY L"Software\\Microsoft\\WBEM\\WDMProvider"
BOOL CWMIBinMof::UserConfiguredRegistryToProcessStrandedClassesDuringEveryInit(void)
{
DWORD dwProcess = 0;
CRegistry RegInfo ;
DWORD dwRet = RegInfo.Open (HKEY_LOCAL_MACHINE, WDMPROV_REG_KEY, KEY_READ) ;
if ( dwRet == ERROR_SUCCESS )
{
RegInfo.GetCurrentKeyValue ( L"ProcessStrandedClasses",dwProcess );
}
RegInfo.Close();
return (BOOL) dwProcess;
}
/////////// //////////////////////////////////////////////////////////
void CWMIBinMof::ProcessListOfWMIBinaryMofsFromWMI()
{
HRESULT hr = WBEM_E_FAILED;
if( m_nInit == FULLY_INITIALIZED )
{
CAutoWChar wcsFileName(MAX_PATH*3);
CAutoWChar wcsResource(MAX_PATH*3);
if( wcsFileName.Valid() && wcsResource.Valid() )
{
KeyList ArrDriversInRegistry;
//============================================================
// Get list of what is currently in the registry
//============================================================
GetListOfDriversCurrentlyInRegistry(WDM_REG_KEY,ArrDriversInRegistry);
//======================================================================
// Initialize things
//======================================================================
BOOL fMofChanged = FALSE;
m_fUpdateNamespace = TRUE;
//======================================================================
// Allocate working classes
//======================================================================
CWMIStandardShell * pWMI = new CWMIStandardShell;
if( pWMI )
{
hr = pWMI->Initialize(NULL,FALSE,m_pWMI->HandleMap(),m_fUpdateNamespace, WMIGUID_QUERY, m_pWMI->Services(),m_pWMI->Handler(),m_pWMI->Context());
if( S_OK == hr )
{
CNamespaceManagement * pNamespace = new CNamespaceManagement(this);
if( pNamespace )
{
//=========================================
// Query the binary guid
//=========================================
pNamespace->InitQuery(L"select * from WMIBinaryMofResource where Name != ");
hr = pWMI->QueryAndProcessAllBinaryGuidInstances(*pNamespace, fMofChanged, &ArrDriversInRegistry);
//=========================================
// Get a list of binary mofs from WMI
//=========================================
GetListOfBinaryMofs();
ULONG nTmp=0;
CAutoWChar wcsTmpKey(MAX_PATH*3);
BOOL fProcessStrandedClasses = FALSE;
if( wcsTmpKey.Valid() )
{
if( m_uResourceCount > 0 )
{
//===============================================================
// Go through and get all the resources to process one by one
//===============================================================
while( GetBinaryMofFileNameAndResourceName(wcsFileName,wcsResource)){
//============================================================
// Process the binary mof
//============================================================
if( ExtractBinaryMofFromFile(wcsFileName,wcsResource,wcsTmpKey,fMofChanged))
{
pNamespace->UpdateQuery(L" and Name != ",wcsTmpKey);
}
if( fMofChanged )
{
fProcessStrandedClasses = TRUE;
}
ArrDriversInRegistry.Remove(wcsTmpKey);
}
}
}
pNamespace->DeleteOldDrivers(FALSE);
//===========================================================================
// If we are not supposed to process stranded classes, check the reg key
// to see if it wants us to anyway
//===========================================================================
if( !fProcessStrandedClasses )
{
fProcessStrandedClasses = UserConfiguredRegistryToProcessStrandedClassesDuringEveryInit();
}
if( fProcessStrandedClasses )
{
pNamespace->DeleteStrandedClasses();
}
DeleteOldDriversInRegistry(ArrDriversInRegistry);
SAFE_DELETE_PTR(pNamespace);
}
}
SAFE_DELETE_PTR(pWMI);
}
if( m_pMofResourceInfo )
{
WmiFreeBuffer( m_pMofResourceInfo );
}
}
}
ERRORTRACE((THISPROVIDER,"End of processing Binary MOFS***************\n"));
}
/////////////////////////////////////////////////////////////////////
//=============================================================
// THE BINARY MOF GROUP
//=============================================================
BOOL CWMIBinMof::GetListOfBinaryMofs()
{
BOOL fRc = TRUE;
ULONG uRc;
m_uCurrentResource = 0;
m_pMofResourceInfo = NULL;
m_uResourceCount = 0;
try
{
uRc = WmiMofEnumerateResourcesW( 0, &m_uResourceCount, &m_pMofResourceInfo );
if( uRc != ERROR_SUCCESS )
{
fRc = FALSE;
}
}
catch(...)
{
fRc = FALSE;
// don't throw
}
return fRc;
}
//=============================================================
BOOL CWMIBinMof::GetBinaryMofFileNameAndResourceName(WCHAR * pwcsFileName,WCHAR * pwcsResource)
{
BOOL fRc = FALSE;
//===================================================================
// There are a lot of tests in here, due to strange results from
// WDM Service under stress.
//===================================================================
if( m_uCurrentResource < m_uResourceCount ){
if( m_pMofResourceInfo ){
DWORD dwFileLen = wcslen(m_pMofResourceInfo[m_uCurrentResource].ImagePath);
DWORD dwResourceLen = wcslen(m_pMofResourceInfo[m_uCurrentResource].ResourceName);
if( dwFileLen <( MAX_PATH * 2) && dwResourceLen < (MAX_PATH * 2 )){
if( IsBadReadPtr( m_pMofResourceInfo[m_uCurrentResource].ImagePath,dwFileLen) == 0 ){
wcscpy( pwcsFileName, m_pMofResourceInfo[m_uCurrentResource].ImagePath );
if( IsBadReadPtr( m_pMofResourceInfo[m_uCurrentResource].ResourceName,dwResourceLen) == 0 ){
wcscpy( pwcsResource, m_pMofResourceInfo[m_uCurrentResource].ResourceName );
m_uCurrentResource++;
fRc = TRUE;
}
}
}
}
}
return fRc;
}
////////////////////////////////////////////////////////////////////
HRESULT CWMIBinMof::ExtractBinaryMofFromDataBlock(BYTE * pByte,ULONG uInstanceSize, WCHAR * wcsKey, BOOL & fMofHasChanged)
{
HRESULT hr = WBEM_E_FAILED;
//===================================================
// Get the CRC of the data buffer
//===================================================
DWORD dwCRC = STARTING_CRC32_VALUE;
if( IsBadReadPtr( pByte,uInstanceSize) != 0 ){
return WBEM_E_INVALID_OBJECT;
}
dwCRC = UpdateCRC32(pByte,uInstanceSize, dwCRC);
FINALIZE_CRC32(dwCRC);
//=========================================================
// get the size of the buffer to send
//=========================================================
DWORD dwCompressedSize;
BYTE * pTmp = pByte;
pTmp += sizeof( DWORD ) * 2;
memcpy(&dwCompressedSize,pTmp,sizeof(DWORD));
dwCompressedSize += 16;
fMofHasChanged = FALSE;
//===================================================
// See if we should process this class or not
//===================================================
ULONG lLow = dwCRC;
ULONG lHigh = 0;
// DBG_PRINTFA((pBuff,"Event:%S\n",wcsKey));
if( NeedToProcessThisMof(wcsKey,lLow,lHigh))
{
if( !m_fUpdateNamespace )
{
fMofHasChanged = TRUE;
hr = WBEM_NO_ERROR;
}
else
{
hr = SendToMofComp(dwCompressedSize,pByte,wcsKey);
if( hr == WBEM_NO_ERROR )
{
if( UpdateMofTimestampInHMOM(wcsKey,lLow,lHigh, TRUE))
{
CNamespaceManagement Namespace(this);
Namespace.CreateClassAssociationsToDriver(wcsKey,pByte,lLow,lHigh);
Namespace.DeleteOldClasses(wcsKey,CVARIANT((long)lLow),CVARIANT((long)lHigh),TRUE);
}
else
{
UpdateMofTimestampInHMOM(wcsKey,lLow,lHigh,FALSE);
}
}
else
{
UpdateMofTimestampInHMOM(wcsKey,lLow,lHigh,FALSE);
}
}
}
else
{
hr = WBEM_NO_ERROR;
}
return hr;
}
////////////////////////////////////////////////////////////////////
HRESULT CWMIBinMof::DeleteMofsFromEvent(CVARIANT & vImagePath,CVARIANT & vResourceName, BOOL & fMofHasChanged)
{
HRESULT hr = WBEM_E_OUT_OF_MEMORY;
CAutoWChar wcsTmp(MAX_PATH*2);
if( wcsTmp.Valid() )
{
hr = WBEM_E_INVALID_OBJECT;
//=========================================
// Initialize stuff
//=========================================
fMofHasChanged = FALSE;
//=================================================================
// if we have an image path and resource path we are working with
// file, otherwise it is a binary guidd
//=================================================================
if((vResourceName.GetType() != VT_NULL ) && ( vImagePath.GetType() != VT_NULL )){
CreateKey( vImagePath.GetStr(), vResourceName.GetStr(),wcsTmp );
}
else if( vResourceName.GetType() != VT_NULL ){
SetBinaryMofClassName(vResourceName.GetStr(),wcsTmp);
}
if( m_fUpdateNamespace )
{
CNamespaceManagement Namespace(this);
Namespace.InitQuery(L"select * from WMIBinaryMofResource where Name = ");
Namespace.UpdateQuery(L"",wcsTmp);
if( Namespace.DeleteOldDrivers(FALSE) )
{
hr = WBEM_NO_ERROR;
fMofHasChanged = TRUE;
}
}
else
{
if( ThisMofExistsInRegistry(WDM_REG_KEY,wcsTmp, 0, 0, FALSE))
{
fMofHasChanged = TRUE;
}
hr = WBEM_NO_ERROR;
}
}
return hr;
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//**********************************************************************************************************************
// Functions for the Dredger
//**********************************************************************************************************************
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// format of string containing mof info is:
// "WmiBinaryMofResource.HighDateTime=9999,LowDateTime=9999,Name="Whatever"
//
// HKLM\Software\Microsoft\WBEM\WDM\WDMBinaryMofResource
//
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
HRESULT CWMIBinMof::AddThisMofToRegistryIfNeeded(WCHAR * wcsKey, WCHAR * wcsFileName, ULONG & lLowDateTime, ULONG & lHighDateTime, BOOL fSuccess)
{
HRESULT hr = WBEM_E_FAILED;
CRegistry RegInfo ;
DWORD dwRet = RegInfo.CreateOpen (HKEY_LOCAL_MACHINE, wcsKey) ;
if ( dwRet == ERROR_SUCCESS )
{
CAutoWChar wcsBuf(MAX_PATH);
if( wcsBuf.Valid() )
{
if( fSuccess )
{
swprintf(wcsBuf,L"LowDateTime:%ld,HighDateTime:%ld***Binary mof compiled successfully", lLowDateTime, lHighDateTime);
}
else
{
swprintf(wcsBuf,L"LowDateTime:%ld,HighDateTime:%ld***Binary mof failed, see WMIPROV.LOG", lLowDateTime, lHighDateTime);
}
CHString sTmp = wcsBuf;
if ( RegInfo.SetCurrentKeyValue ( wcsFileName,sTmp ) == ERROR_SUCCESS )
{
hr = WBEM_S_NO_ERROR ;
}
}
else
{
hr = WBEM_E_OUT_OF_MEMORY;
}
}
RegInfo.Close();
return hr;
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
BOOL CWMIBinMof::ThisMofExistsInRegistry(WCHAR * wcsKey,WCHAR * wcsFileName, ULONG lLowDateTime, ULONG lHighDateTime, BOOL fCompareDates)
{
BOOL fExists = FALSE;
CRegistry RegInfo ;
DWORD dwRet = RegInfo.Open (HKEY_LOCAL_MACHINE, wcsKey, KEY_READ) ;
if ( dwRet == ERROR_SUCCESS )
{
CHString chsValue;
if ( RegInfo.GetCurrentKeyValue ( wcsFileName,chsValue ) == ERROR_SUCCESS )
{
if( fCompareDates )
{
CAutoWChar wcsIncomingValue(MAX_PATH);
CAutoWChar wcsTmp(MAX_PATH);
if( wcsIncomingValue.Valid() && wcsTmp.Valid() )
{
swprintf(wcsIncomingValue,L"LowDateTime:%ld,HighDateTime:%ld", lLowDateTime, lHighDateTime );
WCHAR *wcsToken = NULL;
//======================================================
// Get a ptr to the first *** , if there isn't one, then
// we have a messed up key
//======================================================
wcscpy(wcsTmp,(const WCHAR*)chsValue);
wcsToken = wcstok(wcsTmp, L"*" );
if( wcsToken != NULL )
{
if( _wcsicmp(wcsToken, wcsIncomingValue) == 0 )
{
fExists = TRUE;
}
}
}
}
else
{
fExists = TRUE;
}
}
}
RegInfo.Close();
return fExists;
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
HRESULT CWMIBinMof::DeleteMofFromRegistry(WCHAR * wcsFileName)
{
HRESULT hr = WBEM_E_FAILED;
HKEY hKey;
hr = RegOpenKey(HKEY_LOCAL_MACHINE, WDM_REG_KEY, &hKey);
if(NO_ERROR == hr)
{
hr = RegDeleteValue(hKey,wcsFileName);
CloseHandle(hKey);
}
return hr;
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
BOOL CWMIBinMof::DeleteOldDriversInRegistry(KeyList & ArrDriversInRegistry)
{
int nSize = ArrDriversInRegistry.GetSize();
for( int i=0; i < nSize; i++ )
{
DeleteMofFromRegistry(ArrDriversInRegistry.GetAt(i));
}
return TRUE;
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
BOOL CWMIBinMof::CopyWDMKeyToDredgeKey()
{
BOOL fSuccess = FALSE;
//=======================================================================
// Open up the WDM Dredge Key and enumerate the keys, copy them into
// the DredgeReg key
//=======================================================================
CRegistry WDMReg;
CRegistry WDMDregReg;
if (ERROR_SUCCESS == WDMReg.Open(HKEY_LOCAL_MACHINE, WDM_REG_KEY, KEY_READ))
{
//===============================================================
// Clean up old stuff
// Note: You need to open up the parent key, so you can delete
// the child DREDGE key
//===============================================================
if( ERROR_SUCCESS == WDMDregReg.Open(HKEY_LOCAL_MACHINE, WDM_REG_KEY, KEY_READ))
{
CHString pchs(DREDGE_KEY);
WDMDregReg.DeleteKey(&pchs);
WDMDregReg.Close();
}
if( ERROR_SUCCESS == WDMDregReg.CreateOpen(HKEY_LOCAL_MACHINE, WDM_DREDGE_KEY))
{
//===============================================================
// Go through the loop, and copy the keys
//===============================================================
BYTE *pValueData = NULL ;
WCHAR *pValueName = NULL ;
fSuccess = TRUE;
for(DWORD i = 0 ; i < WDMReg.GetValueCount(); i++)
{
DWORD dwRc = WDMReg.EnumerateAndGetValues(i, pValueName, pValueData) ;
if( dwRc == ERROR_SUCCESS )
{
CHString chsKey(pValueName);
CHString chsValue((LPCWSTR)pValueData);
if ( !WDMDregReg.SetCurrentKeyValue ( chsKey, chsValue ) == ERROR_SUCCESS )
{
fSuccess = FALSE;
}
delete []pValueData;
delete []pValueName;
}
else
{
fSuccess = FALSE;
}
if( !fSuccess )
{
break;
}
}
WDMDregReg.Close();
}
WDMReg.Close();
}
return fSuccess;
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
BOOL CWMIBinMof::GetListOfDriversCurrentlyInRegistry(WCHAR * wcsKey, KeyList & ArrDriversInRegistry)
{
BOOL fSuccess = TRUE;
CRegistry RegInfo ;
//==========================================================
// Open the key for enumeration and go through the sub keys.
//==========================================================
HKEY hKey = NULL;
HRESULT hr = RegOpenKeyEx(HKEY_LOCAL_MACHINE, wcsKey, 0, KEY_READ | KEY_QUERY_VALUE,&hKey);
if( ERROR_SUCCESS == hr )
{
WCHAR wcsKeyName[MAX_PATH+2];
DWORD dwLen = 0;
int i = 0;
while( ERROR_SUCCESS == hr )
{
dwLen = MAX_PATH+2;
hr = RegEnumValue(hKey,i,wcsKeyName, &dwLen,0,NULL,NULL,NULL);
// If we are successful reading the name
//=======================================
if(ERROR_SUCCESS == hr )
{
ArrDriversInRegistry.Add(wcsKeyName);
i++;
}
else
{
break;
}
}
RegCloseKey(hKey);
}
else
{
fSuccess = FALSE;
}
return fSuccess;
}
/////////////////////////////////////////////////////////////////////
HRESULT CWMIBinMof::ProcessBinaryMofEvent(PWNODE_HEADER WnodeHeader )
{
HRESULT hr = WBEM_E_FAILED;
m_fUpdateNamespace = TRUE;
if( m_nInit == FULLY_INITIALIZED )
{
CWMIStandardShell * pWMI = new CWMIStandardShell;
if( pWMI )
{
//=======================================================
// See if a binary mof event is being added or deleted
//=======================================================
if( IsBinaryMofResourceEvent(WMI_RESOURCE_MOF_ADDED_GUID,WnodeHeader->Guid))
{
hr = pWMI->Initialize(RUNTIME_BINARY_MOFS_ADDED,TRUE,m_pWMI->HandleMap(),m_fUpdateNamespace, WMIGUID_QUERY, m_pWMI->Services(),m_pWMI->Handler(), m_pWMI->Context());
if( S_OK == hr )
{
hr = pWMI->ProcessEvent(MOF_ADDED,WnodeHeader);
}
}
else if( IsBinaryMofResourceEvent(WMI_RESOURCE_MOF_REMOVED_GUID,WnodeHeader->Guid))
{
hr = pWMI->Initialize(RUNTIME_BINARY_MOFS_DELETED,TRUE,m_pWMI->HandleMap(),m_fUpdateNamespace, WMIGUID_QUERY, m_pWMI->Services(),m_pWMI->Handler(), m_pWMI->Context());
if( S_OK == hr )
{
hr = pWMI->ProcessEvent(MOF_DELETED,WnodeHeader);
}
}
SAFE_DELETE_PTR(pWMI);
}
}
return hr;
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//**********************************************************************************************************************
// STUFF FOR DREDGE
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//**********************************************************************************************************************
/////////////////////////////////////////////////////////////////////
// DREDGE APIS - access ONLY the DREDGE KEY
/////////////////////////////////////////////////////////////////////
BOOL CWMIBinMof::BinaryMofEventChanged(PWNODE_HEADER WnodeHeader )
{
BOOL fMofHasChanged = TRUE;
if( m_nInit != NOT_INITIALIZED )
{
HRESULT hr = WBEM_E_NOT_FOUND;
m_fUpdateNamespace = FALSE;
CWMIStandardShell * pWMI = new CWMIStandardShell;
if( pWMI )
{
//=======================================================
// See if a binary mof event is being added or deleted
//=======================================================
if( IsBinaryMofResourceEvent(WMI_RESOURCE_MOF_ADDED_GUID,WnodeHeader->Guid))
{
hr = pWMI->Initialize(RUNTIME_BINARY_MOFS_ADDED,
TRUE,
NULL,
m_fUpdateNamespace,
WMIGUID_QUERY,
NULL,
NULL,
NULL);
if( S_OK == hr )
{
hr = pWMI->ProcessEvent(MOF_ADDED,WnodeHeader);
}
}
else if( IsBinaryMofResourceEvent(WMI_RESOURCE_MOF_REMOVED_GUID,WnodeHeader->Guid))
{
// DO NOTHING
hr = pWMI->Initialize(RUNTIME_BINARY_MOFS_DELETED,TRUE,
NULL,
m_fUpdateNamespace,
WMIGUID_QUERY,
NULL,
NULL,
NULL);
if( S_OK == hr )
{
// hr = pWMI->ProcessEvent(MOF_DELETED,WnodeHeader);
}
}
ERRORTRACE((THISPROVIDER,"***************\n"));
if( pWMI->HasMofChanged() )
{
ERRORTRACE((THISPROVIDER,"BinaryMofEventChanged returned TRUE:\n"));
}
else
{
ERRORTRACE((THISPROVIDER,"BinaryMofEventChanged returned FALSE:\n"));
}
fMofHasChanged = pWMI->HasMofChanged();
SAFE_DELETE_PTR(pWMI);
}
}
return fMofHasChanged;
}
/////////////////////////////////////////////////////////////////////
// DREDGE APIS - access ONLY the DREDGE KEY
/////////////////////////////////////////////////////////////////////
BOOL CWMIBinMof::BinaryMofsHaveChanged()
{
BOOL fBinaryMofHasChanged = FALSE;
if( m_nInit != NOT_INITIALIZED )
{
KeyList ArrDriversInRegistry;
HRESULT hr = WBEM_E_FAILED;
m_fUpdateNamespace = FALSE;
//============================================================
// Get list of what is currently in the registry
//============================================================
BOOL fRc = GetListOfDriversCurrentlyInRegistry(WDM_DREDGE_KEY,ArrDriversInRegistry);
if( fRc )
{
//=====================================================================
// Get a list of binary mofs from WMI
// Query WMIBinaryMofResource for list of static mofs
//=====================================================================
GetListOfBinaryMofs();
if( m_uResourceCount > 0 )
{
//===============================================================
// Go through and get all the resources to process one by one
//===============================================================
CAutoWChar FileName(MAX_PATH*2);
CAutoWChar Resource(MAX_PATH*2);
CAutoWChar TmpKey(MAX_PATH*2);
if( FileName.Valid() && Resource.Valid() && TmpKey.Valid() )
{
while( GetBinaryMofFileNameAndResourceName(FileName,Resource))
{
//============================================================
// Process the binary mof, keep going until one needs to
// be processed
//============================================================
ExtractBinaryMofFromFile(FileName,Resource,TmpKey, fBinaryMofHasChanged );
if( fBinaryMofHasChanged )
{
break;
}
ArrDriversInRegistry.Remove(TmpKey);
}
}
}
if( !fBinaryMofHasChanged )
{
//=========================================
// Query the binary guid
//=========================================
CNamespaceManagement * pNamespace = new CNamespaceManagement(this);
if( pNamespace )
{
pNamespace->InitQuery(L"select * from WMIBinaryMofResource where Name != ");
CWMIStandardShell * pWMI = new CWMIStandardShell;
if( pWMI )
{
hr = pWMI->Initialize(NULL, FALSE, NULL,m_fUpdateNamespace, WMIGUID_QUERY,NULL,NULL,NULL);
if( S_OK == hr )
{
hr = pWMI->QueryAndProcessAllBinaryGuidInstances(*pNamespace, fBinaryMofHasChanged,&ArrDriversInRegistry);
}
SAFE_DELETE_PTR(pWMI);
}
SAFE_DELETE_PTR(pNamespace);
}
else
{
hr = WBEM_E_OUT_OF_MEMORY;
}
}
/* //============================================================
// If there are any drivers left in the list, then we need
// to say that the binary mofs have changed
//============================================================
if( !fBinaryMofHasChanged )
{
if( ArrDriversInRegistry.OldDriversLeftOver() )
{
fBinaryMofHasChanged = TRUE;
}
}
*/
}
else
{
//==============================================================================================
// there is no key, so now we need to return that the registry has changed, so the copy of the
// keys will be kicked off
//==============================================================================================
fBinaryMofHasChanged = TRUE;
}
if( m_pMofResourceInfo )
{
WmiFreeBuffer( m_pMofResourceInfo );
}
ERRORTRACE((THISPROVIDER,"***************\n"));
if( fBinaryMofHasChanged )
{
ERRORTRACE((THISPROVIDER,"BinaryMofsHaveChanged returned TRUE:\n"));
}
else
{
ERRORTRACE((THISPROVIDER,"BinaryMofsHaveChanged returned FALSE:\n"));
}
}
return fBinaryMofHasChanged;
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//**********************************************************************************************************************
// Namespace Management Class
//**********************************************************************************************************************
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
CNamespaceManagement::CNamespaceManagement(CWMIBinMof * pOwner)
{
m_pObj = pOwner;
m_nSize = 0;
m_pwcsQuery = NULL;
m_fInit = 0;
m_pwcsSavedQuery = NULL;
m_fSavedInit = 0;
m_nSavedSize = 0;
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
CNamespaceManagement::~CNamespaceManagement()
{
SAFE_DELETE_ARRAY( m_pwcsQuery );
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#define SERVICES_PTR m_pObj->WMI()->Services()
#define CONTEXT_PTR m_pObj->WMI()->Context()
/////////////////////////////////////////////////////////////////////////////////////////////////
// Delete stranded classes in the repository
/////////////////////////////////////////////////////////////////////////////////////////////////
BOOL CNamespaceManagement::DeleteStrandedClasses(void)
{
BOOL fRc = TRUE;
HRESULT hr = WBEM_NO_ERROR;
IEnumWbemClassObject* pEnum = NULL;
IEnumWbemClassObject* pEnumofStrandedClasses = NULL;
// ==================================================================================
// Get list of drivers
// ==================================================================================
InitQuery(L"select * from WMIBinaryMofResource");
CBSTR strQryLang(L"WQL");
CBSTR cbstrQry(m_pwcsQuery);
hr = SERVICES_PTR->ExecQuery(strQryLang,cbstrQry, WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY,CONTEXT_PTR,&pEnum);
if( hr == WBEM_NO_ERROR )
{
unsigned long uReturned = 0;
CVARIANT vDriver, vLow, vHigh;
IWbemClassObject * pClass = NULL;
//================================================================================
// Initialize query for stranded classes as we go along and clean up the old
// classes
//================================================================================
InitQuery(L"select * from WDMClassesOfDriver where Driver != ");
while ( TRUE )
{
IWbemClassObject * pClass = NULL;
if( WBEM_NO_ERROR == (hr = pEnum->Next(2000, 1, &pClass, &uReturned)))
{
if( WBEM_NO_ERROR == (hr = pClass->Get(L"Name", 0, &vDriver, 0, 0)))
{
//============================================================
// Correct the query syntax for next query
//============================================================
UpdateQuery( L" and Driver != ",vDriver.GetStr());
}
}
SAFE_RELEASE_PTR(pClass );
if( hr != WBEM_NO_ERROR )
{
break;
}
}
//================================================================
// Ok, now go after the stranded classes, the ones that don't
// have any drivers for some reason
//================================================================
CBSTR strQryLang(L"WQL");
CBSTR cbstr(m_pwcsQuery);
hr = SERVICES_PTR->ExecQuery(strQryLang,cbstr, WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY,CONTEXT_PTR,&pEnumofStrandedClasses);
if( hr == WBEM_NO_ERROR )
{
BOOL bDrivers = FALSE;
while( TRUE )
{
if( WBEM_NO_ERROR == (hr = pEnumofStrandedClasses->Next(2000, 1, &pClass, &uReturned)))
{
CVARIANT vPath,vClass;
pClass->Get(L"ClassName", 0, &vClass, 0, 0);
if(SUCCEEDED(hr = pClass->Get(L"__RELPATH", 0, &vPath, 0, 0)))
{
hr = DeleteUnusedClassAndDriverInfo( TRUE, vPath.GetStr(),vClass.GetStr() );
}
else
{
fRc = FALSE;
break;
}
}
SAFE_RELEASE_PTR(pClass);
if( hr != WBEM_NO_ERROR )
{
break;
}
}
SAFE_RELEASE_PTR(pEnumofStrandedClasses);
if(!fRc)
{
if( hr != E_OUTOFMEMORY)
{
ERRORTRACE((THISPROVIDER,"Stranded instance exist in repository"));
}
}
}
}
SAFE_RELEASE_PTR(pEnum);
return fRc;
}
////////////////////////////////////////////////////////////////////////////////////////////////////////
BOOL CNamespaceManagement::DeleteOldDrivers(BOOL fCompareDates)
{
HRESULT hr = WBEM_E_FAILED;
IEnumWbemClassObject* pEnum = NULL;
BOOL fRc = TRUE;
BSTR strQry = NULL;
strQry = SysAllocString(m_pwcsQuery);
if(strQry != NULL)
{
CBSTR strQryLang(L"WQL");
hr = SERVICES_PTR->ExecQuery(strQryLang, strQry, WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY,CONTEXT_PTR,&pEnum);
SysFreeString(strQry);
strQry = NULL;
}
else
{
hr = E_OUTOFMEMORY;
fRc = FALSE;
}
if( hr == WBEM_NO_ERROR )
{
IWbemClassObject * pClass = NULL;
unsigned long uReturned = 0;
CVARIANT vClass;
hr = WBEM_NO_ERROR;
//============================================================================================
// NOTE: We only deal with drivers extracted from files here, if it is a guid as the result
// of an event this is handled elsewhere
//============================================================================================
while ( hr == WBEM_NO_ERROR )
{
IWbemClassObject * pClass = NULL;
unsigned long uReturned = 0;
hr = pEnum->Next(2000, 1, &pClass, &uReturned);
if( hr == WBEM_NO_ERROR )
{
CVARIANT vLowDate, vHighDate, vName;
if( WBEM_NO_ERROR != (hr = pClass->Get(L"Name", 0, &vName, 0, 0)))
{
break;
}
if( fCompareDates )
{
vLowDate.SetLONG(0);
vHighDate.SetLONG(0);
if( WBEM_NO_ERROR != (hr = pClass->Get(L"LowDateTime", 0, &vLowDate, 0, 0)))
{
break;
}
if( WBEM_NO_ERROR != (hr = pClass->Get(L"HighDateTime", 0, &vHighDate, 0, 0)))
{
break;
}
}
ERRORTRACE((THISPROVIDER,"Deleting Old Drivers"));
if( DeleteOldClasses((WCHAR *) vName.GetStr(),vLowDate,vHighDate,fCompareDates ))
{
CVARIANT vPath;
hr = pClass->Get(L"__RELPATH", 0, &vPath, 0, 0);
if( hr == WBEM_NO_ERROR )
{
CBSTR cbstrPath(vPath.GetStr());
hr = SERVICES_PTR->DeleteInstance(cbstrPath,WBEM_FLAG_OWNER_UPDATE,CONTEXT_PTR,NULL);
ERRORTRACE((THISPROVIDER,"We have been requested to delete this mof, it is being removed\n"));
TranslateAndLog(cbstrPath);
}
if( WBEM_NO_ERROR == hr )
{
m_pObj->DeleteMofFromRegistry((WCHAR *) vName.GetStr());
}
else
{
ERRORTRACE((THISPROVIDER,"Stranded instance: \n"));
TranslateAndLog(vPath.GetStr());
ERRORTRACE((THISPROVIDER,"DeleteInstance return value: %ld\n",hr));
ERRORTRACE((THISPROVIDER,"Current query: \n"));
TranslateAndLog(m_pwcsQuery);
}
}
}
}
SAFE_RELEASE_PTR(pEnum);
}
else
{
ERRORTRACE((THISPROVIDER,"Cannot delete driver. ExecQuery return value: %ld\n",hr));
ERRORTRACE((THISPROVIDER,"Current query: \n"));
TranslateAndLog(m_pwcsQuery);
}
return fRc;
}
/////////////////////////////////////////////////////////////////////////////////////////////////
// Function to delete Old classes for a particular driver
/////////////////////////////////////////////////////////////////////////////////////////////////
BOOL CNamespaceManagement::DeleteOldClasses(WCHAR * wcsFileName,CVARIANT & vLow, CVARIANT & vHigh, BOOL fCompareDates)
{
HRESULT hr = WBEM_E_FAILED;
CAutoWChar wcsTranslatedKey(MAX_PATH*2);
BOOL fRc = FALSE;
IEnumWbemClassObject* pEnum = NULL;
ULONG lHighDateTime = 0L;
ULONG lLowDateTime = 0L;
ERRORTRACE((THISPROVIDER,"Deleting Old Classes for Driver"));
TranslateAndLog(wcsFileName);
ERRORTRACE((THISPROVIDER,"*******\n"));
if( wcsTranslatedKey.Valid() )
{
//================================================================================
// Initialize everything we need to construct the query
//================================================================================
if( fCompareDates )
{
lLowDateTime= (ULONG)vLow.GetLONG();
lHighDateTime= (ULONG)vHigh.GetLONG();
}
ConvertStringToCTypeString( wcsTranslatedKey,wcsFileName );
//================================================================================
// Now, pick up all the old classes for this driver
//================================================================================
InitQuery(L"select * from WDMClassesOfDriver where Driver = ");
UpdateQuery(L"",wcsFileName);
UpdateQuery(L" and (HighDateTime != ",lHighDateTime);
UpdateQuery(L" or LowDateTime != ", lLowDateTime);
AddToQuery(L")");
BSTR strTmp = NULL;
strTmp = SysAllocString(m_pwcsQuery);
if(strTmp != NULL)
{
CBSTR strQryLang(L"WQL");
hr = SERVICES_PTR->ExecQuery(strQryLang, strTmp, WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY,CONTEXT_PTR,&pEnum);
SysFreeString(strTmp);
strTmp = NULL;
}
else
{
hr = E_OUTOFMEMORY;
fRc = FALSE;
}
if( hr == WBEM_NO_ERROR )
{
IWbemClassObject * pClass = NULL;
unsigned long uReturned = 0;
CVARIANT vClass;
CAutoWChar wcsObjectPath(MAX_PATH*4);
if( wcsObjectPath.Valid() )
{
while ( TRUE )
{
hr = pEnum->Next(2000, 1, &pClass, &uReturned);
if( hr!= WBEM_NO_ERROR )
{
break;
}
hr = pClass->Get(L"ClassName", 0, &vClass, 0, 0);
if( hr != WBEM_NO_ERROR )
{
break;
}
//===========================================================================
// Now, get this instance of tying the class with this old date
//===========================================================================
CVARIANT vPath;
hr = pClass->Get(L"__RELPATH", 0, &vPath, 0, 0);
if( hr != WBEM_NO_ERROR )
{
break;
}
//==========================================================================
// Now, just because we get a class name here doesn't mean we delete the
// class, this class could have been updated, in that case we just delete
// the instance of the WDMClassesOfDriver.
// Now, we need to check to see if this class really needs to be deleted
// or not
//==========================================================================
IWbemClassObject * pTmp = NULL;
CBSTR bTmp = vClass.GetStr();
swprintf(wcsObjectPath,L"WDMClassesOfDriver.ClassName=\"%s\",Driver=\"%s\",HighDateTime=%lu,LowDateTime=%lu",bTmp,wcsTranslatedKey,lHighDateTime,lLowDateTime);
CBSTR bstrQuery = wcsObjectPath;
hr = SERVICES_PTR->GetObject(bstrQuery,0,CONTEXT_PTR,&pTmp,NULL);
//===========================================================================
// this is simple, if we get an instance of WDMClassesOfDriver
// with the newer date, then we know it has been updated, so we don't
// delete the class
//===========================================================================
BOOL fDeleteOldClass = TRUE;
if( hr == WBEM_NO_ERROR )
{
fDeleteOldClass = FALSE;
}
hr = DeleteUnusedClassAndDriverInfo( fDeleteOldClass, vPath.GetStr(),vClass.GetStr() );
//===========================================================================
// Now, delete the WDM Instance of the Old Driver
//===========================================================================
SAFE_RELEASE_PTR( pTmp )
SAFE_RELEASE_PTR( pClass );
vClass.Clear();
}
SAFE_RELEASE_PTR(pEnum);
}
}
if( hr == WBEM_NO_ERROR || hr == WBEM_S_NO_MORE_DATA || hr == WBEM_S_FALSE)
{
fRc = TRUE;
}
}
return fRc;
}
/////////////////////////////////////////////////////////////////////
BOOL CNamespaceManagement::CreateInstance ( WCHAR * wcsDriver, WCHAR * wcsClass, ULONG lLowDateTime, ULONG lHighDateTime )
{
IWbemClassObject * pInst = NULL, * pClass = NULL;
//==================================================
// Get a pointer to a IWbemClassObject object
//==================================================
HRESULT hr;
CVARIANT cvarName;
cvarName.SetStr(L"WDMClassesOfDriver");
hr = SERVICES_PTR->GetObject(cvarName, 0,CONTEXT_PTR, &pClass, NULL);
if(FAILED(hr)){
return FALSE;
}
//=============================================================
// Spawn a new instance
//=============================================================
hr = pClass->SpawnInstance(0, &pInst);
SAFE_RELEASE_PTR(pClass);
if( FAILED(hr) ){
return hr;
}
//=============================================================
// Put the data in the instance
//=============================================================
CVARIANT vClass, vDriver, vLow, vHigh;
vClass.SetStr(wcsClass);
vDriver.SetStr(wcsDriver);
vLow.SetLONG(lLowDateTime);
vHigh.SetLONG(lHighDateTime);
hr = pInst->Put(L"Driver", 0, &vDriver, NULL);
if( hr == WBEM_S_NO_ERROR )
{
hr = pInst->Put(L"ClassName", 0, &vClass, NULL);
hr = pInst->Put(L"LowDateTime", 0, &vLow, NULL);
hr = pInst->Put(L"HighDateTime", 0, &vHigh, NULL);
if( hr == WBEM_S_NO_ERROR )
{
hr = SERVICES_PTR->PutInstance(pInst,WBEM_FLAG_OWNER_UPDATE,CONTEXT_PTR,NULL);
}
}
SAFE_RELEASE_PTR(pInst);
if( WBEM_NO_ERROR == hr ){
return TRUE;
}
return FALSE;
}
/////////////////////////////////////////////////////////////////////
void CNamespaceManagement::CreateClassAssociationsToDriver(WCHAR * wcsFileName, BYTE* pRes, ULONG lLowDateTime, ULONG lHighDateTime)
{
CBMOFObjList * pol;
CBMOFObj * po;
CAnsiUnicode XLate;
//===========================================================================
// Now use the helper functions from David's mofcomp stuff to extract the
// class names we are going to add the Driver qualifier to.
// list structure and use it to enumerate the objects.
//===========================================================================
BYTE * pByte = m_pObj->DecompressBinaryMof(pRes);
if( pByte ){
pol = CreateObjList(pByte);
if(pol != NULL){
ResetObjList (pol);
while(po = NextObj(pol)){
WCHAR * pName = NULL;
if(GetName(po, &pName)){
//===============================================================
// Now, we have the name of the class in pName, we have the
// name of the driver, in wcsFileName
//===============================================================
CreateInstance(wcsFileName, pName, lLowDateTime, lHighDateTime );
BMOFFree(pName);
}
BMOFFree(po);
}
BMOFFree(pol);
}
}
else{
ERRORTRACE((THISPROVIDER,"Could not tie classes to driver for file:\n"));
TranslateAndLog(wcsFileName);
}
if( pByte ){
free(pByte);
}
}
/////////////////////////////////////////////////////////////////////
HRESULT CNamespaceManagement::AllocMemory(WCHAR *& p)
{
HRESULT hr = WBEM_E_FAILED;
p = new WCHAR[m_nSize+4];
if( p )
{
memset(p,NULL,m_nSize+4);
hr = WBEM_NO_ERROR;
}
return hr;
}
/////////////////////////////////////////////////////////////////////
void CNamespaceManagement::AddToQuery(WCHAR * p)
{
int nNewSize = wcslen(p) * sizeof(WCHAR);
int nCurrentBuf = 0;
if( m_pwcsQuery )
{
nCurrentBuf = (int)(wcslen(m_pwcsQuery) + 1) * sizeof(WCHAR);
}
if( nNewSize >= (m_nSize - nCurrentBuf))
{
int nOldSize = m_nSize;
WCHAR * pOld = m_pwcsQuery;
m_nSize += MEMSIZETOALLOCATE;
if( SUCCEEDED(AllocMemory(m_pwcsQuery)))
{
memcpy(m_pwcsQuery,pOld,nOldSize);
}
SAFE_DELETE_ARRAY(pOld);
}
if( wcslen(m_pwcsQuery) == 0 )
{
wcscpy(m_pwcsQuery,p);
}
else
{
wcscat(m_pwcsQuery,p);
}
}
/////////////////////////////////////////////////////////////////////
void CNamespaceManagement::InitQuery(WCHAR * p)
{
SAFE_DELETE_ARRAY(m_pwcsQuery);
m_nSize = MEMSIZETOALLOCATE;
m_fInit = TRUE;
if(SUCCEEDED(AllocMemory(m_pwcsQuery)))
{
AddToQuery(p);
}
}
/////////////////////////////////////////////////////////////////////
void CNamespaceManagement::UpdateQuery( WCHAR * pQueryAddOn, WCHAR * wcsParam )
{
CAutoWChar wcsTranslatedKey(MAX_PATH*3);
if( wcsTranslatedKey.Valid() )
{
ConvertStringToCTypeString( wcsTranslatedKey,wcsParam );
//=============================================
// The first time only we DON'T add the query
// add on string, otherwise, we do
//=============================================
if( !m_fInit )
{
AddToQuery(pQueryAddOn);
}
AddToQuery(L"\"");
AddToQuery(wcsTranslatedKey);
AddToQuery(L"\"");
m_fInit = FALSE;
}
}
/////////////////////////////////////////////////////////////////////
void CNamespaceManagement::SaveCurrentQuery()
{
m_nSavedSize = m_nSize;
m_fSavedInit = m_fInit;
if( SUCCEEDED(AllocMemory(m_pwcsSavedQuery))){
memcpy(m_pwcsSavedQuery,m_pwcsQuery,m_nSize);
}
SAFE_DELETE_ARRAY(m_pwcsQuery);
}
/////////////////////////////////////////////////////////////////////
void CNamespaceManagement::RestoreQuery()
{
SAFE_DELETE_ARRAY(m_pwcsQuery);
m_nSize = m_nSavedSize;
m_fInit = m_fSavedInit;
if( SUCCEEDED(AllocMemory(m_pwcsQuery))){
memcpy(m_pwcsQuery, m_pwcsSavedQuery,m_nSize);
}
m_fSavedInit = 0;
m_nSavedSize = 0;
SAFE_DELETE_ARRAY(m_pwcsSavedQuery);
}
/////////////////////////////////////////////////////////////////////
void CNamespaceManagement::UpdateQuery( WCHAR * pQueryAddOn, ULONG lLong )
{
CAutoWChar wcsBuf(MAX_PATH);
if( wcsBuf.Valid() )
{
AddToQuery(pQueryAddOn);
swprintf(wcsBuf,L"%lu",lLong);
AddToQuery(wcsBuf);
m_fInit = FALSE;
}
}
/////////////////////////////////////////////////////////////////////
HRESULT CNamespaceManagement::DeleteUnusedClassAndDriverInfo(BOOL fDeleteOldClass, WCHAR * wcsPath, WCHAR * wcsClass)
{
HRESULT hr = WBEM_NO_ERROR;
if( fDeleteOldClass )
{
CBSTR bstr(wcsClass );
hr = SERVICES_PTR->DeleteClass(bstr,WBEM_FLAG_OWNER_UPDATE,CONTEXT_PTR,NULL);
if( hr != WBEM_NO_ERROR )
{
if( WBEM_E_NOT_FOUND != hr )
{
ERRORTRACE((THISPROVIDER,"Tried to delete class but couldn't, return code: %ld for class: \n",hr));
TranslateAndLog(wcsClass);
}
else
{
hr = WBEM_NO_ERROR;
}
}
}
if( WBEM_NO_ERROR == hr )
{
// Ok, we may or may have not deleted the class, if it was tied to a different driver, we
// shouldn't have deleted the class, but we want to delete the controlling instance, as
// that driver is no longer there.
hr = SERVICES_PTR->DeleteInstance(wcsPath,WBEM_FLAG_OWNER_UPDATE,CONTEXT_PTR,NULL);
if( WBEM_NO_ERROR != hr )
{
if( hr != WBEM_E_NOT_FOUND )
{
ERRORTRACE((THISPROVIDER,"DeleteUnUnsedClasses Stranded instance: \n"));
TranslateAndLog(wcsPath);
ERRORTRACE((THISPROVIDER,"DeleteInstance return value: %ld\n",hr));
}
}
}
return hr;
}