/*++ Copyright (C) 2000-2002 Microsoft Corporation --*/ #include "precomp.h" #include #include #include #include #include #include #include "a51rep.h" #include #include #include "a51tools.h" #include "corex.h" #include #include "upgrade.h" extern DWORD g_dwSecTlsIndex; //===================================================================== // // CLocalizationUpgrade::CLocalizationUpgrade // // Description: // // Parameters: // pContol Life Control // pRepository Pointer to repository pointer //===================================================================== CLocalizationUpgrade::CLocalizationUpgrade(CLifeControl* pControl, CRepository * pRepository) : m_pControl(pControl), m_pRepository(pRepository) { } //===================================================================== // // CLocalizationUpgrade::~CLocalizationUpgrade // // Description: // // Parameters: // //===================================================================== CLocalizationUpgrade::~CLocalizationUpgrade() { } //===================================================================== // // CLocalizationUpgrade::DoUpgrade // // Description: // Control routing to bootstrap the upgrade process. If the registry key // already exists then it does nothing. // // Parameters: // //===================================================================== HRESULT CLocalizationUpgrade::DoUpgrade() { HRESULT hRes = 0; //Check to make sure we even need to do the upgrade! HKEY hKey; LONG lRes; bool bDoUpgrade = false; //Get the current database version DWORD dwVal = 0; CDbVerRead cfg; cfg.TidyUp(); cfg.ReadDbVer(dwVal); if (dwVal != 6) return WBEM_NO_ERROR; try { hRes = OldHash(L"__namespace", m_namespaceClassHash); if (FAILED(hRes)) return hRes; hRes = OldHash(L"", m_emptyClassHash); if (FAILED(hRes)) return hRes; hRes = OldHash(A51_SYSTEMCLASS_NS, m_systemNamespaceHash); if (FAILED(hRes)) return hRes; //Reset a TLS entry if necessary! Otherwise we may not find any //instances of __thisNamespace! LPVOID pOldTlsEntry = NULL; if (g_dwSecTlsIndex != -1) { pOldTlsEntry = TlsGetValue(g_dwSecTlsIndex); TlsSetValue(g_dwSecTlsIndex, 0); } //Set the Class Cache size to 0 bytes so it does not //cache anything during this process. if it did, we //would get kind of screwed up really badly! g_Glob.m_ForestCache.SetMaxMemory(0, 10000); CAutoWriteLock lock(&g_readWriteLock); if (lock.Lock()) { lRes = g_Glob.m_FileCache.BeginTransaction(); if (lRes) hRes = A51TranslateErrorCode(lRes); if (SUCCEEDED(hRes)) { m_pass = 1; DEBUGTRACE((LOG_REPDRV, "============== LOCALE UPGRADE : Enumerate Child Namespaces =============\n")); //1 Enumeration all namespaces //Deals with class enumeration, and deletion if there is a conflict, //and enumerates all the instances in the namespace checking both types //of hashes and recording differences hRes = EnumerateChildNamespaces(L"root"); //1 Don't do anything unless we have something to do! if (m_keyHash.Size() ||m_pathHash.Size()) { //1 Process namespace collisions if (SUCCEEDED(hRes)) { m_pass = 2; DEBUGTRACE((LOG_REPDRV, "============== LOCALE UPGRADE : Namespace Collision Detection =============\n")); hRes = ProcessNamespaceCollisions(); } if (SUCCEEDED(hRes)) { m_pass = 3; DEBUGTRACE((LOG_REPDRV, "============== LOCALE UPGRADE: Fixup BTree Changes =============\n")); //1 Phase 3 - fixup changed hashes //Iterate through the entire BTree and fix-up all failures hRes = FixupBTree(); } } else { ERRORTRACE((LOG_REPDRV, "============== LOCALE UPGRADE : No Changes Needed! =============\n")); } } if (SUCCEEDED(hRes)) { ERRORTRACE((LOG_REPDRV, "============== LOCALE UPGRADE: Committing Changes =============\n")); g_Glob.m_FileCache.CommitTransaction(); } else { ERRORTRACE((LOG_REPDRV, "============== LOCALE UPGRADE: Rolling back all Changes =============\n")); g_Glob.m_FileCache.AbortTransaction(); } //Regardless of the error code, the class cache is probably totally screwed //up, so we need to do dramatic stuff to it! //This will also reset the class cache to it's default sizes! g_Glob.m_ForestCache.Deinitialize(); g_Glob.m_ForestCache.Initialize(); } if (g_dwSecTlsIndex != -1) { TlsSetValue(g_dwSecTlsIndex, pOldTlsEntry); } if (SUCCEEDED(hRes)) { ERRORTRACE((LOG_REPDRV, "============== LOCALE UPGRADE: Fixup SUCCEEDED =============\n")); } else { ERRORTRACE((LOG_REPDRV, "============== LOCALE UPGRADE: Fixup FAILED =============\n")); } } catch (...) { g_Glob.m_FileCache.AbortTransaction(); ERRORTRACE((LOG_REPDRV, "============== LOCALE UPGRADE: Something threw an exception =============\n")); } CPersistentConfig pCfg; pCfg.SetPersistentCfgValue(PERSIST_CFGVAL_CORE_FSREP_VERSION, A51_REP_FS_VERSION); return hRes; } //===================================================================== // // CLocalizationUpgrade::EnumerateChildNamespaces // // Description: // Enumerates all child namespaces of the namespace passed, adds // the namespaces to the m_namespaces structure, and iterates down // into those namespaces // // Parameters: // wsRootNamespace Namespace name to enumerate. E.G. root\default // //===================================================================== HRESULT CLocalizationUpgrade::EnumerateChildNamespaces(const wchar_t * wsRootNamespace) { //We know the namespace we need to look under, we know the class key root, so we //can enumerate all the instances of that class and do a FileToInstance on them all. From //that we can add the event and the entry to the namespace list, and do the enumeration //of child namespaces on them LONG lRes = 0; HRESULT hRes = 0; CFileName wsNamespaceHash; if (wsNamespaceHash == NULL) return WBEM_E_OUT_OF_MEMORY; wchar_t *wszNewNamespaceHash = new wchar_t[MAX_HASH_LEN+1]; if (wszNewNamespaceHash == NULL) return WBEM_E_OUT_OF_MEMORY; CVectorDeleteMe vdm(wszNewNamespaceHash); hRes = NewHash(wsRootNamespace, wszNewNamespaceHash); if (FAILED(hRes)) return hRes; //Create the hashed path to the Key Root for the namespace StringCchCopyW(wsNamespaceHash, MAX_PATH, g_Glob.GetRootDir()); StringCchCatW(wsNamespaceHash, MAX_PATH, L"\\NS_"); hRes = OldHash(wsRootNamespace, wsNamespaceHash + g_Glob.GetRootDirLen()+4); if (FAILED(hRes)) return hRes; hRes = IndexExists(wsNamespaceHash); if (hRes == WBEM_E_NOT_FOUND) { //Try using NewHash instead! hRes = NewHash(wsRootNamespace, wsNamespaceHash + g_Glob.GetRootDirLen()+4); if (FAILED(hRes)) return hRes; hRes = IndexExists(wsNamespaceHash); if (hRes == WBEM_E_NOT_FOUND) return WBEM_NO_ERROR; //NOthing in this namespace! else if (FAILED(hRes)) return hRes; } else if (FAILED(hRes)) return hRes; DEBUGTRACE((LOG_REPDRV, ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n")); DEBUGTRACE((LOG_REPDRV, "Processing namespace: %S, %S\n", wsRootNamespace, wsNamespaceHash+g_Glob.GetRootDirLen()+1)); //2 Store namespace path for pass 2 of update hRes = m_namespaces.AddStrings(wsRootNamespace, wsNamespaceHash); if (FAILED(hRes)) return hRes; //2 Create a CNamespaceHandle so we can access objects in this namespace CNamespaceHandle *pNs = new CNamespaceHandle(m_pControl, m_pRepository); if (pNs == NULL) return WBEM_E_OUT_OF_MEMORY; CDeleteMe cdm(pNs); hRes = pNs->Initialize2(wsRootNamespace, wsNamespaceHash+g_Glob.GetRootDirLen()+4); if (FAILED(hRes)) return hRes; //2 Fixup all the classes in this namespace //NOTE: We need to do this BEFORE we process the hash for the namespace //because otherwise it will be stored in a different place and so //instance enumeration will fail! hRes = ProcessSystemClassesRecursively(pNs, wsNamespaceHash+g_Glob.GetRootDirLen()+4, m_emptyClassHash); if (FAILED(hRes)) return hRes; hRes = ProcessClassesRecursively(pNs, wsNamespaceHash+g_Glob.GetRootDirLen()+4, m_emptyClassHash); if (FAILED(hRes)) return hRes; hRes = EnumerateInstances(pNs, wszNewNamespaceHash); if (FAILED(hRes)) return hRes; StringCchCatW(wsNamespaceHash, MAX_PATH, L"\\" A51_KEYROOTINST_DIR_PREFIX); StringCchCatW(wsNamespaceHash, MAX_PATH, m_namespaceClassHash); StringCchCatW(wsNamespaceHash, MAX_PATH, L"\\" A51_INSTDEF_FILE_PREFIX); //2 Process Hash for this namespace bool bDifferent = false; hRes = ProcessHash(wsRootNamespace, &bDifferent); if (FAILED(hRes)) return hRes; //2 Enumerate all the child namespaces LPVOID pEnumHandle = NULL; lRes = g_Glob.m_FileCache.ObjectEnumerationBegin(wsNamespaceHash, &pEnumHandle); if (lRes == ERROR_SUCCESS) { BYTE *pBlob = NULL; DWORD dwSize = 0; while(1) { lRes = g_Glob.m_FileCache.ObjectEnumerationNext(pEnumHandle, wsNamespaceHash, &pBlob, &dwSize); if (lRes == ERROR_NO_MORE_FILES) { lRes = ERROR_SUCCESS; break; } else if (lRes) break; //Get the instance _IWmiObject* pInstance = NULL; hRes = pNs->FileToInstance(NULL, wsNamespaceHash, pBlob, dwSize, &pInstance, true); //Free the blob g_Glob.m_FileCache.ObjectEnumerationFree(pEnumHandle, pBlob); if (FAILED(hRes)) break; CReleaseMe rm2(pInstance); //Extract the string from the object VARIANT vName; VariantInit(&vName); CClearMe cm(&vName); hRes = pInstance->Get(L"Name", 0, &vName, NULL, NULL); if(FAILED(hRes)) break; if(V_VT(&vName) != VT_BSTR) { hRes = WBEM_E_INVALID_OBJECT; break; } //Create the full namespace path wchar_t *wszChildNamespacePath = new wchar_t[wcslen(wsRootNamespace)+1+wcslen(V_BSTR(&vName)) + 1]; if (wszChildNamespacePath == NULL) { hRes = WBEM_E_OUT_OF_MEMORY; break; } CVectorDeleteMe vdm(wszChildNamespacePath); StringCchCopyW(wszChildNamespacePath, MAX_PATH, wsRootNamespace); StringCchCatW(wszChildNamespacePath, MAX_PATH, L"\\"); StringCchCatW(wszChildNamespacePath, MAX_PATH, V_BSTR(&vName)); //2 Process all child namespaces in this namespace hRes = EnumerateChildNamespaces(wszChildNamespacePath); if (FAILED(hRes)) break; } g_Glob.m_FileCache.ObjectEnumerationEnd(pEnumHandle); } else { if (lRes == ERROR_FILE_NOT_FOUND) lRes = ERROR_SUCCESS; } if (lRes) hRes = A51TranslateErrorCode(lRes); return hRes; } HRESULT CLocalizationUpgrade::ProcessSystemClassesRecursively(CNamespaceHandle *pNs, const wchar_t *namespaceHash, const wchar_t *parentClassHash) { HRESULT hRes= 0; unsigned long lRes = 0; CFileName wszChildClasses; if (wszChildClasses == NULL) return WBEM_E_OUT_OF_MEMORY; wchar_t *childClassHash = new wchar_t[MAX_HASH_LEN+1]; if (childClassHash == NULL) return WBEM_E_OUT_OF_MEMORY; CVectorDeleteMe vdm(childClassHash); //Create full class reference path for parent/class relationship StringCchCopyW(wszChildClasses, wszChildClasses.Length(), g_Glob.GetRootDir()); StringCchCatW(wszChildClasses, wszChildClasses.Length(), L"\\NS_"); StringCchCatW(wszChildClasses, wszChildClasses.Length(), m_systemNamespaceHash); StringCchCatW(wszChildClasses, wszChildClasses.Length(), L"\\CR_"); StringCchCatW(wszChildClasses, wszChildClasses.Length(), parentClassHash); StringCchCatW(wszChildClasses, wszChildClasses.Length(), L"\\C_"); //Enumerate the child classes LPVOID pEnumHandle = NULL; lRes = g_Glob.m_FileCache.IndexEnumerationBegin(wszChildClasses, &pEnumHandle); if (lRes == ERROR_SUCCESS) { while(1) { lRes = g_Glob.m_FileCache.IndexEnumerationNext(pEnumHandle, wszChildClasses, true); if (lRes == ERROR_NO_MORE_FILES) { hRes = ERROR_SUCCESS; break; } else if (lRes) { hRes = A51TranslateErrorCode(lRes); break; } //extract the class hash StringCchCopyW(childClassHash, MAX_HASH_LEN+1, wszChildClasses + wcslen(wszChildClasses)-32); //Process user derived classes from this system class hRes = ProcessClassesRecursively(pNs, namespaceHash, childClassHash); if (FAILED(hRes)) break; //Process other system classes that are derived from this class hRes = ProcessSystemClassesRecursively(pNs, namespaceHash, childClassHash); if (FAILED(hRes)) break; } g_Glob.m_FileCache.IndexEnumerationEnd(pEnumHandle); } else { if (lRes == ERROR_FILE_NOT_FOUND) lRes = ERROR_SUCCESS; if (lRes) hRes = A51TranslateErrorCode(lRes); } return hRes; } //===================================================================== // // CLocalizationUpgrade::ProcessClassesRecursively // // Description: // Recursively enumerates all the classes from the one specified // and fixes it up as necessary // // Parameters: // classIndex full path to a class definition // //===================================================================== HRESULT CLocalizationUpgrade::ProcessClassesRecursively(CNamespaceHandle *pNs, const wchar_t *namespaceHash, const wchar_t *parentClassHash) { HRESULT hRes= 0; unsigned long lRes = 0; CFileName wszChildClasses; if (wszChildClasses == NULL) return WBEM_E_OUT_OF_MEMORY; wchar_t *childClassHash = new wchar_t[MAX_HASH_LEN+1]; if (childClassHash == NULL) return WBEM_E_OUT_OF_MEMORY; CVectorDeleteMe vdm(childClassHash); //Create full class reference path for parent/class relationship StringCchCopyW(wszChildClasses, wszChildClasses.Length(), g_Glob.GetRootDir()); StringCchCatW(wszChildClasses, wszChildClasses.Length(), L"\\NS_"); StringCchCatW(wszChildClasses, wszChildClasses.Length(), namespaceHash); StringCchCatW(wszChildClasses, wszChildClasses.Length(), L"\\CR_"); StringCchCatW(wszChildClasses, wszChildClasses.Length(), parentClassHash); StringCchCatW(wszChildClasses, wszChildClasses.Length(), L"\\C_"); //Enumerate the child classes LPVOID pEnumHandle = NULL; lRes = g_Glob.m_FileCache.IndexEnumerationBegin(wszChildClasses, &pEnumHandle); if (lRes == ERROR_SUCCESS) { while(1) { lRes = g_Glob.m_FileCache.IndexEnumerationNext(pEnumHandle, wszChildClasses, true); if (lRes == ERROR_NO_MORE_FILES) { hRes = ERROR_SUCCESS; break; } else if (lRes) { hRes = A51TranslateErrorCode(lRes); break; } //extract the class hash StringCchCopyW(childClassHash, MAX_HASH_LEN+1, wszChildClasses + wcslen(wszChildClasses)-32); //Process this class - this class calls back into this class to do the recursion! hRes = ProcessClass(pNs, namespaceHash, parentClassHash, childClassHash); if (FAILED(hRes)) break; } g_Glob.m_FileCache.IndexEnumerationEnd(pEnumHandle); } else { if (lRes == ERROR_FILE_NOT_FOUND) lRes = ERROR_SUCCESS; if (lRes) hRes = A51TranslateErrorCode(lRes); } return hRes; } //===================================================================== // // CLocalizationUpgrade::ProcessClass // // Description: // retrieves the class, calculates new and old class hash, and // if they are different fixes up the CD hash, child class hashes // and the parent class hash to this one // // Parameters: // namespaceHash namespace hash // parentClassHash parent class hash // childClassHash hash of class to process // //===================================================================== HRESULT CLocalizationUpgrade::ProcessClass(CNamespaceHandle *pNs, const wchar_t *namespaceHash, const wchar_t *parentClassHash, const wchar_t *childClassHash) { HRESULT hRes = 0; //Make a class definition string for this class class CFileName classDefinition; if (classDefinition == NULL) return WBEM_E_OUT_OF_MEMORY; StringCchCopyW(classDefinition, classDefinition.Length(), g_Glob.GetRootDir()); StringCchCatW(classDefinition, classDefinition.Length(), L"\\NS_"); StringCchCatW(classDefinition, classDefinition.Length(), namespaceHash); StringCchCatW(classDefinition, classDefinition.Length(), L"\\CD_"); StringCchCatW(classDefinition, classDefinition.Length(), childClassHash); _IWmiObject * pClass = NULL; __int64 nTime; bool bSystemClass; hRes = pNs->FileToClass(classDefinition, &pClass, false, &nTime, &bSystemClass); if (FAILED(hRes)) return hRes; CReleaseMe rm(pClass); //Extract the string from the object VARIANT vName; VariantInit(&vName); CClearMe cm(&vName); hRes = pClass->Get(L"__class", 0, &vName, NULL, NULL); if(FAILED(hRes)) return hRes; if(V_VT(&vName) != VT_BSTR) return WBEM_E_INVALID_OBJECT; MoveMemory(classDefinition, classDefinition+g_Glob.GetRootDirLen()+1, (wcslen(classDefinition+g_Glob.GetRootDirLen()+1)+1)*sizeof(wchar_t)); DEBUGTRACE((LOG_REPDRV, "Processing Class: %S, %S\n", V_BSTR(&vName), classDefinition)); bool bDifferent = false; hRes = ProcessHash(V_BSTR(&vName), &bDifferent); if (FAILED(hRes)) return hRes; //Lets check that the hash we just generated was not the same as the one we are using! if (bDifferent) { wchar_t *newClassHash; hRes=GetNewHash(childClassHash, &newClassHash); if (hRes == WBEM_E_NOT_FOUND) { //There are no differences! hRes=WBEM_NO_ERROR; bDifferent = false; } } if (bDifferent) { CFileName newIndexEntry; if (newIndexEntry == NULL) return WBEM_E_OUT_OF_MEMORY; //We need to fixup this entry hRes = FixupIndex(classDefinition, newIndexEntry, bDifferent); if (FAILED(hRes)) return hRes; bool bClassDeleted = false; if (bDifferent) { hRes = WriteClassIndex(pNs, classDefinition, newIndexEntry, &bClassDeleted); if (FAILED(hRes)) return hRes; } //Now we need to fix up parent/class relationships? //Finally, process the child classes if (!bClassDeleted) return ProcessClassesRecursively(pNs, namespaceHash, newIndexEntry+wcslen(newIndexEntry)-32); else return WBEM_NO_ERROR; } else return ProcessClassesRecursively(pNs, namespaceHash, childClassHash); } //===================================================================== // // CLocalizationUpgrade::EnumerateInstances // // Description: // Enumerates all instances in a specified namespace // // Parameters: // pNs - We need to retrieve an instance, so we need a namespace handle to do that // //===================================================================== HRESULT CLocalizationUpgrade::EnumerateInstances(CNamespaceHandle *pNs, const wchar_t *wszNewNamespaceHash) { unsigned long lRes = 0; HRESULT hRes = 0; CFileName wsInstancePath; if (wsInstancePath == NULL) return WBEM_E_OUT_OF_MEMORY; CFileName wsInstanceShortPath; if (wsInstanceShortPath == NULL) return WBEM_E_OUT_OF_MEMORY; StringCchCopyW(wsInstancePath, wsInstancePath.Length(), pNs->m_wszClassRootDir); StringCchCatW(wsInstancePath, wsInstancePath.Length(), L"\\" A51_KEYROOTINST_DIR_PREFIX); //Enumerate all the objects LPVOID pEnumHandle = NULL; lRes = g_Glob.m_FileCache.IndexEnumerationBegin(wsInstancePath, &pEnumHandle); if (lRes == ERROR_SUCCESS) { while(1) { lRes = g_Glob.m_FileCache.IndexEnumerationNext(pEnumHandle, wsInstanceShortPath, true); if (lRes == ERROR_NO_MORE_FILES) { lRes = ERROR_SUCCESS; break; } else if (lRes) break; //Need to strip out the .X.Y.Z and make long path version wcstok(wsInstanceShortPath, L"."); StringCchCopyW(wsInstancePath + g_Glob.GetRootDirLen()+1, wsInstancePath.Length() - g_Glob.GetRootDirLen() -1, wsInstanceShortPath); //2 check if this is an INSTANCE or a REFERENCE! //We are only interested if we are an instance. Instances are ns_..\KI..\I_..x.y.z //Reference is ns_..\KI_..\IR_..\R_..\I_..x.y.z //We can validate this by checking for the existance of the _ in the I_ entry! //for reference it would be an R from the IR_ entry! if ((wcslen(wsInstanceShortPath) > 73) && (wsInstanceShortPath[73] == L'_')) { //2 Retrieve the object blob DWORD dwLen = 0; BYTE *pBuffer = NULL; lRes = g_Glob.m_FileCache.ReadObject(wsInstancePath, &dwLen, &pBuffer); if (lRes) { hRes = A51TranslateErrorCode(lRes); break; } CTempFreeMe tfm(pBuffer, dwLen); //2 Extract class hash from blob wchar_t *wsOldClassHash = new wchar_t[MAX_HASH_LEN+1]; wchar_t *wsNewClassHash = NULL; if (wsOldClassHash == NULL) { hRes = WBEM_E_OUT_OF_MEMORY; break; } CVectorDeleteMe vdm(wsOldClassHash); StringCchCopyNW(wsOldClassHash, MAX_HASH_LEN+1, (wchar_t*)pBuffer, 32); hRes = GetNewHash(wsOldClassHash, &wsNewClassHash); if (hRes == WBEM_E_NOT_FOUND) hRes = WBEM_NO_ERROR; else if (FAILED(hRes)) break; else StringCchCopyW(wsOldClassHash, MAX_HASH_LEN+1, wsNewClassHash); //Build up the full class definition fror this class CFileName wszClassDefinition; if (wszClassDefinition == NULL) { hRes = WBEM_E_OUT_OF_MEMORY; break; } StringCchCopyW(wszClassDefinition, wszClassDefinition.Length(), g_Glob.GetRootDir()); StringCchCatW(wszClassDefinition, wszClassDefinition.Length(), L"\\"); StringCchCatNW(wszClassDefinition, wszClassDefinition.Length(), wsInstanceShortPath, 3+32+1); StringCchCatW(wszClassDefinition, wszClassDefinition.Length(), L"CD_"); StringCchCatW(wszClassDefinition, wszClassDefinition.Length(), wsOldClassHash); _IWmiObject *pClass = NULL; __int64 nTime; bool bSystemClass; hRes = pNs->FileToClass(wszClassDefinition, &pClass, false, &nTime, &bSystemClass); if (FAILED(hRes)) break; CReleaseMe rm3(pClass); //2 Get the instance _IWmiObject* pInstance = NULL; hRes = pNs->FileToInstance(pClass, wsInstancePath, pBuffer, dwLen, &pInstance, true); if (FAILED(hRes)) break; CReleaseMe rm2(pInstance); //2 Get the path VARIANT var; VariantInit(&var); hRes = pInstance->Get(L"__relpath", 0, &var, 0, 0); if (FAILED(hRes)) break; CClearMe cm2(&var); dwLen = (wcslen(V_BSTR(&var)) + 1) ; wchar_t *strKey = (WCHAR*)TempAlloc(dwLen* sizeof(WCHAR)); if(strKey == NULL) { hRes = WBEM_E_OUT_OF_MEMORY; break; } CTempFreeMe tfm3(strKey, dwLen* sizeof(WCHAR)); bool bIsClass; LPWSTR __wszClassName = NULL; hRes = pNs->ComputeKeyFromPath(V_BSTR(&var), strKey, dwLen, &__wszClassName, &bIsClass); if(FAILED(hRes)) break; DEBUGTRACE((LOG_REPDRV, "Processing Instance Hash: %S='%S', %S\n", __wszClassName, strKey, wsInstanceShortPath)); TempFree(__wszClassName); bool bDifferent = false; hRes = ProcessHash(strKey, &bDifferent); if (FAILED(hRes)) break; hRes = ProcessFullPath(wsInstancePath, wszNewNamespaceHash); if (FAILED(hRes)) break; } else { DEBUGTRACE((LOG_REPDRV, "Ignoring Instance reference: %S\n", wsInstanceShortPath)); } } g_Glob.m_FileCache.IndexEnumerationEnd(pEnumHandle); } else { if (lRes == ERROR_FILE_NOT_FOUND) lRes = ERROR_SUCCESS; } if (lRes) hRes = A51TranslateErrorCode(lRes); return hRes; } //===================================================================== // // CLocalizationUpgrade::ProcessHash // // Description: // Does the actual comparison of old and new hash of the given string. // If different it records it for later use. // // Parameters: // wszName Class name, namespace name, instance key. // //===================================================================== HRESULT CLocalizationUpgrade::ProcessHash(const wchar_t *wszName, bool *pDifferent) { //Hash using old ToUpper method //Hash using new ToUpper method //If they are not the same add to the m_keyHash structure HRESULT hRes = 0; wchar_t wszOldHash[MAX_HASH_LEN+1]; wchar_t wszNewHash[MAX_HASH_LEN+1]; hRes = OldHash(wszName, wszOldHash); if (SUCCEEDED(hRes)) hRes = NewHash(wszName, wszNewHash); if (SUCCEEDED(hRes)) { if (wcscmp(wszOldHash, wszNewHash) != 0) { DEBUGTRACE((LOG_REPDRV, "Hash difference detected for: %S, %S, %S\n", wszName, wszOldHash, wszNewHash)); //2 The hashes are different! We need to process them hRes = m_keyHash.AddStrings(wszOldHash, wszNewHash); *pDifferent = true; } } return hRes; } //===================================================================== // // CLocalizationUpgrade::ProcessFullPath // // Description: // Takes an key root instance path and checks that the full hash using // old and new methods match. If they are different it records for later // usage // // Parameters: // wszOldPath - Instance string c:\windows\...\NS_\KI_\I_hash.X.Y.Z // //===================================================================== HRESULT CLocalizationUpgrade::ProcessFullPath(CFileName &wszOldFullPath, const wchar_t *wszNewNamespaceHash) { //Hash using old ToUpper method //Hash using new ToUpper method //If they are not the same add to the m_pathHash structure HRESULT hRes = 0; bool bChanged = false; wchar_t wszOldHash[MAX_HASH_LEN+1]; wchar_t wszNewHash[MAX_HASH_LEN+1]; CFileName wsOldShortPath; CFileName wszNewFullPath; CFileName wszNewShortPath; if ((wsOldShortPath == NULL) || (wszNewFullPath == NULL) || (wszNewShortPath == NULL)) return WBEM_E_OUT_OF_MEMORY; //Need to fixup the old path with new hashes before we continue! //Fixup requires short path to work and we have full path currently! StringCchCopyW(wsOldShortPath, wsOldShortPath.Length(), wszOldFullPath+g_Glob.GetRootDirLen()+1); hRes = FixupIndex(wsOldShortPath, wszNewShortPath, bChanged); if (FAILED(hRes) || !bChanged) return hRes; //Copy the new namespace hash into the string to be sure! wmemcpy(wszNewShortPath+3, wszNewNamespaceHash, 32); //Now we need to add the FULL path to the start of each path before we hash it. Kind //of crazy, but that's the way it was done! StringCchCopyW(wszNewFullPath, wszNewFullPath.Length(), g_Glob.GetRootDir()); StringCchCatW(wszNewFullPath, wszNewFullPath.Length(), L"\\"); StringCchCatW(wszNewFullPath, wszNewFullPath.Length(), wszNewShortPath); hRes = OldHash(wszOldFullPath, wszOldHash); if (FAILED(hRes)) return hRes; hRes = NewHash(wszNewFullPath, wszNewHash); if (FAILED(hRes)) return hRes; if (wcscmp(wszOldHash, wszNewHash) != 0) { //2 The hashes are different! We need to process them DEBUGTRACE((LOG_REPDRV, "Path difference detected for: %S, %S, %S, %S\n", wszOldFullPath, wszNewShortPath, wszOldHash, wszNewHash)); hRes = m_pathHash.AddStrings(wszOldHash, wszNewHash); } return hRes; } //===================================================================== // // CLocalizationUpgrade::OldHash // // Description: // Generates a 32 character hash of the given string. It does it in // the OLD way which is case screwed up // // Parameters: // wszName Name to hash // wszHash Returns the hash of the name // //===================================================================== static wchar_t g_HexDigit[] = { L'0', L'1', L'2', L'3', L'4', L'5', L'6', L'7', L'8', L'9', L'A', L'B', L'C', L'D', L'E', L'F'}; HRESULT CLocalizationUpgrade::OldHash(const wchar_t *wszName, wchar_t *wszHash) { DWORD dwBufferSize = wcslen(wszName)*2+2; LPWSTR wszBuffer = (WCHAR*)TempAlloc(dwBufferSize); if (wszBuffer == NULL) return WBEM_E_OUT_OF_MEMORY; CTempFreeMe vdm(wszBuffer, dwBufferSize); OldStringToUpper(wszBuffer, wszName); BYTE RawHash[16]; MD5::Transform((void*)wszBuffer, wcslen(wszBuffer)*2, RawHash); WCHAR* pwc = wszHash; for(int i = 0; i < 16; i++) { *(pwc++) = g_HexDigit[RawHash[i]/16]; *(pwc++) = g_HexDigit[RawHash[i]%16]; } *pwc = 0; return WBEM_NO_ERROR; } //===================================================================== // // CLocalizationUpgrade::NewHash // // Description: // Hashes the given name using the new locale invariant specific // conversion to upper case // // Parameters: // wszName - Name to hash // wszHash - Returns hash // //===================================================================== HRESULT CLocalizationUpgrade::NewHash(const wchar_t *wszName, wchar_t *wszHash) { DWORD dwBufferSize = wcslen(wszName)*2+2; LPWSTR wszBuffer = (WCHAR*)TempAlloc(dwBufferSize); if (wszBuffer == NULL) return WBEM_E_OUT_OF_MEMORY; CTempFreeMe vdm(wszBuffer, dwBufferSize); NewStringToUpper(wszBuffer, wszName); BYTE RawHash[16]; MD5::Transform((void*)wszBuffer, wcslen(wszBuffer)*2, RawHash); WCHAR* pwc = wszHash; for(int i = 0; i < 16; i++) { *(pwc++) = g_HexDigit[RawHash[i]/16]; *(pwc++) = g_HexDigit[RawHash[i]%16]; } *pwc = 0; return WBEM_NO_ERROR; } //===================================================================== // // CLocalizationUpgrade::FixupBTree // // Description: // Method that bootstraps the fixup of the BTree by iterating through // all namespaces // // Parameters: // //===================================================================== HRESULT CLocalizationUpgrade::FixupBTree() { HRESULT hRes = NO_ERROR; //Lets iterate through the namespace list and iterate through everything in that namespace //fixing things up and fixing things as we go for (unsigned int i = 0; i != m_namespaces.Size(); i++) { hRes = FixupNamespace(m_namespaces[i]->m_wsz2); if (FAILED(hRes)) break; } return hRes; } //===================================================================== // // CLocalizationUpgrade::FixupNamespace // // Description: // Enumerates all items within the namespace, andcalls into method to // do all the work // // Parameters: // wszNamespace - in the format of a FULL namespace path... c:\windows\...\NS_ // //===================================================================== HRESULT CLocalizationUpgrade::FixupNamespace(const wchar_t *wszNamespace) { HRESULT hRes = NO_ERROR; long lRes = NO_ERROR; CFileName indexEntry; if (indexEntry == NULL) return WBEM_E_OUT_OF_MEMORY; CFileName newEntry; if (newEntry == NULL) return WBEM_E_OUT_OF_MEMORY; bool bChanged = false; LPVOID pEnumHandle = NULL; lRes = g_Glob.m_FileCache.IndexEnumerationBegin(wszNamespace, &pEnumHandle); if (lRes == ERROR_SUCCESS) { while(1) { lRes = g_Glob.m_FileCache.IndexEnumerationNext(pEnumHandle, indexEntry, true); if (lRes == ERROR_NO_MORE_FILES) { lRes = ERROR_SUCCESS; break; } else if (lRes) break; bChanged = false; hRes = FixupIndex(indexEntry, newEntry, bChanged); if (FAILED(hRes)) break; if (bChanged) { hRes = WriteIndex(indexEntry, newEntry); if (FAILED(hRes)) break; } if (IsInstanceReference(newEntry)) { hRes = FixupIndexReferenceBlob(newEntry); if (FAILED(hRes)) break; } if (IsKeyRootInstancePath(newEntry)) { hRes = FixupInstanceBlob(newEntry); if (FAILED(hRes)) break; } } g_Glob.m_FileCache.IndexEnumerationEnd(pEnumHandle); } else { if (lRes == ERROR_FILE_NOT_FOUND) lRes = ERROR_SUCCESS; } if (lRes) hRes = A51TranslateErrorCode(lRes); return hRes; } //===================================================================== // // CLocalizationUpgrade::FixupIndex // // Description: // Fixes up the entry with all the new hashes we detected and returns the new entry // // Parameters: // oldIndexEntry - Entry to fix up, in format of NS_\.... // newIndexEntry - oldIndexEntry with all hashes substituted to new entries // bChanged - Returns a flag to say if it was changed // //===================================================================== HRESULT CLocalizationUpgrade::FixupIndex(CFileName &oldIndexEntry, CFileName &newIndexEntry, bool &bChanged) { //Need to check each hash to see if it has a problem. To do this we can search for each '_' //character and check the hash after that entry. If we see a match, we need to correct it. //Any changes we detect need to be written back, then we need to delete the main entry. //If we write it back, we need to check an entry doesn't already exist because if it does we //need to discard this entry, and if we have an associated object we need to delete it, then log //an event log entry to describe what we did! CFileName scratchIndex; if (scratchIndex == NULL) return WBEM_E_OUT_OF_MEMORY; StringCchCopyW(scratchIndex, scratchIndex.Length(), oldIndexEntry); StringCchCopyW(newIndexEntry, newIndexEntry.Length(), oldIndexEntry); wchar_t *wszSection = wcstok(scratchIndex, L"_");; wchar_t *wszHash = wcstok(NULL, L"\\."); wchar_t *pNewHash = NULL; bool bInstanceReferenceDetected = false; bool bUsePathHash = false; HRESULT hRes = 0; while (wszHash != NULL) { if (!bInstanceReferenceDetected) { if (wcsncmp(wszSection, A51_INSTREF_DIR_PREFIX, 2) == 0) { bInstanceReferenceDetected = true; } } else if (bInstanceReferenceDetected && (wszSection != NULL)) { if (wcsncmp(wszSection, A51_REF_FILE_PREFIX, 1) == 0) { bUsePathHash = true; } } //Now the wszCursor points to just the hash, so we can check the hash out! if (bUsePathHash) { hRes = GetNewPath(wszHash, &pNewHash); bUsePathHash = false; } else { hRes = GetNewHash(wszHash, &pNewHash); } if (hRes == WBEM_NO_ERROR) { if ((m_pass != 3) && (wcsncmp(wszSection, L"NS_", 3) == 0)) { //Do nothing! } else { //We have a difference bChanged = true; wmemcpy(((wchar_t*)newIndexEntry)+(wszHash-((wchar_t*)scratchIndex)), pNewHash, MAX_HASH_LEN); } } else if (hRes == WBEM_E_NOT_FOUND) hRes = WBEM_NO_ERROR; //Search for next extry wszSection = wcstok(NULL, L"_"); if (wszSection) wszHash = wcstok(NULL, L"\\."); else wszHash = NULL; } if (bChanged) { DEBUGTRACE((LOG_REPDRV, "Fixed up index: %S, %S\n", (const wchar_t *)oldIndexEntry, (const wchar_t *)newIndexEntry)); } return hRes; } //===================================================================== // // CLocalizationUpgrade::GetNewHash // // Description: // Given an old hash, returns a new hash if one exists, otherwise WBEM_E_NOT_FOUND // // Parameters: // wszOldHash - Old hash string to search for - 32 character string // pNewHash - pointer to a 32-character string of new entry if one exists, NULL otherwise // // Return Code // WBEM_E_NOT_FOUND if a HASH is not found // //===================================================================== HRESULT CLocalizationUpgrade::GetNewHash(const wchar_t *wszOldHash, wchar_t **pNewHash) { return m_keyHash.FindStrings(wszOldHash, pNewHash); } //===================================================================== // // CLocalizationUpgrade::GetNewPath // // Description: // Given an old hash, returns a new hash if one exists, otherwise WBEM_E_NOT_FOUND // // Parameters: // wszOldHash - Old hash string to search for - 32 character string // pNewHash - pointer to a 32-character string of new entry if one exists, NULL otherwise // // Return Code // WBEM_E_NOT_FOUND if a HASH is not found // //===================================================================== HRESULT CLocalizationUpgrade::GetNewPath(const wchar_t *wszOldHash, wchar_t **pNewHash) { return m_pathHash.FindStrings(wszOldHash, pNewHash); } //===================================================================== // // CLocalizationUpgrade::WriteIndex // // Description: // Checks if the new index exists. If not writes the new entry and deletes the old one. If the link points to an // object then it deletes that, unless this is the instance class link object link. // If there is a conflict calls into the method to deal with that. // // Parameters: // wszOldIndex - old path of format NS_\... // wszNewIndex - new path of format NS_\... // //===================================================================== HRESULT CLocalizationUpgrade::WriteIndex(CFileName &wszOldIndex, const wchar_t *wszNewIndex) { //We need to determine if we have a collision before we write the index. Therefore we //need to strip off the X.Y.Z entry if it exists and retrieve it. If it exists then we have //to delete our index and delete the associated object CFileName wszScratchIndex; if (wszScratchIndex == NULL) return WBEM_E_OUT_OF_MEMORY; StringCchCopyW(wszScratchIndex, wszScratchIndex.Length(), wszNewIndex); wchar_t *wszObjectLocation = NULL; if (wcstok(wszScratchIndex, L".") != NULL) wszObjectLocation = wcstok(NULL, L""); CFileName wszFullPath; if (wszFullPath == NULL) return WBEM_E_OUT_OF_MEMORY; StringCchCopyW(wszFullPath, wszFullPath.Length(), g_Glob.GetRootDir()); StringCchCatW(wszFullPath, wszFullPath.Length(), L"\\"); StringCchCatW(wszFullPath, wszFullPath.Length(), wszScratchIndex); HRESULT hRes = IndexExists(wszFullPath); if (hRes == WBEM_NO_ERROR) { //2 We have a conflict, therefore we need to delete the OLD entry! long lRes = 0; DEBUGTRACE((LOG_REPDRV, "Index Collision detected: %S\n", (const wchar_t *)wszOldIndex)); hRes = FixupIndexConflict(wszOldIndex); } else if (hRes == WBEM_E_NOT_FOUND) { hRes = WBEM_NO_ERROR; //2 Write the new index if (wszObjectLocation) { //Put the .X.Y.Z on the end! StringCchCatW(wszFullPath, wszFullPath.Length(), L"."); StringCchCatW(wszFullPath, wszFullPath.Length(), wszObjectLocation); } long lRes = g_Glob.m_FileCache.WriteLink(wszFullPath); if(lRes != ERROR_SUCCESS) hRes = A51TranslateErrorCode(lRes); else { //2 Delete the old link //strip off .X.Y.Z off old entry StringCchCopyW(wszScratchIndex, wszScratchIndex.Length(), wszOldIndex); wcstok(wszScratchIndex, L"."); //Build path StringCchCopyW(wszFullPath, wszFullPath.Length(), g_Glob.GetRootDir()); StringCchCatW(wszFullPath, wszFullPath.Length(), L"\\"); StringCchCatW(wszFullPath, wszFullPath.Length(), wszScratchIndex); //Do delete lRes = g_Glob.m_FileCache.DeleteLink(wszFullPath); if(lRes != ERROR_SUCCESS) hRes = A51TranslateErrorCode(lRes); } } return hRes; } //===================================================================== // // CLocalizationUpgrade::WriteClassIndex // // Description: // Checks if the new index exists. If not writes the new entry and deletes the old one. If the link points to an // object then it deletes that, unless this is the instance class link object link. // If there is a conflict calls into the method to deal with that. // // Parameters: // wszOldIndex - old path of format NS_\... // wszNewIndex - new path of format NS_\... // //===================================================================== HRESULT CLocalizationUpgrade::WriteClassIndex(CNamespaceHandle *pNs, CFileName &wszOldIndex, const wchar_t *wszNewIndex, bool *pClassDeleted) { //We need to re-read the old index because we don't have the .X.Y.X on the end. HRESULT hRes = g_Glob.m_FileCache.ReadNextIndex(wszOldIndex, wszOldIndex); if (FAILED(hRes)) return hRes; //Save off and remove the .X.Y.Z wchar_t *wszObjectLocation = NULL; if (wcstok(wszOldIndex, L".") != NULL) wszObjectLocation = wcstok(NULL, L""); //We need to determine if we have a collision before we write the index. //If it exists then we have //to delete our index and delete the associated object CFileName wszFullPath; if (wszFullPath == NULL) return WBEM_E_OUT_OF_MEMORY; StringCchCopyW(wszFullPath, wszFullPath.Length(), g_Glob.GetRootDir()); StringCchCatW(wszFullPath, wszFullPath.Length(), L"\\"); StringCchCatW(wszFullPath, wszFullPath.Length(), wszNewIndex); hRes = IndexExists(wszFullPath); if (hRes == WBEM_NO_ERROR) { //2 We have a conflict, therefore we need to delete the old class! DEBUGTRACE((LOG_REPDRV, "Class Index Collision detected: %S\n", (const wchar_t *)wszOldIndex)); *pClassDeleted = true; hRes = DeleteClass(pNs, wszOldIndex); } else if (hRes == WBEM_E_NOT_FOUND) { hRes = WBEM_NO_ERROR; //2 Write the new index if (wszObjectLocation) { //Put the .X.Y.Z on the end! StringCchCatW(wszFullPath, wszFullPath.Length(), L"."); StringCchCatW(wszFullPath, wszFullPath.Length(), wszObjectLocation); } long lRes = g_Glob.m_FileCache.WriteLink(wszFullPath); if(lRes != ERROR_SUCCESS) hRes = A51TranslateErrorCode(lRes); else { //2 Delete the old link //Build path StringCchCopyW(wszFullPath, wszFullPath.Length(), g_Glob.GetRootDir()); StringCchCatW(wszFullPath, wszFullPath.Length(), L"\\"); StringCchCatW(wszFullPath, wszFullPath.Length(), wszOldIndex); //Do delete lRes = g_Glob.m_FileCache.DeleteLink(wszFullPath); if(lRes != ERROR_SUCCESS) hRes = A51TranslateErrorCode(lRes); } } return hRes; } //===================================================================== // // CLocalizationUpgrade::IndexExists // // Description: // Checks to see if a specific index exists. Returns WBEM_E_NOT_FOUND if not, or WBEM_NO_ERROR if it // does. // // Parameters: // wszIndex - full path of index to find - c:\windows\...\ns_<>\.... // // Returns: // WBEM_E_NOT_FOUND if index does not exist // WBEM_NO_ERROR if it exists. // //===================================================================== HRESULT CLocalizationUpgrade::IndexExists(const wchar_t *wszIndex) { HRESULT hRes = NO_ERROR; long lRes = NO_ERROR; CFileName indexEntry; if (indexEntry == NULL) return WBEM_E_OUT_OF_MEMORY; LPVOID pEnumHandle = NULL; lRes = g_Glob.m_FileCache.IndexEnumerationBegin(wszIndex, &pEnumHandle); if (lRes == ERROR_SUCCESS) { lRes = g_Glob.m_FileCache.IndexEnumerationNext(pEnumHandle, indexEntry, true); g_Glob.m_FileCache.IndexEnumerationEnd(pEnumHandle); } if (lRes) hRes = A51TranslateErrorCode(lRes); //make sure index we retrieved was from this index if (SUCCEEDED(hRes)) if (wcsncmp(wszIndex+g_Glob.GetRootDirLen()+1, indexEntry, wcslen(wszIndex+g_Glob.GetRootDirLen()+1)) != 0) hRes = WBEM_E_NOT_FOUND; return hRes; } //===================================================================== // // CLocalizationUpgrade::ProcessNamespaceCollisions // // Description: // Searches through the namespace list for collisions. If one exists then we delete the namespace // recursively // // Parameters: // //===================================================================== HRESULT CLocalizationUpgrade::ProcessNamespaceCollisions() { HRESULT hRes = NO_ERROR; wchar_t thisNamespace[MAX_HASH_LEN+1]; wchar_t thatNamespace[MAX_HASH_LEN+1]; bool bDeletedSomething = false; //Lets iterate through the namespace list and calculate the hash. //Then we will itterate through the rest of the namespace list and check the //hash with that one. If we have a collision, we need to delete it! do { bDeletedSomething = false; for (int i = 0; i != m_namespaces.Size(); i++) { //Hash this entry hRes = NewHash(m_namespaces[i]->m_wsz1, thisNamespace); if (FAILED(hRes)) break; for (int j = (i+1); j < m_namespaces.Size(); j++) { //Hash this entry hRes = NewHash(m_namespaces[j]->m_wsz1, thatNamespace); if (FAILED(hRes)) break; //If they are the same we need to delete this one if (wcscmp(thisNamespace, thatNamespace) == 0) { //OK, so we have a collision! Lets deal with it! hRes = DeleteNamespaceRecursive(m_namespaces[i]->m_wsz1); if (FAILED(hRes)) break; //We need to start again with the iteration as we may have deleted several entries //from the array at this point bDeletedSomething = true; break; } } if (FAILED(hRes) || bDeletedSomething) break; } } while (SUCCEEDED(hRes) && bDeletedSomething); return hRes; } //===================================================================== // // CLocalizationUpgrade::DeleteNamespaceRecursive // // Description: // Searches through the namespace list for any which start with the one we passed in. Any matches are // deleted // // Parameters: // wszNamespace - namespace name in the format like root\default // //===================================================================== HRESULT CLocalizationUpgrade::DeleteNamespaceRecursive(const wchar_t *wszNamespace) { LONG lRes = 0; HRESULT hRes = NO_ERROR; wchar_t *wszNamespaceHash = new wchar_t[MAX_HASH_LEN+1]; if (wszNamespaceHash == NULL) return WBEM_E_OUT_OF_MEMORY; hRes = OldHash(wszNamespace, wszNamespaceHash); if (FAILED(hRes)) return hRes; CFileName wszNamespacePath; if (wszNamespacePath == NULL) return WBEM_E_OUT_OF_MEMORY; //Create the hashed path to the Key Root for the namespace StringCchCopyW(wszNamespacePath, MAX_PATH, g_Glob.GetRootDir()); StringCchCatW(wszNamespacePath, MAX_PATH, L"\\NS_"); StringCchCatW(wszNamespacePath, MAX_PATH, wszNamespaceHash); DEBUGTRACE((LOG_REPDRV, "Deleting namespace (recursive): %S, %S\n", wszNamespace, wszNamespacePath+g_Glob.GetRootDirLen()+1)); //2 Create a CNamespaceHandle so we can access objects in this namespace CNamespaceHandle *pNs = new CNamespaceHandle(m_pControl, m_pRepository); if (pNs == NULL) return WBEM_E_OUT_OF_MEMORY; CDeleteMe cdm(pNs); hRes = pNs->Initialize2(wszNamespace, wszNamespaceHash); if (FAILED(hRes)) return hRes; StringCchCatW(wszNamespacePath, MAX_PATH, L"\\" A51_KEYROOTINST_DIR_PREFIX); StringCchCatW(wszNamespacePath, MAX_PATH, m_namespaceClassHash); StringCchCatW(wszNamespacePath, MAX_PATH, L"\\" A51_INSTDEF_FILE_PREFIX); //2 Enumerate all the child namespaces LPVOID pEnumHandle = NULL; lRes = g_Glob.m_FileCache.ObjectEnumerationBegin(wszNamespacePath, &pEnumHandle); if (lRes == ERROR_SUCCESS) { BYTE *pBlob = NULL; DWORD dwSize = 0; while(1) { lRes = g_Glob.m_FileCache.ObjectEnumerationNext(pEnumHandle, wszNamespacePath, &pBlob, &dwSize); if (lRes == ERROR_NO_MORE_FILES) { lRes = ERROR_SUCCESS; break; } else if (lRes) break; //Get the instance _IWmiObject* pInstance = NULL; hRes = pNs->FileToInstance(NULL, wszNamespacePath, pBlob, dwSize, &pInstance, true); //Free the blob g_Glob.m_FileCache.ObjectEnumerationFree(pEnumHandle, pBlob); if (FAILED(hRes)) break; CReleaseMe rm2(pInstance); //Extract the string from the object VARIANT vName; VariantInit(&vName); CClearMe cm(&vName); hRes = pInstance->Get(L"Name", 0, &vName, NULL, NULL); if(FAILED(hRes)) break; if(V_VT(&vName) != VT_BSTR) { hRes = WBEM_E_INVALID_OBJECT; break; } //Create the full namespace path wchar_t *wszChildNamespacePath = new wchar_t[wcslen(wszNamespace)+1+wcslen(V_BSTR(&vName)) + 1]; if (wszChildNamespacePath == NULL) { hRes = WBEM_E_OUT_OF_MEMORY; break; } CVectorDeleteMe vdm(wszChildNamespacePath); StringCchCopyW(wszChildNamespacePath, MAX_PATH, wszNamespace); StringCchCatW(wszChildNamespacePath, MAX_PATH, L"\\"); StringCchCatW(wszChildNamespacePath, MAX_PATH, V_BSTR(&vName)); //2 Process all child namespaces in this namespace hRes = DeleteNamespaceRecursive(wszChildNamespacePath); if (FAILED(hRes)) break; } g_Glob.m_FileCache.ObjectEnumerationEnd(pEnumHandle); } else { if (lRes == ERROR_FILE_NOT_FOUND) lRes = ERROR_SUCCESS; } if (lRes) hRes = A51TranslateErrorCode(lRes); if (SUCCEEDED(hRes)) { StringCchCopyW(wszNamespacePath, MAX_PATH, g_Glob.GetRootDir()); StringCchCatW(wszNamespacePath, MAX_PATH, L"\\NS_"); StringCchCatW(wszNamespacePath, MAX_PATH, wszNamespaceHash); hRes = DeleteNamespace(wszNamespace, wszNamespacePath); } //2 Remote namespace path if (SUCCEEDED(hRes)) { hRes = m_namespaces.RemoveString(wszNamespace); //Small chance that we get NOT_FOUND if we have not done full enumeration yet! if (hRes == WBEM_E_NOT_FOUND) hRes = WBEM_NO_ERROR; } return hRes; } //===================================================================== // // CLocalizationUpgrade::DeleteNamespace // // Description: // Deletes the specified namespace using the DeleteNode, then goes into the parent namespace and deletes // the instance from that namespace // // Parameters: // wszNamespaceName - namespace name in format root\default // wszNamespaceHash - Full namespace hash in format c:\windows\...\NS_ // //===================================================================== HRESULT CLocalizationUpgrade::DeleteNamespace(const wchar_t *wszNamespaceName,const wchar_t *wszNamespaceHash) { HRESULT hRes = NO_ERROR; LONG lRes = NO_ERROR; DEBUGTRACE((LOG_REPDRV, "Deleting namespace: %S, %S\n", wszNamespaceName, wszNamespaceHash+g_Glob.GetRootDirLen()+1)); //2 Delete the actual namespace contents lRes = g_Glob.m_FileCache.DeleteNode(wszNamespaceHash); if (lRes != 0) return A51TranslateErrorCode(lRes); //2 Calculate parent namespace name wchar_t *wszParentNamespaceName = new wchar_t[wcslen(wszNamespaceName)+1]; wchar_t *wszThisNamespaceName = NULL; if (wszParentNamespaceName == NULL) return WBEM_E_OUT_OF_MEMORY; StringCchCopyW(wszParentNamespaceName, wcslen(wszNamespaceName)+1, wszNamespaceName); for (int i = wcslen(wszParentNamespaceName) - 1; i != 0; i--) { if (wszParentNamespaceName[i] == L'\\') { wszParentNamespaceName[i] = L'\0'; wszThisNamespaceName = wszParentNamespaceName+i+1; break; } } //2 Calculate parent namespace hash wchar_t wszParentNamespaceHash[MAX_HASH_LEN+1]; hRes = OldHash(wszParentNamespaceName, wszParentNamespaceHash); if (FAILED(hRes)) return hRes; //2Calculate this namespaces hash wchar_t wszThisNamespaceHash[MAX_HASH_LEN+1]; hRes = OldHash(wszThisNamespaceName, wszThisNamespaceHash); if (FAILED(hRes)) return hRes; //2 Calculate __namespace class hash wchar_t wszNamespaceClassHash[MAX_HASH_LEN+1]; hRes = OldHash(L"__namespace", wszNamespaceClassHash); if (FAILED(hRes)) return hRes; CFileName wszKI; CFileName wszCI; if ((wszKI == NULL) || (wszCI == NULL)) return WBEM_E_OUT_OF_MEMORY; //2 Build KI instance path StringCchCopyW(wszKI,wszKI.Length(), g_Glob.GetRootDir()); StringCchCatW(wszKI, wszKI.Length(), L"\\NS_"); StringCchCatW(wszKI, wszKI.Length(), wszParentNamespaceHash); StringCchCopyW(wszCI, wszCI.Length(), wszKI); StringCchCatW(wszKI, wszKI.Length(), L"\\KI_"); StringCchCatW(wszKI, wszKI.Length(), wszNamespaceClassHash); StringCchCatW(wszKI, wszKI.Length(), L"\\I_"); StringCchCatW(wszKI, wszKI.Length(), wszThisNamespaceHash); //2 Retrieve instance blob so we can get the class hash for this instance wchar_t wszClassHash[MAX_HASH_LEN+1]; BYTE *pBuffer = NULL; DWORD dwLen = 0; lRes = g_Glob.m_FileCache.ReadObject(wszKI, &dwLen, &pBuffer, false); if (lRes) { //If this object does not exist, then we have probably already deleted the parent namespace! if (lRes == ERROR_FILE_NOT_FOUND) lRes = 0; return A51TranslateErrorCode(lRes); } StringCchCopyNW(wszClassHash, MAX_HASH_LEN+1, (wchar_t*)pBuffer, MAX_HASH_LEN); TempFree(pBuffer, dwLen); //2 Build the CI instance path StringCchCatW(wszCI, wszCI.Length(), L"\\CI_"); StringCchCatW(wszCI, wszCI.Length(), wszClassHash); StringCchCatW(wszCI, wszCI.Length(), L"\\IL_"); StringCchCatW(wszCI, wszCI.Length(), wszThisNamespaceHash); //2 Delete the KI link and object lRes = g_Glob.m_FileCache.DeleteObject(wszKI); if (lRes) return A51TranslateErrorCode(lRes); //2Delete the CI link only lRes = g_Glob.m_FileCache.DeleteLink(wszCI); if (lRes) return A51TranslateErrorCode(lRes); //OK, now, in theory, we should really, if we were really good citizens, delete any references that could be in this object! //However nothing too bad will happen if we don't, so we won't! return hRes; } //===================================================================== // // CLocalizationUpgrade::FixupIndexConflict // // Description: // Method is called if the old and new index exists. If the link is for a class definition, we have a lot more // work to do, so call into the handling method. Otherwise we just delete the old index, and object // if it exists. If it is a KI_ index then we do not delete the object because the CI index entry will // delete it instead // // Parameters: // wszOldIndex -- Index to update in format NS_\KI_<>\I_<>.X.Y.Z. It must have the // X.Y.Z entry if one exists // //===================================================================== HRESULT CLocalizationUpgrade::FixupIndexConflict(CFileName &wszOldIndex) { //If it is a class definition, we have a lot of work to do as we need to delete the class, all sub-classes, and all instances. //If the class is derived from __namespace then we need to delete the namespace recursively as well if (IsClassDefinitionPath(wszOldIndex)) { DEBUGTRACE((LOG_REPDRV, "TRYING TO FIX UP A CLASS IN THE WRONG PLACE\n")); _ASSERT(1, L"TRYING TO FIX UP A CLASS IN THE WRONG PLACE"); return WBEM_E_FAILED; } else { LONG lRes = 0; //This is the simple case, we just have to delete the old link or object CFileName wszFullPath; if (wszFullPath == NULL) return WBEM_E_OUT_OF_MEMORY; StringCchCopyW(wszFullPath, wszFullPath.Length(), g_Glob.GetRootDir()); StringCchCatW(wszFullPath, wszFullPath.Length(), L"\\"); StringCchCatW(wszFullPath, wszFullPath.Length(), wszOldIndex); //Strip off the .X.Y.Z entry if it exists wchar_t *wszObjectLocation = wcstok(wszFullPath+g_Glob.GetRootDirLen()+1, L"."); if (wszObjectLocation) wszObjectLocation = wcstok(NULL, L""); if (wszObjectLocation && !IsKeyRootInstancePath(wszOldIndex)) lRes = g_Glob.m_FileCache.DeleteObject(wszFullPath); else lRes = g_Glob.m_FileCache.DeleteLink(wszFullPath); return A51TranslateErrorCode(lRes); } } //===================================================================== // // CLocalizationUpgrade::IsClassDefinitionPath // // Description: // Checks the link to see if this is a class definition or not // // Parameters: // wszPath - link in the format NS_<>\CD_<>, or something else // // Returns: // true - link is a class definition // false - is not one // //===================================================================== bool CLocalizationUpgrade::IsClassDefinitionPath(const wchar_t *wszPath) { WCHAR* pDot = wcschr(wszPath, L'\\'); if(pDot == NULL) return false; pDot++; if ((*pDot == L'C') && (*(pDot+1) == L'D')&& (*(pDot+2) == L'_')) return true; else return false; } //===================================================================== // // CLocalizationUpgrade::IsKeyRootInstancePath // // Description: // Returns if this is a key root instance entry // // Parameters: // wszPath - index in format NS_<>\KI_<>\I_, or somthing like that // // Returns: // true - if this is a KI_<>\I_<> entry // false - otherwise // //===================================================================== bool CLocalizationUpgrade::IsKeyRootInstancePath(const wchar_t *wszPath) { WCHAR* pDot = wcschr(wszPath, L'\\'); if(pDot == NULL) return false; pDot++; pDot = wcschr(pDot, L'\\'); if(pDot == NULL) return false; pDot++; if ((*pDot == L'I') && (*(pDot+1) == L'_')) return true; else return false; } //===================================================================== // // CLocalizationUpgrade::IsInstanceReference // // Description: // Returns if this is a instance reference entry // // Parameters: // wszPath - index in format NS_<>\KI_<>\IR_<>\R, or somthing like that // // Returns: // true - if this is a NS_<>\KI_<>\IR_<>\R entry // false - otherwise // //===================================================================== bool CLocalizationUpgrade::IsInstanceReference(const wchar_t *wszPath) { WCHAR* pDot = wcschr(wszPath, L'\\'); if(pDot == NULL) return false; pDot++; pDot = wcschr(pDot, L'\\'); if(pDot == NULL) return false; pDot++; pDot = wcschr(pDot, L'\\'); if(pDot == NULL) return false; pDot++; if ((*pDot == L'R') && (*(pDot+1) == L'_')) return true; else return false; } //===================================================================== // // CLocalizationUpgrade::DeleteClass // // Description: // Recursively deletes the class definition, sub-classes and instances. If the instance is // a namespace then we need to delete that also // // Parameters: // wszClassDefinitionPath - short path of class definition (ns_...\CD_....X.Y.Z. XYZ is optional! We kill it! // //===================================================================== HRESULT CLocalizationUpgrade::DeleteClass(CNamespaceHandle *pNs, CFileName &wszClassDefinitionPath) { HRESULT hRes =0; LONG lRes = 0; DEBUGTRACE((LOG_REPDRV, "Deleting Class: %S\n", wszClassDefinitionPath)); CFileName wszKeyRootClass; if (wszKeyRootClass == NULL) return WBEM_E_OUT_OF_MEMORY; CFileName wszFullPath; if (wszFullPath == NULL) hRes = WBEM_E_OUT_OF_MEMORY; wchar_t *wszParentClassHash = new wchar_t[MAX_HASH_LEN+1]; if (wszParentClassHash == NULL) return WBEM_E_OUT_OF_MEMORY; //Kill the .X.Y.Z on the end of the definition, in case it was passed in that way wcstok((wchar_t*)wszClassDefinitionPath,L"."); StringCchCopyW(wszFullPath, wszFullPath.Length(), g_Glob.GetRootDir()); StringCchCatW(wszFullPath, wszFullPath.Length(), L"\\"); StringCchCatW(wszFullPath, wszFullPath.Length(), wszClassDefinitionPath); hRes = DeleteChildClasses(pNs, wszClassDefinitionPath); if (SUCCEEDED(hRes)) hRes = RetrieveKeyRootClass(wszClassDefinitionPath, wszKeyRootClass); if (SUCCEEDED(hRes)) { hRes = RetrieveParentClassHash(wszFullPath, wszParentClassHash); if (hRes == WBEM_S_NO_MORE_DATA) hRes = 0; } if (SUCCEEDED(hRes) && wcslen(wszKeyRootClass) > 0) hRes = DeleteInstances(pNs, wszClassDefinitionPath, wszKeyRootClass); if (SUCCEEDED(hRes)) { //Need to build the full path lRes = g_Glob.m_FileCache.DeleteObject(wszFullPath); hRes = A51TranslateErrorCode(lRes); } if (SUCCEEDED(hRes)) hRes = DeleteClassRelationships(wszFullPath, wszParentClassHash); return hRes; } //===================================================================== // // CLocalizationUpgrade::DeleteChildClasses // // Description: // Enumerates child classes from a given parent class definition, and calls DeleteClass on each // // Parameters: // wszParentClassDefinition - NS_<>\CD_<> of parent class // //===================================================================== HRESULT CLocalizationUpgrade::DeleteChildClasses(CNamespaceHandle *pNs, const wchar_t *wszParentClassDefinition) { HRESULT hRes= 0; unsigned long lRes = 0; //Build up a string for this classes c:\...\NS_...\CR_...\C_ enumeration CFileName wszChildClasses; if (wszChildClasses == NULL) return WBEM_E_OUT_OF_MEMORY; CFileName wszClassDefinition; if (wszClassDefinition == NULL) return WBEM_E_OUT_OF_MEMORY; StringCchCopyW(wszClassDefinition, wszClassDefinition.Length(), wszParentClassDefinition); //Create full class definition path StringCchCopyW(wszChildClasses, wszChildClasses.Length(), g_Glob.GetRootDir()); StringCchCatW(wszChildClasses, wszChildClasses.Length(), L"\\"); StringCchCatW(wszChildClasses, wszChildClasses.Length(), wszParentClassDefinition); //change the CD_ into CR_ wszChildClasses[g_Glob.GetRootDirLen()+1+3+32+2] = L'R'; //Add the \C_ on the end StringCchCatW(wszChildClasses, wszChildClasses.Length(), L"\\C_"); //Enumerate the child classes LPVOID pEnumHandle = NULL; lRes = g_Glob.m_FileCache.IndexEnumerationBegin(wszChildClasses, &pEnumHandle); if (lRes == ERROR_SUCCESS) { while(1) { lRes = g_Glob.m_FileCache.IndexEnumerationNext(pEnumHandle, wszChildClasses, true); if (lRes == ERROR_NO_MORE_FILES) { hRes = ERROR_SUCCESS; break; } else if (lRes) { hRes = A51TranslateErrorCode(lRes); break; } //Build a NS_...\CD_... from the NS_...\CR_...\C_... path, using last hash StringCchCopyW(wszClassDefinition+wcslen(wszClassDefinition) - 32, wszClassDefinition.Length() - wcslen(wszClassDefinition) + 32, wszChildClasses + wcslen(wszChildClasses)-32); //Delete all child classes hRes = DeleteClass(pNs, wszClassDefinition); if (FAILED(hRes)) break; } g_Glob.m_FileCache.IndexEnumerationEnd(pEnumHandle); } else { if (lRes == ERROR_FILE_NOT_FOUND) lRes = ERROR_SUCCESS; if (lRes) hRes = A51TranslateErrorCode(lRes); } return hRes; } //===================================================================== // // CLocalizationUpgrade::DeleteInstances // // Description: // Enumerates all instances for a specified class definition and calls DeleteInstance // // Parameters: // wszClassDefinition - NS_<>\CD_<> of class whose instances are to be deleted // wszKeyRootClass - hash of key root class in 32-character format // //===================================================================== HRESULT CLocalizationUpgrade::DeleteInstances(CNamespaceHandle *pNs, const wchar_t *wszClassDefinition, CFileName &wszKeyRootClass) { LONG lRes = 0; HRESULT hRes = 0; //Need to enumerate all NS_\CI_\IL_... //for each, we need to deltete the instance CFileName wszClassInstance; if (wszClassInstance == NULL) return WBEM_E_OUT_OF_MEMORY; StringCchCopyW(wszClassInstance, wszClassInstance.Length(), g_Glob.GetRootDir()); StringCchCatW(wszClassInstance, wszClassInstance.Length(), L"\\"); StringCchCatW(wszClassInstance, wszClassInstance.Length(), wszClassDefinition); wszClassInstance[g_Glob.GetRootDirLen() + 1+3+32+1+1] = L'I'; StringCchCatW(wszClassInstance, wszClassInstance.Length(), L"\\IL_"); //Enumerate the instances LPVOID pEnumHandle = NULL; lRes = g_Glob.m_FileCache.IndexEnumerationBegin(wszClassInstance, &pEnumHandle); if (lRes == ERROR_SUCCESS) { while(1) { lRes = g_Glob.m_FileCache.IndexEnumerationNext(pEnumHandle, wszClassInstance, true); if (lRes == ERROR_NO_MORE_FILES) { hRes = ERROR_SUCCESS; break; } else if (lRes) { hRes = A51TranslateErrorCode(lRes); break; } hRes = DeleteInstance(pNs, wszClassInstance, wszKeyRootClass); if (FAILED(hRes)) break; } g_Glob.m_FileCache.IndexEnumerationEnd(pEnumHandle); } else { if (lRes == ERROR_FILE_NOT_FOUND) lRes = ERROR_SUCCESS; if (lRes) hRes = A51TranslateErrorCode(lRes); } return hRes; } //===================================================================== // // CLocalizationUpgrade::DeleteInstance // // Description: // Deletes the instance links for a given instance // // Parameters: // wszClassInstanceLink - NS_<>\CI_<>\IL_<> format of instance to delete // wszKeyRoot - Hash of key root class for this instance // //===================================================================== HRESULT CLocalizationUpgrade::DeleteInstance(CNamespaceHandle *pNs, const wchar_t *wszClassInstanceLink, CFileName &wszKeyRoot) { HRESULT hRes = 0; LONG lRes = 0; //Remove .X.Y.Z from end of string if it exists wcstok((wchar_t *)wszClassInstanceLink, L"."); DEBUGTRACE((LOG_REPDRV, "Deleting Instance: %S\n", wszClassInstanceLink)); if (wcscmp(wszKeyRoot, m_namespaceClassHash) == 0) { return DeleteInstanceAsNamespace(pNs, wszClassInstanceLink); } //build KI entry and delete the object CFileName wszKI; if (wszKI == NULL) return NULL; StringCchCopyW(wszKI, wszKI.Length(), g_Glob.GetRootDir()); StringCchCatW(wszKI, wszKI.Length(), L"\\"); StringCchCatNW(wszKI, wszKI.Length(), wszClassInstanceLink, 3+32); StringCchCatW(wszKI, wszKI.Length(), L"\\KI_"); StringCchCatW(wszKI, wszKI.Length(), wszKeyRoot); StringCchCatW(wszKI, wszKI.Length(), L"\\I_"); StringCchCatW(wszKI, wszKI.Length(), wszClassInstanceLink + wcslen(wszClassInstanceLink) - 32); lRes = g_Glob.m_FileCache.DeleteObject(wszKI); if (lRes) return A51TranslateErrorCode(lRes); //Build instance reference enumerator link StringCchCopyW(wszKI, wszKI.Length(), g_Glob.GetRootDir()); StringCchCatW(wszKI, wszKI.Length(), L"\\"); StringCchCatNW(wszKI, wszKI.Length(), wszClassInstanceLink, 3+32); StringCchCatW(wszKI, wszKI.Length(), L"\\KI_"); StringCchCatW(wszKI, wszKI.Length(), wszKeyRoot); StringCchCatW(wszKI, wszKI.Length(), L"\\IR_"); StringCchCatW(wszKI, wszKI.Length(), wszClassInstanceLink + wcslen(wszClassInstanceLink) - 32); StringCchCatW(wszKI, wszKI.Length(), L"\\R_"); hRes = DeleteInstanceReferences(wszKI); if (SUCCEEDED(hRes)) { //Now delete the class instance link StringCchCopyW(wszKI, wszKI.Length(), g_Glob.GetRootDir()); StringCchCatW(wszKI, wszKI.Length(), L"\\"); StringCchCatW(wszKI, wszKI.Length(), wszClassInstanceLink); lRes = g_Glob.m_FileCache.DeleteLink(wszKI); if (lRes) hRes = A51TranslateErrorCode(lRes); } return hRes; } //===================================================================== // // CLocalizationUpgrade::DeleteInstanceReferences // // Description: // Enumerates the instance references for the given instance link and deletes the link and object // // Parameters: // wszInstLink - key root instance link of references to be deleted in format NS_<>\KI_<>\I_<> // //===================================================================== //NOTE: FULL LINK PASSED IN! HRESULT CLocalizationUpgrade::DeleteInstanceReferences(CFileName &wszInstLink) { LONG lRes = 0; CFileName wszFullPath; if (wszFullPath == NULL) return WBEM_E_OUT_OF_MEMORY; StringCchCopyW(wszFullPath, wszFullPath.Length(), g_Glob.GetRootDir()); StringCchCatW(wszFullPath, wszFullPath.Length(), L"\\"); //Enumerate the instances LPVOID pEnumHandle = NULL; lRes = g_Glob.m_FileCache.IndexEnumerationBegin(wszInstLink, &pEnumHandle); if (lRes == ERROR_SUCCESS) { while(1) { lRes = g_Glob.m_FileCache.IndexEnumerationNext(pEnumHandle, wszInstLink, true); if (lRes == ERROR_NO_MORE_FILES) { lRes = ERROR_SUCCESS; break; } else if (lRes) { break; } //Convert to a FULL path StringCchCatW(wszFullPath+g_Glob.GetRootDirLen()+1, wszFullPath.Length()-g_Glob.GetRootDirLen()-1, wszInstLink); lRes = g_Glob.m_FileCache.DeleteObject(wszFullPath); if (lRes) break; } g_Glob.m_FileCache.IndexEnumerationEnd(pEnumHandle); } else { if (lRes == ERROR_FILE_NOT_FOUND) lRes = ERROR_SUCCESS; } return A51TranslateErrorCode(lRes);; } //===================================================================== // // CLocalizationUpgrade::DeleteClassRelationships // // Description: // Deletes all class relationships, including parent/child and references // // Parameters: // wszPath - Full path of class definition, c:\windows\...\NS_<>\CD_<> // //===================================================================== HRESULT CLocalizationUpgrade::DeleteClassRelationships(CFileName &wszPath, const wchar_t wszParentClassHash[MAX_HASH_LEN+1]) { //Convert from the class definition to a class relationship path CFileName wszCRLink; if (wszCRLink == NULL) return WBEM_E_OUT_OF_MEMORY; StringCchCopyW(wszCRLink, wszCRLink.Length(), wszPath); wszCRLink[g_Glob.GetRootDirLen()+1+3+32+1+1] = L'R'; HRESULT hRes = 0; LONG lRes = 0; CFileName wszFullPath; if (wszFullPath == NULL) return WBEM_E_OUT_OF_MEMORY; StringCchCopyW(wszFullPath, wszFullPath.Length(), g_Glob.GetRootDir()); StringCchCatW(wszFullPath, wszFullPath.Length(), L"\\"); //Enumerate the instances LPVOID pEnumHandle = NULL; lRes = g_Glob.m_FileCache.IndexEnumerationBegin(wszCRLink, &pEnumHandle); if (lRes == ERROR_SUCCESS) { while(1) { lRes = g_Glob.m_FileCache.IndexEnumerationNext(pEnumHandle, wszCRLink, true); if (lRes == ERROR_NO_MORE_FILES) { lRes = ERROR_SUCCESS; break; } else if (lRes) { break; } //Convert to a FULL path StringCchCopyW(wszFullPath+g_Glob.GetRootDirLen()+1, wszFullPath.Length()-g_Glob.GetRootDirLen()-1, wszCRLink); lRes = g_Glob.m_FileCache.DeleteLink(wszFullPath); if (lRes) break; } g_Glob.m_FileCache.IndexEnumerationEnd(pEnumHandle); } else { if (lRes == ERROR_FILE_NOT_FOUND) lRes = ERROR_SUCCESS; } hRes = A51TranslateErrorCode(lRes); if (SUCCEEDED(hRes)) { //Now we need to delete our parent's relationship to us! StringCchCopyW(wszCRLink, wszCRLink.Length(), wszPath); wszCRLink[g_Glob.GetRootDirLen()+1+3+32+1+1] = L'R'; StringCchCopyW(wszCRLink+g_Glob.GetRootDirLen()+1+3+32+1+3, wszCRLink.Length()-g_Glob.GetRootDirLen()-1-3-32-1-3, wszParentClassHash); StringCchCatW(wszCRLink, wszCRLink.Length(), L"\\C_"); StringCchCatW(wszCRLink, wszCRLink.Length(), wszPath+g_Glob.GetRootDirLen()+1+3+32+1+3); lRes = g_Glob.m_FileCache.DeleteLink(wszCRLink); hRes = A51TranslateErrorCode(lRes); } return hRes; } //===================================================================== // // CLocalizationUpgrade::RetrieveKeyRootClass // // Description: // Searches for instances under KI_<> for all classes in the hierarchy chain for the specified class. // This is a slower process because we have to retrieve each class blob and get the hash of the // parent class // // Parameters: // wszClassDefinitionPath - Path of class definition to retrieve key root class, NS_<>\CD_<> // wszKeyRootClass - This is where we put the 32-character hash of the key root class // or empty string if there is none! // //===================================================================== HRESULT CLocalizationUpgrade::RetrieveKeyRootClass(CFileName &wszClassDefinitionPath, CFileName &wszKeyRootClass) { HRESULT hRes = 0; LONG lRes = 0; CFileName wszFullClassPath; if (wszFullClassPath == NULL) return WBEM_E_OUT_OF_MEMORY; CFileName wszFullKIPath; if (wszFullKIPath == NULL) return WBEM_E_OUT_OF_MEMORY; StringCchCopyW(wszFullClassPath, wszFullClassPath.Length(), g_Glob.GetRootDir()); StringCchCatW(wszFullClassPath, wszFullClassPath.Length(), L"\\"); StringCchCatW(wszFullClassPath, wszFullClassPath.Length(), wszClassDefinitionPath); StringCchCopyW(wszFullKIPath, wszFullKIPath.Length(), g_Glob.GetRootDir()); StringCchCatW(wszFullKIPath, wszFullKIPath.Length(), L"\\"); StringCchCatW(wszFullKIPath, wszFullKIPath.Length(), wszClassDefinitionPath); //convert the class definition to a instance definition wszFullKIPath[g_Glob.GetRootDirLen()+1+3+32+1]=L'K'; wszFullKIPath[g_Glob.GetRootDirLen()+1+3+32+2]=L'I'; StringCchCatW(wszFullKIPath, wszFullKIPath.Length(), L"\\I_"); wszKeyRootClass[0] = L'\0'; do { //Check if we have any instances hRes = IndexExists(wszFullKIPath); if (SUCCEEDED(hRes)) { //We have the entry we are looking for StringCchCopyNW(wszKeyRootClass, wszKeyRootClass.Length(), wszFullKIPath+g_Glob.GetRootDirLen()+1+3+32+1+3, 32); break; } else if (hRes != WBEM_E_NOT_FOUND) { break; } hRes = 0; //Retrieve the class hash of the parent class hRes = RetrieveParentClassHash(wszFullClassPath, wszFullKIPath + g_Glob.GetRootDirLen() + 1 + 3 + 32 + 1 + 3); if (hRes == WBEM_S_NO_MORE_DATA) { hRes = 0; break; } StringCchCatW(wszFullKIPath, wszFullKIPath.Length(), L"\\I_"); StringCchCopyNW(wszFullClassPath + g_Glob.GetRootDirLen() + 1 + 3 + 32 + 1 + 3, wszFullClassPath.Length() - g_Glob.GetRootDirLen() - 1 - 3 - 32 - 1 - 3, wszFullKIPath + g_Glob.GetRootDirLen() + 1 + 3 + 32 + 1 + 3, 32); if (FAILED(hRes)) break; } while (1); return hRes; } HRESULT CLocalizationUpgrade::RetrieveParentClassHash(CFileName &wszFullClassPath, wchar_t wszParentClassHash[MAX_HASH_LEN+1]) { LONG lRes = 0; HRESULT hRes = 0; //Retrieve the class hash of the parent class BYTE *pBuffer = NULL; DWORD dwLen = 0; lRes = g_Glob.m_FileCache.ReadObject(wszFullClassPath, &dwLen, &pBuffer, true); if (lRes == ERROR_FILE_NOT_FOUND) { //This is probably a class from the system namespace! CFileName wszSysClassPath; if (wszSysClassPath == NULL) return WBEM_E_OUT_OF_MEMORY; StringCchCopyW(wszSysClassPath, wszSysClassPath.Length(), wszFullClassPath); wmemcpy(wszSysClassPath+g_Glob.GetRootDirLen()+1+3, m_systemNamespaceHash, 32); lRes = g_Glob.m_FileCache.ReadObject(wszSysClassPath, &dwLen, &pBuffer, true); if (lRes) return A51TranslateErrorCode(lRes); } else if (lRes) { return A51TranslateErrorCode(lRes); } CTempFreeMe tfm(pBuffer, dwLen); //Null terminate the class name - safe to update buffer as it is always bigger than //just the name! wchar_t *wszSuperclassName = (wchar_t*)(pBuffer+sizeof(DWORD)); wszSuperclassName[*(DWORD*)pBuffer] = L'\0'; //Now we need to validate that this parent is generated using the OldHash //method and not NewHash! wchar_t wszOldHash[MAX_HASH_LEN+1]; wchar_t wszNewHash[MAX_HASH_LEN+1]; hRes = OldHash(wszSuperclassName, wszOldHash); if (FAILED(hRes)) return hRes; hRes = NewHash(wszSuperclassName, wszNewHash); if (FAILED(hRes)) return hRes; if (wcsncmp(L"", wszSuperclassName, *((DWORD*)pBuffer)) == 0) { StringCchCopyW(wszParentClassHash, MAX_HASH_LEN+1, wszNewHash); return WBEM_S_NO_MORE_DATA; } if (wcscmp(wszOldHash, wszNewHash) == 0) { //No difference so nothing extra to do! StringCchCopyW(wszParentClassHash, MAX_HASH_LEN+1, wszNewHash); return WBEM_NO_ERROR; } //There is a possibility of using either new or old, so we need to dig deeper! CFileName wszParentClass; if (wszParentClass == NULL) return WBEM_E_OUT_OF_MEMORY; StringCchCopyW(wszParentClass, wszParentClass.Length(), wszFullClassPath); wmemcpy(wszParentClass+g_Glob.GetRootDirLen()+1+3+32+1+3, wszOldHash, 32); hRes = IndexExists(wszParentClass); if (hRes == WBEM_E_NOT_FOUND) { //Try with the other hash! wmemcpy(wszParentClass+g_Glob.GetRootDirLen()+1+3+32+1+3, wszNewHash, 32); hRes = IndexExists(wszParentClass); if (hRes == WBEM_NO_ERROR) StringCchCopyW(wszParentClassHash, MAX_HASH_LEN+1, wszNewHash); } else if (hRes == WBEM_NO_ERROR) { StringCchCopyW(wszParentClassHash, MAX_HASH_LEN+1, wszOldHash); } return hRes; } HRESULT CLocalizationUpgrade::DeleteInstanceAsNamespace(CNamespaceHandle *pNs, const wchar_t *wszClassInstanceLink) { HRESULT hRes = NULL; //Retrieve the instance and get the key from it CFileName wszKIInstanceLink; if (wszKIInstanceLink == NULL) return WBEM_E_OUT_OF_MEMORY; StringCchCopyW(wszKIInstanceLink, wszKIInstanceLink.Length(),g_Glob.GetRootDir()); StringCchCatW(wszKIInstanceLink, wszKIInstanceLink.Length(), L"\\"); StringCchCatNW(wszKIInstanceLink, wszKIInstanceLink.Length(), wszClassInstanceLink, 3+32); StringCchCatW(wszKIInstanceLink, wszKIInstanceLink.Length(), L"\\KI_"); StringCchCatW(wszKIInstanceLink, wszKIInstanceLink.Length(), m_namespaceClassHash); StringCchCatW(wszKIInstanceLink, wszKIInstanceLink.Length(), L"\\I_"); StringCchCatW(wszKIInstanceLink, wszKIInstanceLink.Length(), wszClassInstanceLink + wcslen(wszClassInstanceLink) - 32); _IWmiObject *pInstance = NULL; hRes = pNs->FileToInstance(NULL, wszKIInstanceLink, NULL, 0, &pInstance, true); if (FAILED(hRes)) return hRes; CReleaseMe rm2(pInstance); //Extract the string from the object VARIANT vName; VariantInit(&vName); CClearMe cm(&vName); hRes = pInstance->Get(L"Name", 0, &vName, NULL, NULL); if(FAILED(hRes)) return hRes; if(V_VT(&vName) != VT_BSTR) { return WBEM_E_INVALID_OBJECT; } //Build the full namespace name size_t len = wcslen(pNs->m_wsNamespace) + 1 + wcslen(V_BSTR(&vName)) + 1; wchar_t *wszNamespaceName = new wchar_t[len]; if (wszNamespaceName == NULL) return WBEM_E_OUT_OF_MEMORY; StringCchCopyW(wszNamespaceName, len, pNs->m_wsNamespace); StringCchCatW(wszNamespaceName, len, L"\\"); StringCchCatW(wszNamespaceName, len, V_BSTR(&vName)); return DeleteNamespaceRecursive(wszNamespaceName); } //===================================================================== // // CLocalizationUpgrade::FixupIndexReferenceBlob // // Description: // Retrieves the instance reference blob and fixes up the entry in // there, then writes it back. // // Parameters: // wszReferenceIndex - Path to an index reference path: ns\ki\ir\r // //===================================================================== HRESULT CLocalizationUpgrade::FixupIndexReferenceBlob(CFileName &wszReferenceIndex) { HRESULT hRes =0; //Create full path name CFileName wszFullPath; if (wszFullPath == NULL) return WBEM_E_OUT_OF_MEMORY; StringCchCopyW(wszFullPath, wszFullPath.Length(), g_Glob.GetRootDir()); StringCchCatW(wszFullPath, wszFullPath.Length(), L"\\"); StringCchCatW(wszFullPath, wszFullPath.Length(), wszReferenceIndex); //remove the .X.Y.Z as this would screw everything up - both reading and writing wcstok(wszFullPath + g_Glob.GetRootDirLen(), L"."); //Retrieve the blob LONG lRes = 0; DWORD dwLen = 0; BYTE *pBuffer = NULL; lRes = g_Glob.m_FileCache.ReadObject(wszFullPath, &dwLen, &pBuffer); if (lRes) return A51TranslateErrorCode(lRes); CTempFreeMe tfm(pBuffer, dwLen); //Find the path BYTE *pPath = pBuffer; DWORD dwLen2; memcpy(&dwLen2, pPath, sizeof(DWORD)); pPath += (sizeof(wchar_t)*dwLen2) + sizeof(DWORD); memcpy(&dwLen2, pPath, sizeof(DWORD)); pPath += (sizeof(wchar_t)*dwLen2) + sizeof(DWORD); memcpy(&dwLen2, pPath, sizeof(DWORD)); pPath += (sizeof(wchar_t)*dwLen2) + sizeof(DWORD); memcpy(&dwLen2, pPath, sizeof(DWORD)); pPath += sizeof(DWORD) + sizeof(L'\\'); dwLen2 --; //Extract the path CFileName wszInstPath, wszNewInstPath; if ((wszInstPath == NULL) || (wszNewInstPath == NULL)) return WBEM_E_OUT_OF_MEMORY; StringCchCopyNW(wszInstPath, wszInstPath.Length(), (wchar_t*)pPath, dwLen2); //fixup the path bool bChanged = false; hRes = FixupIndex(wszInstPath, wszNewInstPath, bChanged); if (FAILED(hRes)) return hRes; if (bChanged) { DEBUGTRACE((LOG_REPDRV, "Fixing up instance path in reference blob: %S\n", wszReferenceIndex)); //re-insert into the blob wmemcpy((wchar_t*)pPath, wszNewInstPath, dwLen2); //write back lRes = g_Glob.m_FileCache.WriteObject(wszFullPath, NULL, dwLen, pBuffer); if (lRes) return A51TranslateErrorCode(lRes); } return 0; } //===================================================================== // // CLocalizationUpgrade::FixupInstanceBlob // // Description: // Retrieves the instance blob and fixes up the class entry in // there, then writes it back. // // Parameters: // wszInstanceIndex - Path to an instance reference path: ns\ki\i // //===================================================================== HRESULT CLocalizationUpgrade::FixupInstanceBlob(CFileName &wszInstanceIndex) { HRESULT hRes =0; //Create full path name CFileName wszFullPath; if (wszFullPath == NULL) return WBEM_E_OUT_OF_MEMORY; StringCchCopyW(wszFullPath, wszFullPath.Length(), g_Glob.GetRootDir()); StringCchCatW(wszFullPath, wszFullPath.Length(), L"\\"); StringCchCatW(wszFullPath, wszFullPath.Length(), wszInstanceIndex); //remove the .X.Y.Z as this would screw everything up - both reading and writing wcstok(wszFullPath + g_Glob.GetRootDirLen(), L"."); //Retrieve the blob LONG lRes = 0; DWORD dwLen = 0; BYTE *pBuffer = NULL; lRes = g_Glob.m_FileCache.ReadObject(wszFullPath, &dwLen, &pBuffer); if (lRes) return A51TranslateErrorCode(lRes); CTempFreeMe tfm(pBuffer, dwLen); //Extract the class hash wchar_t *wszClassHash = new wchar_t [MAX_HASH_LEN+1]; if (wszClassHash == NULL) return WBEM_E_OUT_OF_MEMORY; StringCchCopyNW(wszClassHash, MAX_HASH_LEN+1, (wchar_t*)pBuffer, 32); //fixup the path wchar_t *wszNewHash = NULL; hRes = GetNewHash(wszClassHash, &wszNewHash); if (hRes == WBEM_E_NOT_FOUND) return WBEM_NO_ERROR; else if (FAILED(hRes)) return hRes; else { DEBUGTRACE((LOG_REPDRV, "Fixing up class hash in instance blob: %S\n", wszInstanceIndex)); //re-insert into the blob wmemcpy((wchar_t*)pBuffer, wszNewHash, 32); //Build the CI full path also as we need to write both back CFileName wsCIPath; if (wsCIPath == NULL) return WBEM_E_OUT_OF_MEMORY; StringCchCopyW(wsCIPath, wsCIPath.Length(), g_Glob.GetRootDir()); StringCchCatW(wsCIPath, wsCIPath.Length(), L"\\"); StringCchCatNW(wsCIPath, wsCIPath.Length(), wszInstanceIndex, 3+32); StringCchCatW(wsCIPath, wsCIPath.Length(), L"\\CI_"); StringCchCatW(wsCIPath, wsCIPath.Length(), wszNewHash); StringCchCatW(wsCIPath, wsCIPath.Length(), L"\\IL_"); StringCchCatN(wsCIPath, wsCIPath.Length(), wszInstanceIndex + 3+32+1+3+32+1+2, 32); //write back lRes = g_Glob.m_FileCache.WriteObject(wszFullPath, wsCIPath, dwLen, pBuffer); if (lRes) return A51TranslateErrorCode(lRes); } return 0; }