///////////////////////////////////////////////////////////////////// // // BINMOF.CPP // // Module: // Purpose: // // Copyright (c) 1997-2001 Microsoft Corporation, All Rights Reserved // ///////////////////////////////////////////////////////////////////// #include "wmicom.h" #include "wmimof.h" #include #include #include "wdmshell.h" #include #include #include #include #include #include //#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; }