You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
2636 lines
93 KiB
2636 lines
93 KiB
/*++
|
|
|
|
Copyright (C) 2000-2002 Microsoft Corporation
|
|
|
|
--*/
|
|
|
|
#include "precomp.h"
|
|
#include <wbemidl.h>
|
|
#include <wbemint.h>
|
|
#include <stdio.h>
|
|
#include <wbemcomn.h>
|
|
#include <ql.h>
|
|
#include <time.h>
|
|
#include "a51rep.h"
|
|
#include <md5.h>
|
|
#include <objpath.h>
|
|
#include "a51tools.h"
|
|
#include "corex.h"
|
|
#include <persistcfg.h>
|
|
#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<wchar_t> 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<CNamespaceHandle> 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<wchar_t> 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<wchar_t> 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<wchar_t> 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<wchar_t> 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_<hash>\KI_<hash>\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_<hash>
|
|
//
|
|
//=====================================================================
|
|
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_<hash>\....
|
|
// 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_<hash>\...
|
|
// wszNewIndex - new path of format NS_<hash>\...
|
|
//
|
|
//=====================================================================
|
|
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_<hash>\...
|
|
// wszNewIndex - new path of format NS_<hash>\...
|
|
//
|
|
//=====================================================================
|
|
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<CNamespaceHandle> 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<wchar_t> 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_<hash>
|
|
//
|
|
//=====================================================================
|
|
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_<hash>\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_<class defn hash>\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;
|
|
}
|
|
|
|
|
|
|
|
|