Leaked source code of windows server 2003
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.
 
 
 
 
 
 

2830 lines
100 KiB

/////////////////////////////////////////////////////////////////////
//
// BINMOF.CPP
//
// Module:
// Purpose:
//
// Copyright (c) 1997-2002 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>
#include <autoptr.h>
#include <comdef.h>
#include <strutils.h>
//
// auto variables
//
#include <ScopeGuard.h>
#if defined(_M_IA64)
//
// NTBUG#744176
//
template void deleteArray<unsigned char>(unsigned char*);
template void deleteArray<unsigned short>(unsigned short*);
template void deletePtr<CWMIStandardShell>(const CWMIStandardShell*);
template void deletePtr<CNamespaceManagement>(const CNamespaceManagement*);
#endif
#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);
}
///////////////////////////////////////////////////////////////////////////////////////////////////
HRESULT ConvertStringToCTypeString( WCHAR * Out, int cchSizeOut, WCHAR * In )
{
HRESULT hr = WBEM_E_INVALID_PARAMETER;
WCHAR * token = NULL;
if(In)
{
CAutoWChar tmpBuf(_MAX_PATH*2);
if( tmpBuf.Valid() )
{
if ( hr = SUCCEEDED ( StringCchCopyW ((WCHAR*)tmpBuf,_MAX_PATH*2,In) ) )
{
token = wcstok( (WCHAR*)tmpBuf, L"\\" );
if( !token )
{
hr = StringCchCopyW (Out,cchSizeOut,In);
}
else
{
hr = WBEM_S_FALSE;
BOOL fFirst = TRUE;
while( SUCCEEDED ( hr ) && token != NULL )
{
if( fFirst )
{
hr = StringCchCopyW(Out,cchSizeOut,token);
fFirst = FALSE;
}
else
{
if ( SUCCEEDED ( hr = StringCchCatW(Out,cchSizeOut,L"\\\\") ) )
{
hr = StringCchCatW(Out,cchSizeOut,token);
}
}
token = wcstok( NULL, L"\\" );
}
}
}
}
}
return hr;
}
///////////////////////////////////////////////////////////////////////////////////////////
//*****************************************************************************************
// 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,
IWbemServices __RPC_FAR * pRepository,
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, pRepository, 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->Repository(),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,
IWbemServices __RPC_FAR * pRepository,
IWbemObjectSink __RPC_FAR * pHandler,
IWbemContext __RPC_FAR *pCtx
)
{
HRESULT hr = WBEM_E_FAILED;
hr = InitializePtrs(pList,pServices,pRepository,pHandler,pCtx);
m_fUpdateNamespace = fUpdateNamespace;
return hr;
}
/////////////////////////////////////////////////////////////////////
CWMIBinMof::~CWMIBinMof()
{
SAFE_RELEASE_PTR(m_pCompiler);
SAFE_DELETE_PTR(m_pWMI);
}
/////////////////////////////////////////////////////////////////////
HRESULT CWMIBinMof::OpenFileAndLookForItIfItDoesNotExist(wmilib::auto_buffer<TCHAR> & pFile, HANDLE & hFile )
{
HRESULT hr = S_OK;
//=========================================================================
// Ok, hopefully CreateFile will find it
//=========================================================================
hFile = CreateFile(pFile.get(), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
if( hFile != INVALID_HANDLE_VALUE )
{
return S_OK;
}
// cache last error value
DWORD dwLastError = ::GetLastError ();
hr = WBEM_E_FAILED;
//=====================================================================
// CreateFile DIDN'T find it, so look in the Windows dir
//=====================================================================
wmilib::auto_ptr<TCHAR> pszSysDir( new TCHAR[MAX_PATH+1]);
if ( NULL == pszSysDir.get() ) return WBEM_E_OUT_OF_MEMORY;;
UINT uSize = GetSystemDirectory(pszSysDir.get(), MAX_PATH+1);
if( 0 == uSize )
{
::SetLastError ( dwLastError );
return WBEM_E_FAILED;
}
if ( uSize > MAX_PATH )
{
pszSysDir.reset( new TCHAR [ uSize + 1 ]);
if ( NULL == pszSysDir.get()) return WBEM_E_OUT_OF_MEMORY;
if (!GetSystemDirectory( pszSysDir.get(), uSize + 1 ) )
{
return WBEM_E_FAILED;
}
}
wmilib::auto_buffer<TCHAR> pFileNew( new TCHAR[MAX_PATH*2 + 1]);
if( NULL == pFileNew.get() ) return WBEM_E_OUT_OF_MEMORY;
if (FAILED( hr = StringCchPrintfW ( pFileNew.get(), MAX_PATH*2 + 1, L"%s\\%s", pszSysDir.get(), pFile.get())))
{
::SetLastError ( dwLastError );
return WBEM_E_FAILED;
}
//=============================================================
// Ok, now try to open again
//=============================================================
hFile = CreateFile(pFileNew.get(), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
if( hFile == INVALID_HANDLE_VALUE )
{
::SetLastError ( dwLastError );
return WBEM_E_FAILED;
}
pFile.reset(pFileNew.release());
return S_OK;
}
/////////////////////////////////////////////////////////////////////
BOOL CWMIBinMof::GetFileDateAndTime(ULONG & lLowDateTime,ULONG & lHighDateTime,WCHAR * wcsFileName, int cchSize)
{
HANDLE hFile = NULL;
FILETIME ftCreationTime, ftLastAccessTime, ftLastWriteTime,ftLocal;
BOOL fRc = FALSE;
wmilib::auto_buffer<TCHAR> pFile;
if( ExtractFileNameFromKey(pFile,wcsFileName,cchSize) )
{
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.get(), MAX_PATH * 4, sFullPath, &sFilename) != 0)
{
StringCchCopyW ( wcsFileName, MAX_PATH*4, sFullPath );
}
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));
}
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 \\
//==================================================
if ( SUCCEEDED ( hr = ConvertStringToCTypeString( wcsTmp,_MAX_PATH*4,wcsFileName ) ) )
{
if ( SUCCEEDED ( hr = StringCchPrintfW(wcsBuf,_MAX_PATH*4,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 = REPOSITORY->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;
if ( SUCCEEDED ( hr = StringCchPrintfW(wcsQuery,MEMSIZETOALLOCATE,L"select * from WMIBinaryMofResource where Name = \"%s\"",wcsTmp) ) )
{
CBSTR bstrTemp = wcsQuery;
CBSTR strQryLang(L"WQL");
hr = REPOSITORY->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( vPath.GetStr() )
{
if( wbem_wcsicmp(vPath.GetStr(),wcsBuf) != 0 )
{
hr = REPOSITORY->DeleteInstance(vPath.GetStr(),0,CONTEXT,NULL);
if ( FAILED ( hr ) )
{
ERRORTRACE((THISPROVIDER,"We have been requested to delete this mof:\n"));
TranslateAndLog(vPath.GetStr());
ERRORTRACE((THISPROVIDER,"It failed with 0x%08lx\n", hr));
}
else
{
DEBUGTRACE((THISPROVIDER,"We have been requested to delete this mof:\n"));
TranslateAndLog(vPath.GetStr(), TRUE);
}
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 = REPOSITORY->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 = REPOSITORY->PutInstance(pNewInst,WBEM_FLAG_CREATE_OR_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, int cchSize )
{
BOOL fReturn = FALSE;
WCHAR * pc = wcsrchr(pwcsTempPath,'\\');
if(pc)
{
//==================================================
// Copy what was there and set the end to NULL
//==================================================
pc++;
if ( *pc )
{
if ( SUCCEEDED ( StringCchCopyW ( pwcsEnd, cchSize, pc ) ) )
{
fReturn = TRUE;
}
}
pc--;
*(pc) = NULL;
}
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 = new TCHAR[_MAX_PATH + 1];
if ( szWindowsDir )
{
UINT uSize = GetWindowsDirectory ( szWindowsDir , _MAX_PATH + 1);
if ( uSize )
{
if ( uSize > MAX_PATH )
{
SAFE_DELETE_ARRAY ( szWindowsDir );
szWindowsDir = new TCHAR [ uSize + 1 ];
if ( szWindowsDir )
{
if ( ! GetWindowsDirectory( szWindowsDir, uSize + 1 ) )
{
SAFE_DELETE_ARRAY ( szWindowsDir );
return fLoadDefaultLocale;
}
}
else
{
return fLoadDefaultLocale;
}
}
//==========================================================
// if these are windows directories
//==========================================================
if( 0 == wbem_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
//======================================================
if ( SUCCEEDED ( StringCchCopyW (wcsTempPath,_MAX_PATH,wcsFile) ) )
{
if( GetNextSectionFromTheEnd( wcsTempPath, wcsBuffer, _MAX_PATH ))
{
//==================================================
// Now, get the potential locale id
//==================================================
if( GetNextSectionFromTheEnd( wcsTempPath, wcsBuffer, _MAX_PATH ))
{
wLocalId = (WORD) _wtoi(wcsBuffer);
//==============================================
// Now, get the next bit to see if it says MUI
// or Fallback
//==============================================
if( GetNextSectionFromTheEnd( wcsTempPath, wcsBuffer, _MAX_PATH ))
{
if( 0 == wbem_wcsicmp( L"MUI", wcsBuffer ))
{
fLoadDefaultLocale = FALSE;
}
else if( 0 == wbem_wcsicmp( L"Fallback", wcsBuffer ) )
{
//==============================================
// If it says Fallback, then check to make
// sure the next bit says MUI
//==============================================
if( GetNextSectionFromTheEnd( wcsTempPath, wcsBuffer, _MAX_PATH ))
{
if( 0 == wbem_wcsicmp( L"MUI", wcsBuffer ) )
{
fLoadDefaultLocale = FALSE;
}
}
}
}
}
}
}
}
}
}
SAFE_DELETE_ARRAY ( szWindowsDir );
}
return fLoadDefaultLocale;
}
///////////////////////////////////////////////////////////////////
BOOL CWMIBinMof::GetPointerToBinaryResource(BYTE *& pRes,
DWORD & dwSize,
HGLOBAL & hResource,
HINSTANCE & hInst,
WCHAR * wcsResource,
WCHAR * wcsFile,
int cchSizeFile)
{
TCHAR * pResource = NULL;
BOOL fRc = FALSE;
DWORD dwError = 0;
wmilib::auto_buffer<TCHAR> pFile;
if( ExtractFileNameFromKey(pFile,wcsFile,cchSizeFile) ){
pResource = wcsResource;
if( pResource )
{
hInst = LoadLibraryEx(pFile.get(),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
}
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(wmilib::auto_buffer<TCHAR> & pKey,WCHAR * wcsKey,int cchSize)
{
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.
//======================================================
if ( SUCCEEDED ( StringCchCopyW (wcsTmp,MAX_PATH*4,wcsKey) ) )
{
wcsToken = wcstok(wcsTmp, L"[" );
if( wcsToken != NULL )
{
StringCchCopyW(wcsTmp,MAX_PATH*4,wcsToken);
}
int cchSizeNew = lstrlenW ( wcsTmp ) + 1;
pKey.reset(new TCHAR[cchSizeNew]);
if(pKey.get())
{
if ( SUCCEEDED ( StringCchCopyW (pKey.get(),cchSizeNew,wcsTmp) ) )
{
fRc = TRUE;
}
}
}
}
}
return fRc;
}
/////////////////////////////////////////////////////////////////////
HRESULT CWMIBinMof::CreateKey(WCHAR * wcsFileName, WCHAR * wcsResource,WCHAR * wcsKey, int cchSizeKey)
{
return StringCchPrintfW(wcsKey,cchSizeKey,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,
WBEM_FLAG_CONNECT_PROVIDERS,
WBEM_FLAG_OWNER_UPDATE,
WBEM_FLAG_OWNER_UPDATE,
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,"***************************************\n"));
ERRORTRACE((THISPROVIDER,"WBEM_COMPILE_STATUS_INFO:\n"));
ERRORTRACE((THISPROVIDER,"\tphase:\t%d\n",Info.lPhaseError));
ERRORTRACE((THISPROVIDER,"\thresult:\t0x%x\n",Info.hRes));
ERRORTRACE((THISPROVIDER,"***************************************\n"));
ERRORTRACE((THISPROVIDER,"Size of Mof: %ld\n",dwSize));
ERRORTRACE((THISPROVIDER,"***************************************\n"));
}
else
{
DEBUGTRACE((THISPROVIDER,"***************************************\n"));
DEBUGTRACE((THISPROVIDER,"Binary mof succeeded for:\n"));
TranslateAndLog(wcsKey, TRUE);
DEBUGTRACE((THISPROVIDER,"***************************************\n"));
}
}
return hr;
}
/////////////////////////////////////////////////////////////////////
BOOL CWMIBinMof::ExtractBinaryMofFromFile(WCHAR * wcsFile, WCHAR * wcsResource,WCHAR * wcsKey, int cchSizeKey, BOOL & fMofHasChanged)
{
HRESULT hr;
BOOL fSuccess = FALSE;
CAutoWChar wcsTmp(MAX_PATH*4);
try
{
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.
//==============================================
if ( SUCCEEDED ( StringCchCopyW(wcsTmp,MAX_PATH*4,wcsFile) ) )
{
if( GetFileDateAndTime(lLowDateTime,lHighDateTime,wcsTmp,MAX_PATH*4) )
{
if ( SUCCEEDED ( CreateKey(wcsTmp,wcsResource,wcsKey,cchSizeKey) ) )
{
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,cchSizeKey) )
{
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
{
UpdateMofTimestampInHMOM(wcsFile,lLowDateTime,lHighDateTime,FALSE);
StringCchCopyW(wcsKey, cchSizeKey, wcsFile);
}
}
}
}
catch ( CHeap_Exception & exc )
{
fSuccess = FALSE ;
}
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;
try
{
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 )
{
ON_BLOCK_EXIT ( deletePtr < CWMIStandardShell >, pWMI ) ;
hr = pWMI->Initialize (
NULL,
FALSE,
m_pWMI->HandleMap(),
m_fUpdateNamespace,
WMIGUID_QUERY,
m_pWMI->Services(),
m_pWMI->Repository(),
m_pWMI->Handler(),
m_pWMI->Context()
);
if( S_OK == hr )
{
CNamespaceManagement * pNamespace = new CNamespaceManagement(this);
if( pNamespace )
{
ON_BLOCK_EXIT ( deletePtr < CNamespaceManagement >, pNamespace ) ;
//=========================================
// Query the binary guid
//=========================================
if ( SUCCEEDED ( hr = pNamespace->InitQuery(L"select * from WMIBinaryMofResource where Name != ") ) )
{
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,MAX_PATH*3,wcsResource,MAX_PATH*3) && SUCCEEDED ( hr ) )
{
//============================================================
// Process the binary mof
//============================================================
if( ExtractBinaryMofFromFile(wcsFileName,wcsResource,wcsTmpKey,MAX_PATH*3,fMofChanged))
{
hr = pNamespace->UpdateQuery(L" and Name != ",wcsTmpKey);
}
if( fMofChanged )
{
fProcessStrandedClasses = TRUE;
}
ArrDriversInRegistry.Remove(wcsTmpKey);
}
}
}
if ( SUCCEEDED ( hr ) )
{
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);
}
else
{
DEBUGTRACE((THISPROVIDER,"***************************************\n"));
DEBUGTRACE((THISPROVIDER,"Failure in processing binary mofs\n"));
DEBUGTRACE((THISPROVIDER,"Resources %d\n", m_uResourceCount));
DEBUGTRACE((THISPROVIDER,"Current %d\n", m_uCurrentResource));
DEBUGTRACE((THISPROVIDER,"***************************************\n"));
}
}
}
}
}
if( m_pMofResourceInfo )
{
WmiFreeBuffer( m_pMofResourceInfo );
}
}
}
}
catch ( CHeap_Exception & exc )
{
}
DEBUGTRACE((THISPROVIDER,"End of processing Binary MOFS\n"));
DEBUGTRACE((THISPROVIDER,"***************************************\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, int cchSizeFile, WCHAR * pwcsResource, int cchSizeResource )
{
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( IsBadReadPtr( m_pMofResourceInfo[m_uCurrentResource].ImagePath,dwFileLen) == 0 )
{
if ( SUCCEEDED ( StringCchCopyW( pwcsFileName, cchSizeFile, m_pMofResourceInfo[m_uCurrentResource].ImagePath ) ) )
{
if( IsBadReadPtr( m_pMofResourceInfo[m_uCurrentResource].ResourceName,dwResourceLen) == 0 )
{
if ( SUCCEEDED ( StringCchCopyW ( pwcsResource, cchSizeResource, 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;
try
{
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;
}
}
catch ( CHeap_Exception & exc )
{
hr = WBEM_E_OUT_OF_MEMORY ;
}
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;
try
{
//=================================================================
// 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 )){
hr = CreateKey( vImagePath.GetStr(), vResourceName.GetStr(),wcsTmp, MAX_PATH*2 );
}
else if( vResourceName.GetType() != VT_NULL ){
hr = SetBinaryMofClassName(vResourceName.GetStr(),wcsTmp, MAX_PATH*2);
}
if ( SUCCEEDED ( hr ) )
{
if( m_fUpdateNamespace )
{
CNamespaceManagement Namespace(this);
if ( SUCCEEDED ( hr = Namespace.InitQuery(L"select * from WMIBinaryMofResource where Name = ") ) )
{
if ( SUCCEEDED ( hr = 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;
}
}
}
catch ( CHeap_Exception & exc )
{
hr = WBEM_E_OUT_OF_MEMORY ;
}
}
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 )
{
StringCchPrintfW(wcsBuf,MAX_PATH,L"LowDateTime:%ld,HighDateTime:%ld***Binary mof compiled successfully", lLowDateTime, lHighDateTime);
}
else
{
StringCchPrintfW(wcsBuf,MAX_PATH,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() )
{
if ( SUCCEEDED ( StringCchPrintfW (wcsIncomingValue, MAX_PATH, 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
//======================================================
if ( SUCCEEDED ( StringCchCopyW ( wcsTmp, MAX_PATH, (const WCHAR*)chsValue ) ) )
{
wcsToken = wcstok(wcsTmp, L"*" );
if( wcsToken != NULL )
{
if( wbem_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;
try
{
if (ERROR_SUCCESS == WDMReg.Open(HKEY_LOCAL_MACHINE, WDM_REG_KEY, KEY_READ))
{
ON_BLOCK_EXIT_OBJ ( WDMReg, CRegistry::Close ) ;
//===============================================================
// 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))
{
ON_BLOCK_EXIT_OBJ ( WDMDregReg, CRegistry::Close ) ;
CHString pchs(DREDGE_KEY);
WDMDregReg.DeleteKey ( &pchs ) ;
}
if( ERROR_SUCCESS == WDMDregReg.CreateOpen(HKEY_LOCAL_MACHINE, WDM_DREDGE_KEY))
{
ON_BLOCK_EXIT_OBJ ( WDMDregReg, CRegistry::Close ) ;
//===============================================================
// 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 )
{
ON_BLOCK_EXIT ( deleteArray < TCHAR >, pValueName ) ;
ON_BLOCK_EXIT ( deleteArray < BYTE >, pValueData ) ;
CHString chsKey(pValueName);
CHString chsValue((LPCWSTR)pValueData);
if ( !WDMDregReg.SetCurrentKeyValue ( chsKey, chsValue ) == ERROR_SUCCESS )
{
fSuccess = FALSE;
}
}
else
{
fSuccess = FALSE;
}
if( !fSuccess )
{
break;
}
}
}
}
}
catch ( CHeap_Exception & exc )
{
fSuccess = FALSE ;
}
return fSuccess;
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
BOOL CWMIBinMof::GetListOfDriversCurrentlyInRegistry(WCHAR * wcsKey, KeyList & ArrDriversInRegistry)
{
BOOL fSuccess = TRUE;
//==========================================================
// 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->Repository(),
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->Repository(),
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,
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,
NULL);
if( S_OK == hr )
{
// only provider will handle deletion of driver
// hr = pWMI->ProcessEvent(MOF_DELETED,WnodeHeader);
}
}
DEBUGTRACE((THISPROVIDER,"***************************************\n"));
if( pWMI->HasMofChanged() )
{
DEBUGTRACE((THISPROVIDER,"BinaryMofEventChanged returned TRUE:\n"));
}
else
{
DEBUGTRACE((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,MAX_PATH*2,Resource,MAX_PATH*2))
{
//============================================================
// Process the binary mof, keep going until one needs to
// be processed
//============================================================
ExtractBinaryMofFromFile(FileName,Resource,TmpKey, MAX_PATH*2,fBinaryMofHasChanged );
if( fBinaryMofHasChanged )
{
break;
}
ArrDriversInRegistry.Remove(TmpKey);
}
}
}
if( !fBinaryMofHasChanged )
{
//=========================================
// Query the binary guid
//=========================================
CNamespaceManagement * pNamespace = new CNamespaceManagement(this);
if( pNamespace )
{
if ( SUCCEEDED ( hr = 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,NULL);
if( S_OK == 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 );
}
DEBUGTRACE((THISPROVIDER,"***************************************\n"));
if( fBinaryMofHasChanged )
{
DEBUGTRACE((THISPROVIDER,"BinaryMofsHaveChanged returned TRUE:\n"));
}
else
{
DEBUGTRACE((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 REPOSITORY_PTR m_pObj->WMI()->Repository()
#define CONTEXT_PTR m_pObj->WMI()->Context()
/////////////////////////////////////////////////////////////////////////////////////////////////
//
// IsClassPseudoSystem
// ===================================
//
// returns false if class doesn't belong to set of
// pseudo system classes which should be not deleted
//
/////////////////////////////////////////////////////////////////////////////////////////////////
BOOL CNamespaceManagement::IsClassPseudoSystem ( LPCWSTR wcsClass )
{
BOOL fResult = FALSE ;
if ( wcsClass )
{
static LPWSTR wcsPseudoSystem [] = {
L"WMIEvent",
L"Win32_Perf",
L"Win32_PerfRawData",
L"Win32_PerfFormattedData"
};
static DWORD dwPseudoSystem = sizeof ( wcsPseudoSystem ) / sizeof ( wcsPseudoSystem [ 0 ] ) ;
for ( DWORD dwIndex = 0; dwIndex < dwPseudoSystem; dwIndex++ )
{
if ( 0 == wbem_wcsicmp ( wcsClass, wcsPseudoSystem [ dwIndex ] ) )
{
fResult = TRUE ;
break ;
}
}
}
return fResult ;
}
/////////////////////////////////////////////////////////////////////////////////////////////////
//
// IsClassAsociatedWithDifferentDriver
// ===================================
//
// returns false if there is no other driver referencing class
// we assume that there is driver when internally failing
//
/////////////////////////////////////////////////////////////////////////////////////////////////
BOOL CNamespaceManagement::IsClassAsociatedWithDifferentDriver ( LPCWSTR wcsClass, LPCWSTR wcsDriverToCompare )
{
BOOL fResult = TRUE ;
BOOL fFind = FALSE ;
HRESULT hr = S_OK ;
CBSTR strQueryLang(L"WQL");
LPCWSTR wcsQuery = L"\"" ;
LPCWSTR query1 = L"select * from WDMClassesOfDriver where ClassName = \"" ;
DWORD dwQuery1 = sizeof ( L"select * from WDMClassesOfDriver where ClassName = \"" ) / sizeof ( WCHAR ) ;
DWORD dw1 = wcslen ( wcsClass ) + dwQuery1 + 1 ;
LPWSTR wcsQuery1 = new WCHAR [ dw1 ] ;
wmilib::auto_buffer < WCHAR > smartwcsQuery1 ( wcsQuery1 ) ;
if ( SUCCEEDED ( hr = StringCchCopyW ( wcsQuery1, dw1, query1 ) ) )
{
if ( SUCCEEDED ( hr = StringCchCatW ( wcsQuery1, dw1, wcsClass ) ) )
{
hr = StringCchCatW ( wcsQuery1, dw1, wcsQuery ) ;
}
}
if ( SUCCEEDED ( hr ) )
{
_COM_SMARTPTR_TYPEDEF(IEnumWbemClassObject, __uuidof(IEnumWbemClassObject));
IEnumWbemClassObjectPtr pEnum;
hr = REPOSITORY_PTR->ExecQuery ( strQueryLang, CBSTR ( wcsQuery1 ), WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY, CONTEXT_PTR, &pEnum );
if ( SUCCEEDED ( hr ) )
{
DWORD uReturned = 0L ;
_COM_SMARTPTR_TYPEDEF(IWbemClassObject, __uuidof(IWbemClassObject));
IWbemClassObjectPtr pClass;
LPCWSTR query2 = L"select * from WMIBinaryMofResource where Name = \"" ;
DWORD dwQuery2 = sizeof ( L"select * from WMIBinaryMofResource where Name = \"" ) / sizeof ( WCHAR ) ;
while ( WBEM_S_NO_ERROR == hr )
{
hr = pEnum->Next ( WBEM_INFINITE, 1, &pClass, &uReturned ) ;
if ( WBEM_S_NO_ERROR == hr )
{
CVARIANT vDriver ;
hr = pClass->Get ( L"Driver", 0, &vDriver, 0, 0 );
if ( SUCCEEDED ( hr ) )
{
if ( wcsDriverToCompare )
{
if ( 0 == ( wbem_wcsicmp ( wcsDriverToCompare, vDriver.GetStr() ) ) )
{
//
// we know that this driver has a class
//
continue ;
}
}
DWORD dwDriver = 2 * ( wcslen ( vDriver.GetStr() ) + 1 ) ;
CAutoWChar wcsDriver( dwDriver );
if ( SUCCEEDED ( hr = ConvertStringToCTypeString ( wcsDriver, dwDriver, vDriver.GetStr() ) ) )
{
DWORD dw2 = wcslen ( wcsDriver ) + dwQuery2 + 1;
LPWSTR wcsQuery2 = new WCHAR [ dw2 ] ;
wmilib::auto_buffer < WCHAR > smartwcsQuery2 ( wcsQuery2 ) ;
if ( SUCCEEDED ( hr = StringCchCopyW ( wcsQuery2, dw2, query2 ) ) )
{
if ( SUCCEEDED ( hr = StringCchCatW ( wcsQuery2, dw2, wcsDriver ) ) )
{
hr = StringCchCatW ( wcsQuery2, dw2, wcsQuery ) ;
}
}
if ( SUCCEEDED ( hr ) )
{
IEnumWbemClassObjectPtr pEnum1;
hr = REPOSITORY_PTR->ExecQuery ( strQueryLang, CBSTR ( wcsQuery2 ), WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY, CONTEXT_PTR, &pEnum1 );
if ( SUCCEEDED ( hr ) )
{
DWORD uReturned1 = 0L ;
IWbemClassObjectPtr pClass1;
hr = pEnum1->Next ( WBEM_INFINITE, 1, &pClass1, &uReturned1 ) ;
if ( WBEM_S_NO_ERROR == hr )
{
//
// we are associated with some live driver for this class
//
fFind = TRUE ;
break ;
}
else
{
if ( WBEM_S_FALSE == hr )
{
//
// we get empty enumerator back (continue with other drivers)
//
hr = WBEM_S_NO_ERROR ;
}
else
{
if ( FAILED ( hr ) )
{
// get object failure
ERRORTRACE ( ( THISPROVIDER, "QUERY:\n" ) ) ;
TranslateAndLog ( wcsQuery2 ) ;
ERRORTRACE ( ( THISPROVIDER, "Failure to get class object out of enumerator with error 0x%08lx\n", hr));
}
}
}
}
else
{
// exec query failure
ERRORTRACE ( ( THISPROVIDER, "Failed to execute following QUERY:\n" ) ) ;
TranslateAndLog ( wcsQuery2 ) ;
ERRORTRACE ( ( THISPROVIDER, "Error 0x%08lx\n", hr));
}
}
else
{
// out of memory
ERRORTRACE ( ( THISPROVIDER, "String creation failed: ", hr ) ) ;
TranslateAndLog ( wcsQuery2 ) ;
ERRORTRACE ( ( THISPROVIDER, "Error 0x%08lx\n", hr ) ) ;
}
}
else
{
// convert failure
ERRORTRACE ( ( THISPROVIDER, "Convertion failure ... probably OUT OF MEMORY !\n" ) ) ;
}
}
else
{
// get property failed
ERRORTRACE ( ( THISPROVIDER, "QUERY:\n" ) ) ;
TranslateAndLog ( wcsQuery1 ) ;
ERRORTRACE ( ( THISPROVIDER, "Failure to get property value from class object with error 0x%08lx\n", hr));
}
}
else
{
if ( WBEM_S_FALSE == hr )
{
//
// we did get empty enumerator back
//
if ( FALSE == fFind )
{
//
// we didn't find live driver here
//
fResult = FALSE ;
}
}
else
{
// get object failure
ERRORTRACE ( ( THISPROVIDER, "QUERY:\n" ) ) ;
TranslateAndLog ( wcsQuery1 ) ;
ERRORTRACE ( ( THISPROVIDER, "Failure to get class object out of enumerator with error 0x%08lx\n", hr));
}
}
}
}
else
{
// exec query failure
ERRORTRACE ( ( THISPROVIDER, "Failed to execute following QUERY:\n" ) ) ;
TranslateAndLog ( wcsQuery1 ) ;
ERRORTRACE ( ( THISPROVIDER, "Error 0x%08lx\n", hr));
}
}
else
{
// out of memory
ERRORTRACE ( ( THISPROVIDER, "String creation failed: ", hr ) ) ;
TranslateAndLog ( wcsQuery1 ) ;
ERRORTRACE ( ( THISPROVIDER, "Error 0x%08lx\n", hr ) ) ;
}
return fResult ;
}
/////////////////////////////////////////////////////////////////////////////////////////////////
// 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
// ==================================================================================
if ( SUCCEEDED ( hr = InitQuery(L"select * from WMIBinaryMofResource") ) )
{
CBSTR strQryLang(L"WQL");
CBSTR cbstrQry(m_pwcsQuery);
hr = REPOSITORY_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
//================================================================================
if ( SUCCEEDED ( hr = 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
//============================================================
hr = 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 = REPOSITORY_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)))
{
//
// we need to recognize if class is not associated with
// different driver prior to its deletion
//
// (upgrade scenario where diff driver was exposing same classes)
//
BOOL fDeleteClass = ! IsClassAsociatedWithDifferentDriver ( vClass.GetStr() );
//
// we do not care if there was error in deletion
// as it usually means there was no such a class
// previously
//
hr = DeleteUnusedClassAndDriverInfo( fDeleteClass, vClass.GetStr(), vPath.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\n"));
}
}
}
}
}
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 = REPOSITORY_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;
}
}
DEBUGTRACE((THISPROVIDER,"Deleting Old Drivers\n"));
DEBUGTRACE((THISPROVIDER,"***************************************\n"));
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 = REPOSITORY_PTR->DeleteInstance(cbstrPath,0,CONTEXT_PTR,NULL);
if ( FAILED ( hr ) )
{
ERRORTRACE((THISPROVIDER,"We have been requested to delete this instance:\n"));
TranslateAndLog(vPath.GetStr());
ERRORTRACE((THISPROVIDER,"It failed with 0x%08lx\n", hr));
}
else
{
DEBUGTRACE((THISPROVIDER,"We have been requested to delete this instance:\n"));
TranslateAndLog(vPath.GetStr(), TRUE);
}
if( WBEM_NO_ERROR == hr )
{
m_pObj->DeleteMofFromRegistry((WCHAR *) vName.GetStr());
}
}
else
{
ERRORTRACE((THISPROVIDER,"Get returned value: 0x%08lx\n",hr));
}
}
}
}
SAFE_RELEASE_PTR(pEnum);
}
else
{
ERRORTRACE((THISPROVIDER,"Cannot delete driver. ExecQuery return value: 0x%08lx\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;
DEBUGTRACE((THISPROVIDER,"Deleting Old Classes for Driver\n"));
TranslateAndLog(wcsFileName, TRUE);
DEBUGTRACE((THISPROVIDER,"***************************************\n"));
if( wcsTranslatedKey.Valid() )
{
//================================================================================
// Initialize everything we need to construct the query
//================================================================================
if( fCompareDates )
{
lLowDateTime= (ULONG)vLow.GetLONG();
lHighDateTime= (ULONG)vHigh.GetLONG();
}
if ( SUCCEEDED ( hr = ConvertStringToCTypeString( wcsTranslatedKey,MAX_PATH*2,wcsFileName ) ) )
{
//================================================================================
// Now, pick up all the old classes for this driver
//================================================================================
if ( SUCCEEDED ( hr = InitQuery(L"select * from WDMClassesOfDriver where Driver = ") ) )
{
if ( SUCCEEDED ( hr = UpdateQuery(L"",wcsFileName) ) )
{
if ( SUCCEEDED ( hr = UpdateQuery(L" and (HighDateTime != ",lHighDateTime) ) )
{
if ( SUCCEEDED ( hr = UpdateQuery(L" or LowDateTime != ", lLowDateTime) ) )
{
if ( SUCCEEDED ( hr = AddToQuery(L")") ) )
{
BSTR strTmp = NULL;
strTmp = SysAllocString(m_pwcsQuery);
if(strTmp != NULL)
{
CBSTR strQryLang(L"WQL");
hr = REPOSITORY_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;
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 )
{
SAFE_RELEASE_PTR( pClass );
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 )
{
SAFE_RELEASE_PTR( pClass );
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
//==========================================================================
BOOL bProceedDeletion = FALSE ;
BOOL fDeleteOldClass = TRUE ;
if ( FALSE == fCompareDates )
{
//
// we need to recognize if class is not associated with
// different driver prior to its deletion
//
// (upgrade scenario where diff driver was exposing same classes)
//
fDeleteOldClass = ! IsClassAsociatedWithDifferentDriver ( vClass.GetStr(), wcsFileName );
bProceedDeletion = TRUE ;
}
else
{
IWbemClassObject * pTmp = NULL;
CBSTR bTmp = vClass.GetStr();
if( bTmp )
{
CAutoWChar wcsObjectPath(MAX_PATH*4);
if( wcsObjectPath.Valid() )
{
if ( SUCCEEDED ( hr = StringCchPrintfW(wcsObjectPath,MAX_PATH*4,L"WDMClassesOfDriver.ClassName=\"%s\",Driver=\"%s\",HighDateTime=%lu,LowDateTime=%lu",bTmp,wcsTranslatedKey,lHighDateTime,lLowDateTime) ) )
{
//===========================================================================
// 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
//===========================================================================
if ( WBEM_NO_ERROR == REPOSITORY_PTR->GetObject ( CBSTR ( wcsObjectPath ), 0, CONTEXT_PTR, &pTmp, NULL ) )
{
fDeleteOldClass = FALSE;
}
//===========================================================================
// Now, delete the WDM Instance of the Old Driver
//===========================================================================
SAFE_RELEASE_PTR( pTmp );
bProceedDeletion = TRUE ;
}
}
}
}
if ( bProceedDeletion )
{
//
// we do not care if there was error in deletion
// as it usually means there was no such a class
// previously
//
hr = DeleteUnusedClassAndDriverInfo( fDeleteOldClass, vClass.GetStr(), vPath.GetStr() );
}
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 = REPOSITORY_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 = REPOSITORY_PTR->PutInstance(pInst,WBEM_FLAG_CREATE_OR_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;
//===========================================================================
// 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 = ( WCHAR* ) new BYTE[m_nSize+4];
if( p )
{
memset(p,NULL,m_nSize+4);
hr = WBEM_NO_ERROR;
}
else
{
WBEM_E_OUT_OF_MEMORY;
}
return hr;
}
/////////////////////////////////////////////////////////////////////
HRESULT CNamespaceManagement::AddToQuery(WCHAR * p)
{
HRESULT hr = WBEM_E_FAILED;
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;
m_pwcsQuery = NULL;
if( SUCCEEDED( hr = AllocMemory(m_pwcsQuery)))
{
memcpy(m_pwcsQuery,pOld,nOldSize);
}
SAFE_DELETE_ARRAY(pOld);
}
else
{
// no need to re-allocate
hr = WBEM_S_FALSE;
}
if ( SUCCEEDED ( hr ) )
{
if( m_pwcsQuery )
{
if( wcslen(m_pwcsQuery) == 0 )
{
hr = StringCbCopyW(m_pwcsQuery,m_nSize,p);
}
else
{
hr = StringCbCatW(m_pwcsQuery,m_nSize,p);
}
}
else
{
// this is so bad
hr = WBEM_E_FAILED;
}
}
return hr;
}
/////////////////////////////////////////////////////////////////////
HRESULT CNamespaceManagement::InitQuery(WCHAR * p)
{
HRESULT hr = WBEM_S_NO_ERROR;
SAFE_DELETE_ARRAY(m_pwcsQuery);
m_nSize = MEMSIZETOALLOCATE;
m_fInit = TRUE;
if(SUCCEEDED(hr = AllocMemory(m_pwcsQuery)))
{
hr = AddToQuery(p);
}
return hr;
}
/////////////////////////////////////////////////////////////////////
HRESULT CNamespaceManagement::UpdateQuery( WCHAR * pQueryAddOn, WCHAR * wcsParam )
{
HRESULT hr = WBEM_E_OUT_OF_MEMORY;
CAutoWChar wcsTranslatedKey(MAX_PATH*3);
if( wcsTranslatedKey.Valid() )
{
if ( SUCCEEDED ( hr = ConvertStringToCTypeString( wcsTranslatedKey,MAX_PATH*3,wcsParam ) ) )
{
//=============================================
// The first time only we DON'T add the query
// add on string, otherwise, we do
//=============================================
if( !m_fInit )
{
hr = AddToQuery(pQueryAddOn);
}
if ( SUCCEEDED ( hr ) )
{
if ( SUCCEEDED ( hr = AddToQuery(L"\"") ) )
{
if ( SUCCEEDED ( hr = AddToQuery(wcsTranslatedKey) ) )
{
if ( SUCCEEDED ( hr = AddToQuery(L"\"") ) )
{
m_fInit = FALSE;
}
}
}
}
}
}
return hr;
}
/////////////////////////////////////////////////////////////////////
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);
}
/////////////////////////////////////////////////////////////////////
HRESULT CNamespaceManagement::UpdateQuery( WCHAR * pQueryAddOn, ULONG lLong )
{
HRESULT hr = WBEM_E_OUT_OF_MEMORY;
CAutoWChar wcsBuf(MAX_PATH);
if( wcsBuf.Valid() )
{
if ( SUCCEEDED ( hr = AddToQuery(pQueryAddOn) ) )
{
if ( SUCCEEDED ( hr = StringCchPrintfW(wcsBuf,MAX_PATH,L"%lu",lLong) ) )
{
if ( SUCCEEDED ( hr = AddToQuery(wcsBuf) ) )
{
m_fInit = FALSE;
}
}
}
}
return hr;
}
/////////////////////////////////////////////////////////////////////
HRESULT CNamespaceManagement::DeleteUnusedClassAndDriverInfo( BOOL fDeleteOldClass, WCHAR * wcsClass, WCHAR * wcsPath )
{
HRESULT hr = WBEM_NO_ERROR;
if( fDeleteOldClass )
{
if ( FALSE == IsClassPseudoSystem ( wcsClass ) )
{
hr = SERVICES_PTR->DeleteClass(CBSTR(wcsClass),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: 0x%08lx for class: \n",hr));
TranslateAndLog(wcsClass);
}
else
{
hr = WBEM_NO_ERROR;
}
}
}
else
{
DEBUGTRACE ( ( THISPROVIDER,"Tried to delete class but skipped: \n" ) );
DEBUGTRACE ( ( THISPROVIDER,"%S is PSEUDO system class \n", wcsClass ) ); ;
}
}
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(CBSTR(wcsPath),WBEM_FLAG_OWNER_UPDATE,CONTEXT_PTR,NULL);
if( WBEM_NO_ERROR != hr )
{
if( hr != WBEM_E_NOT_FOUND )
{
ERRORTRACE((THISPROVIDER,"Tried to delete instance but couldn't, return code: 0x%08lx for instance: \n ",hr));
TranslateAndLog(wcsPath);
}
}
}
return hr;
}