Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

2636 lines
93 KiB

  1. /*++
  2. Copyright (C) 2000-2002 Microsoft Corporation
  3. --*/
  4. #include "precomp.h"
  5. #include <wbemidl.h>
  6. #include <wbemint.h>
  7. #include <stdio.h>
  8. #include <wbemcomn.h>
  9. #include <ql.h>
  10. #include <time.h>
  11. #include "a51rep.h"
  12. #include <md5.h>
  13. #include <objpath.h>
  14. #include "a51tools.h"
  15. #include "corex.h"
  16. #include <persistcfg.h>
  17. #include "upgrade.h"
  18. extern DWORD g_dwSecTlsIndex;
  19. //=====================================================================
  20. //
  21. // CLocalizationUpgrade::CLocalizationUpgrade
  22. //
  23. // Description:
  24. //
  25. // Parameters:
  26. // pContol Life Control
  27. // pRepository Pointer to repository pointer
  28. //=====================================================================
  29. CLocalizationUpgrade::CLocalizationUpgrade(CLifeControl* pControl, CRepository * pRepository)
  30. : m_pControl(pControl), m_pRepository(pRepository)
  31. {
  32. }
  33. //=====================================================================
  34. //
  35. // CLocalizationUpgrade::~CLocalizationUpgrade
  36. //
  37. // Description:
  38. //
  39. // Parameters:
  40. //
  41. //=====================================================================
  42. CLocalizationUpgrade::~CLocalizationUpgrade()
  43. {
  44. }
  45. //=====================================================================
  46. //
  47. // CLocalizationUpgrade::DoUpgrade
  48. //
  49. // Description:
  50. // Control routing to bootstrap the upgrade process. If the registry key
  51. // already exists then it does nothing.
  52. //
  53. // Parameters:
  54. //
  55. //=====================================================================
  56. HRESULT CLocalizationUpgrade::DoUpgrade()
  57. {
  58. HRESULT hRes = 0;
  59. //Check to make sure we even need to do the upgrade!
  60. HKEY hKey;
  61. LONG lRes;
  62. bool bDoUpgrade = false;
  63. //Get the current database version
  64. DWORD dwVal = 0;
  65. CDbVerRead cfg;
  66. cfg.TidyUp();
  67. cfg.ReadDbVer(dwVal);
  68. if (dwVal != 6)
  69. return WBEM_NO_ERROR;
  70. try
  71. {
  72. hRes = OldHash(L"__namespace", m_namespaceClassHash);
  73. if (FAILED(hRes))
  74. return hRes;
  75. hRes = OldHash(L"", m_emptyClassHash);
  76. if (FAILED(hRes))
  77. return hRes;
  78. hRes = OldHash(A51_SYSTEMCLASS_NS, m_systemNamespaceHash);
  79. if (FAILED(hRes))
  80. return hRes;
  81. //Reset a TLS entry if necessary! Otherwise we may not find any
  82. //instances of __thisNamespace!
  83. LPVOID pOldTlsEntry = NULL;
  84. if (g_dwSecTlsIndex != -1)
  85. {
  86. pOldTlsEntry = TlsGetValue(g_dwSecTlsIndex);
  87. TlsSetValue(g_dwSecTlsIndex, 0);
  88. }
  89. //Set the Class Cache size to 0 bytes so it does not
  90. //cache anything during this process. if it did, we
  91. //would get kind of screwed up really badly!
  92. g_Glob.m_ForestCache.SetMaxMemory(0, 10000);
  93. CAutoWriteLock lock(&g_readWriteLock);
  94. if (lock.Lock())
  95. {
  96. lRes = g_Glob.m_FileCache.BeginTransaction();
  97. if (lRes)
  98. hRes = A51TranslateErrorCode(lRes);
  99. if (SUCCEEDED(hRes))
  100. {
  101. m_pass = 1;
  102. DEBUGTRACE((LOG_REPDRV, "============== LOCALE UPGRADE : Enumerate Child Namespaces =============\n"));
  103. //1 Enumeration all namespaces
  104. //Deals with class enumeration, and deletion if there is a conflict,
  105. //and enumerates all the instances in the namespace checking both types
  106. //of hashes and recording differences
  107. hRes = EnumerateChildNamespaces(L"root");
  108. //1 Don't do anything unless we have something to do!
  109. if (m_keyHash.Size() ||m_pathHash.Size())
  110. {
  111. //1 Process namespace collisions
  112. if (SUCCEEDED(hRes))
  113. {
  114. m_pass = 2;
  115. DEBUGTRACE((LOG_REPDRV, "============== LOCALE UPGRADE : Namespace Collision Detection =============\n"));
  116. hRes = ProcessNamespaceCollisions();
  117. }
  118. if (SUCCEEDED(hRes))
  119. {
  120. m_pass = 3;
  121. DEBUGTRACE((LOG_REPDRV, "============== LOCALE UPGRADE: Fixup BTree Changes =============\n"));
  122. //1 Phase 3 - fixup changed hashes
  123. //Iterate through the entire BTree and fix-up all failures
  124. hRes = FixupBTree();
  125. }
  126. }
  127. else
  128. {
  129. ERRORTRACE((LOG_REPDRV, "============== LOCALE UPGRADE : No Changes Needed! =============\n"));
  130. }
  131. }
  132. if (SUCCEEDED(hRes))
  133. {
  134. ERRORTRACE((LOG_REPDRV, "============== LOCALE UPGRADE: Committing Changes =============\n"));
  135. g_Glob.m_FileCache.CommitTransaction();
  136. }
  137. else
  138. {
  139. ERRORTRACE((LOG_REPDRV, "============== LOCALE UPGRADE: Rolling back all Changes =============\n"));
  140. g_Glob.m_FileCache.AbortTransaction();
  141. }
  142. //Regardless of the error code, the class cache is probably totally screwed
  143. //up, so we need to do dramatic stuff to it!
  144. //This will also reset the class cache to it's default sizes!
  145. g_Glob.m_ForestCache.Deinitialize();
  146. g_Glob.m_ForestCache.Initialize();
  147. }
  148. if (g_dwSecTlsIndex != -1)
  149. {
  150. TlsSetValue(g_dwSecTlsIndex, pOldTlsEntry);
  151. }
  152. if (SUCCEEDED(hRes))
  153. {
  154. ERRORTRACE((LOG_REPDRV, "============== LOCALE UPGRADE: Fixup SUCCEEDED =============\n"));
  155. }
  156. else
  157. {
  158. ERRORTRACE((LOG_REPDRV, "============== LOCALE UPGRADE: Fixup FAILED =============\n"));
  159. }
  160. }
  161. catch (...)
  162. {
  163. g_Glob.m_FileCache.AbortTransaction();
  164. ERRORTRACE((LOG_REPDRV, "============== LOCALE UPGRADE: Something threw an exception =============\n"));
  165. }
  166. CPersistentConfig pCfg;
  167. pCfg.SetPersistentCfgValue(PERSIST_CFGVAL_CORE_FSREP_VERSION, A51_REP_FS_VERSION);
  168. return hRes;
  169. }
  170. //=====================================================================
  171. //
  172. // CLocalizationUpgrade::EnumerateChildNamespaces
  173. //
  174. // Description:
  175. // Enumerates all child namespaces of the namespace passed, adds
  176. // the namespaces to the m_namespaces structure, and iterates down
  177. // into those namespaces
  178. //
  179. // Parameters:
  180. // wsRootNamespace Namespace name to enumerate. E.G. root\default
  181. //
  182. //=====================================================================
  183. HRESULT CLocalizationUpgrade::EnumerateChildNamespaces(const wchar_t * wsRootNamespace)
  184. {
  185. //We know the namespace we need to look under, we know the class key root, so we
  186. //can enumerate all the instances of that class and do a FileToInstance on them all. From
  187. //that we can add the event and the entry to the namespace list, and do the enumeration
  188. //of child namespaces on them
  189. LONG lRes = 0;
  190. HRESULT hRes = 0;
  191. CFileName wsNamespaceHash;
  192. if (wsNamespaceHash == NULL)
  193. return WBEM_E_OUT_OF_MEMORY;
  194. wchar_t *wszNewNamespaceHash = new wchar_t[MAX_HASH_LEN+1];
  195. if (wszNewNamespaceHash == NULL)
  196. return WBEM_E_OUT_OF_MEMORY;
  197. CVectorDeleteMe<wchar_t> vdm(wszNewNamespaceHash);
  198. hRes = NewHash(wsRootNamespace, wszNewNamespaceHash);
  199. if (FAILED(hRes))
  200. return hRes;
  201. //Create the hashed path to the Key Root for the namespace
  202. StringCchCopyW(wsNamespaceHash, MAX_PATH, g_Glob.GetRootDir());
  203. StringCchCatW(wsNamespaceHash, MAX_PATH, L"\\NS_");
  204. hRes = OldHash(wsRootNamespace, wsNamespaceHash + g_Glob.GetRootDirLen()+4);
  205. if (FAILED(hRes))
  206. return hRes;
  207. hRes = IndexExists(wsNamespaceHash);
  208. if (hRes == WBEM_E_NOT_FOUND)
  209. {
  210. //Try using NewHash instead!
  211. hRes = NewHash(wsRootNamespace, wsNamespaceHash + g_Glob.GetRootDirLen()+4);
  212. if (FAILED(hRes))
  213. return hRes;
  214. hRes = IndexExists(wsNamespaceHash);
  215. if (hRes == WBEM_E_NOT_FOUND)
  216. return WBEM_NO_ERROR; //NOthing in this namespace!
  217. else if (FAILED(hRes))
  218. return hRes;
  219. }
  220. else if (FAILED(hRes))
  221. return hRes;
  222. DEBUGTRACE((LOG_REPDRV, ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n"));
  223. DEBUGTRACE((LOG_REPDRV, "Processing namespace: %S, %S\n", wsRootNamespace, wsNamespaceHash+g_Glob.GetRootDirLen()+1));
  224. //2 Store namespace path for pass 2 of update
  225. hRes = m_namespaces.AddStrings(wsRootNamespace, wsNamespaceHash);
  226. if (FAILED(hRes))
  227. return hRes;
  228. //2 Create a CNamespaceHandle so we can access objects in this namespace
  229. CNamespaceHandle *pNs = new CNamespaceHandle(m_pControl, m_pRepository);
  230. if (pNs == NULL)
  231. return WBEM_E_OUT_OF_MEMORY;
  232. CDeleteMe<CNamespaceHandle> cdm(pNs);
  233. hRes = pNs->Initialize2(wsRootNamespace, wsNamespaceHash+g_Glob.GetRootDirLen()+4);
  234. if (FAILED(hRes))
  235. return hRes;
  236. //2 Fixup all the classes in this namespace
  237. //NOTE: We need to do this BEFORE we process the hash for the namespace
  238. //because otherwise it will be stored in a different place and so
  239. //instance enumeration will fail!
  240. hRes = ProcessSystemClassesRecursively(pNs,
  241. wsNamespaceHash+g_Glob.GetRootDirLen()+4,
  242. m_emptyClassHash);
  243. if (FAILED(hRes))
  244. return hRes;
  245. hRes = ProcessClassesRecursively(pNs,
  246. wsNamespaceHash+g_Glob.GetRootDirLen()+4,
  247. m_emptyClassHash);
  248. if (FAILED(hRes))
  249. return hRes;
  250. hRes = EnumerateInstances(pNs, wszNewNamespaceHash);
  251. if (FAILED(hRes))
  252. return hRes;
  253. StringCchCatW(wsNamespaceHash, MAX_PATH, L"\\" A51_KEYROOTINST_DIR_PREFIX);
  254. StringCchCatW(wsNamespaceHash, MAX_PATH, m_namespaceClassHash);
  255. StringCchCatW(wsNamespaceHash, MAX_PATH, L"\\" A51_INSTDEF_FILE_PREFIX);
  256. //2 Process Hash for this namespace
  257. bool bDifferent = false;
  258. hRes = ProcessHash(wsRootNamespace, &bDifferent);
  259. if (FAILED(hRes))
  260. return hRes;
  261. //2 Enumerate all the child namespaces
  262. LPVOID pEnumHandle = NULL;
  263. lRes = g_Glob.m_FileCache.ObjectEnumerationBegin(wsNamespaceHash, &pEnumHandle);
  264. if (lRes == ERROR_SUCCESS)
  265. {
  266. BYTE *pBlob = NULL;
  267. DWORD dwSize = 0;
  268. while(1)
  269. {
  270. lRes = g_Glob.m_FileCache.ObjectEnumerationNext(pEnumHandle, wsNamespaceHash, &pBlob, &dwSize);
  271. if (lRes == ERROR_NO_MORE_FILES)
  272. {
  273. lRes = ERROR_SUCCESS;
  274. break;
  275. }
  276. else if (lRes)
  277. break;
  278. //Get the instance
  279. _IWmiObject* pInstance = NULL;
  280. hRes = pNs->FileToInstance(NULL, wsNamespaceHash, pBlob, dwSize, &pInstance, true);
  281. //Free the blob
  282. g_Glob.m_FileCache.ObjectEnumerationFree(pEnumHandle, pBlob);
  283. if (FAILED(hRes))
  284. break;
  285. CReleaseMe rm2(pInstance);
  286. //Extract the string from the object
  287. VARIANT vName;
  288. VariantInit(&vName);
  289. CClearMe cm(&vName);
  290. hRes = pInstance->Get(L"Name", 0, &vName, NULL, NULL);
  291. if(FAILED(hRes))
  292. break;
  293. if(V_VT(&vName) != VT_BSTR)
  294. {
  295. hRes = WBEM_E_INVALID_OBJECT;
  296. break;
  297. }
  298. //Create the full namespace path
  299. wchar_t *wszChildNamespacePath = new wchar_t[wcslen(wsRootNamespace)+1+wcslen(V_BSTR(&vName)) + 1];
  300. if (wszChildNamespacePath == NULL)
  301. {
  302. hRes = WBEM_E_OUT_OF_MEMORY;
  303. break;
  304. }
  305. CVectorDeleteMe<wchar_t> vdm(wszChildNamespacePath);
  306. StringCchCopyW(wszChildNamespacePath, MAX_PATH, wsRootNamespace);
  307. StringCchCatW(wszChildNamespacePath, MAX_PATH, L"\\");
  308. StringCchCatW(wszChildNamespacePath, MAX_PATH, V_BSTR(&vName));
  309. //2 Process all child namespaces in this namespace
  310. hRes = EnumerateChildNamespaces(wszChildNamespacePath);
  311. if (FAILED(hRes))
  312. break;
  313. }
  314. g_Glob.m_FileCache.ObjectEnumerationEnd(pEnumHandle);
  315. }
  316. else
  317. {
  318. if (lRes == ERROR_FILE_NOT_FOUND)
  319. lRes = ERROR_SUCCESS;
  320. }
  321. if (lRes)
  322. hRes = A51TranslateErrorCode(lRes);
  323. return hRes;
  324. }
  325. HRESULT CLocalizationUpgrade::ProcessSystemClassesRecursively(CNamespaceHandle *pNs,
  326. const wchar_t *namespaceHash,
  327. const wchar_t *parentClassHash)
  328. {
  329. HRESULT hRes= 0;
  330. unsigned long lRes = 0;
  331. CFileName wszChildClasses;
  332. if (wszChildClasses == NULL)
  333. return WBEM_E_OUT_OF_MEMORY;
  334. wchar_t *childClassHash = new wchar_t[MAX_HASH_LEN+1];
  335. if (childClassHash == NULL)
  336. return WBEM_E_OUT_OF_MEMORY;
  337. CVectorDeleteMe<wchar_t> vdm(childClassHash);
  338. //Create full class reference path for parent/class relationship
  339. StringCchCopyW(wszChildClasses, wszChildClasses.Length(), g_Glob.GetRootDir());
  340. StringCchCatW(wszChildClasses, wszChildClasses.Length(), L"\\NS_");
  341. StringCchCatW(wszChildClasses, wszChildClasses.Length(), m_systemNamespaceHash);
  342. StringCchCatW(wszChildClasses, wszChildClasses.Length(), L"\\CR_");
  343. StringCchCatW(wszChildClasses, wszChildClasses.Length(), parentClassHash);
  344. StringCchCatW(wszChildClasses, wszChildClasses.Length(), L"\\C_");
  345. //Enumerate the child classes
  346. LPVOID pEnumHandle = NULL;
  347. lRes = g_Glob.m_FileCache.IndexEnumerationBegin(wszChildClasses, &pEnumHandle);
  348. if (lRes == ERROR_SUCCESS)
  349. {
  350. while(1)
  351. {
  352. lRes = g_Glob.m_FileCache.IndexEnumerationNext(pEnumHandle, wszChildClasses, true);
  353. if (lRes == ERROR_NO_MORE_FILES)
  354. {
  355. hRes = ERROR_SUCCESS;
  356. break;
  357. }
  358. else if (lRes)
  359. {
  360. hRes = A51TranslateErrorCode(lRes);
  361. break;
  362. }
  363. //extract the class hash
  364. StringCchCopyW(childClassHash, MAX_HASH_LEN+1, wszChildClasses + wcslen(wszChildClasses)-32);
  365. //Process user derived classes from this system class
  366. hRes = ProcessClassesRecursively(pNs, namespaceHash, childClassHash);
  367. if (FAILED(hRes))
  368. break;
  369. //Process other system classes that are derived from this class
  370. hRes = ProcessSystemClassesRecursively(pNs, namespaceHash, childClassHash);
  371. if (FAILED(hRes))
  372. break;
  373. }
  374. g_Glob.m_FileCache.IndexEnumerationEnd(pEnumHandle);
  375. }
  376. else
  377. {
  378. if (lRes == ERROR_FILE_NOT_FOUND)
  379. lRes = ERROR_SUCCESS;
  380. if (lRes)
  381. hRes = A51TranslateErrorCode(lRes);
  382. }
  383. return hRes;
  384. }
  385. //=====================================================================
  386. //
  387. // CLocalizationUpgrade::ProcessClassesRecursively
  388. //
  389. // Description:
  390. // Recursively enumerates all the classes from the one specified
  391. // and fixes it up as necessary
  392. //
  393. // Parameters:
  394. // classIndex full path to a class definition
  395. //
  396. //=====================================================================
  397. HRESULT CLocalizationUpgrade::ProcessClassesRecursively(CNamespaceHandle *pNs,
  398. const wchar_t *namespaceHash,
  399. const wchar_t *parentClassHash)
  400. {
  401. HRESULT hRes= 0;
  402. unsigned long lRes = 0;
  403. CFileName wszChildClasses;
  404. if (wszChildClasses == NULL)
  405. return WBEM_E_OUT_OF_MEMORY;
  406. wchar_t *childClassHash = new wchar_t[MAX_HASH_LEN+1];
  407. if (childClassHash == NULL)
  408. return WBEM_E_OUT_OF_MEMORY;
  409. CVectorDeleteMe<wchar_t> vdm(childClassHash);
  410. //Create full class reference path for parent/class relationship
  411. StringCchCopyW(wszChildClasses, wszChildClasses.Length(), g_Glob.GetRootDir());
  412. StringCchCatW(wszChildClasses, wszChildClasses.Length(), L"\\NS_");
  413. StringCchCatW(wszChildClasses, wszChildClasses.Length(), namespaceHash);
  414. StringCchCatW(wszChildClasses, wszChildClasses.Length(), L"\\CR_");
  415. StringCchCatW(wszChildClasses, wszChildClasses.Length(), parentClassHash);
  416. StringCchCatW(wszChildClasses, wszChildClasses.Length(), L"\\C_");
  417. //Enumerate the child classes
  418. LPVOID pEnumHandle = NULL;
  419. lRes = g_Glob.m_FileCache.IndexEnumerationBegin(wszChildClasses, &pEnumHandle);
  420. if (lRes == ERROR_SUCCESS)
  421. {
  422. while(1)
  423. {
  424. lRes = g_Glob.m_FileCache.IndexEnumerationNext(pEnumHandle, wszChildClasses, true);
  425. if (lRes == ERROR_NO_MORE_FILES)
  426. {
  427. hRes = ERROR_SUCCESS;
  428. break;
  429. }
  430. else if (lRes)
  431. {
  432. hRes = A51TranslateErrorCode(lRes);
  433. break;
  434. }
  435. //extract the class hash
  436. StringCchCopyW(childClassHash, MAX_HASH_LEN+1, wszChildClasses + wcslen(wszChildClasses)-32);
  437. //Process this class - this class calls back into this class to do the recursion!
  438. hRes = ProcessClass(pNs, namespaceHash, parentClassHash, childClassHash);
  439. if (FAILED(hRes))
  440. break;
  441. }
  442. g_Glob.m_FileCache.IndexEnumerationEnd(pEnumHandle);
  443. }
  444. else
  445. {
  446. if (lRes == ERROR_FILE_NOT_FOUND)
  447. lRes = ERROR_SUCCESS;
  448. if (lRes)
  449. hRes = A51TranslateErrorCode(lRes);
  450. }
  451. return hRes;
  452. }
  453. //=====================================================================
  454. //
  455. // CLocalizationUpgrade::ProcessClass
  456. //
  457. // Description:
  458. // retrieves the class, calculates new and old class hash, and
  459. // if they are different fixes up the CD hash, child class hashes
  460. // and the parent class hash to this one
  461. //
  462. // Parameters:
  463. // namespaceHash namespace hash
  464. // parentClassHash parent class hash
  465. // childClassHash hash of class to process
  466. //
  467. //=====================================================================
  468. HRESULT CLocalizationUpgrade::ProcessClass(CNamespaceHandle *pNs,
  469. const wchar_t *namespaceHash,
  470. const wchar_t *parentClassHash,
  471. const wchar_t *childClassHash)
  472. {
  473. HRESULT hRes = 0;
  474. //Make a class definition string for this class class
  475. CFileName classDefinition;
  476. if (classDefinition == NULL)
  477. return WBEM_E_OUT_OF_MEMORY;
  478. StringCchCopyW(classDefinition, classDefinition.Length(), g_Glob.GetRootDir());
  479. StringCchCatW(classDefinition, classDefinition.Length(), L"\\NS_");
  480. StringCchCatW(classDefinition, classDefinition.Length(), namespaceHash);
  481. StringCchCatW(classDefinition, classDefinition.Length(), L"\\CD_");
  482. StringCchCatW(classDefinition, classDefinition.Length(), childClassHash);
  483. _IWmiObject * pClass = NULL;
  484. __int64 nTime;
  485. bool bSystemClass;
  486. hRes = pNs->FileToClass(classDefinition, &pClass, false, &nTime, &bSystemClass);
  487. if (FAILED(hRes))
  488. return hRes;
  489. CReleaseMe rm(pClass);
  490. //Extract the string from the object
  491. VARIANT vName;
  492. VariantInit(&vName);
  493. CClearMe cm(&vName);
  494. hRes = pClass->Get(L"__class", 0, &vName, NULL, NULL);
  495. if(FAILED(hRes))
  496. return hRes;
  497. if(V_VT(&vName) != VT_BSTR)
  498. return WBEM_E_INVALID_OBJECT;
  499. MoveMemory(classDefinition, classDefinition+g_Glob.GetRootDirLen()+1, (wcslen(classDefinition+g_Glob.GetRootDirLen()+1)+1)*sizeof(wchar_t));
  500. DEBUGTRACE((LOG_REPDRV, "Processing Class: %S, %S\n", V_BSTR(&vName), classDefinition));
  501. bool bDifferent = false;
  502. hRes = ProcessHash(V_BSTR(&vName), &bDifferent);
  503. if (FAILED(hRes))
  504. return hRes;
  505. //Lets check that the hash we just generated was not the same as the one we are using!
  506. if (bDifferent)
  507. {
  508. wchar_t *newClassHash;
  509. hRes=GetNewHash(childClassHash, &newClassHash);
  510. if (hRes == WBEM_E_NOT_FOUND)
  511. {
  512. //There are no differences!
  513. hRes=WBEM_NO_ERROR;
  514. bDifferent = false;
  515. }
  516. }
  517. if (bDifferent)
  518. {
  519. CFileName newIndexEntry;
  520. if (newIndexEntry == NULL)
  521. return WBEM_E_OUT_OF_MEMORY;
  522. //We need to fixup this entry
  523. hRes = FixupIndex(classDefinition, newIndexEntry, bDifferent);
  524. if (FAILED(hRes))
  525. return hRes;
  526. bool bClassDeleted = false;
  527. if (bDifferent)
  528. {
  529. hRes = WriteClassIndex(pNs, classDefinition, newIndexEntry, &bClassDeleted);
  530. if (FAILED(hRes))
  531. return hRes;
  532. }
  533. //Now we need to fix up parent/class relationships?
  534. //Finally, process the child classes
  535. if (!bClassDeleted)
  536. return ProcessClassesRecursively(pNs, namespaceHash, newIndexEntry+wcslen(newIndexEntry)-32);
  537. else
  538. return WBEM_NO_ERROR;
  539. }
  540. else
  541. return ProcessClassesRecursively(pNs, namespaceHash, childClassHash);
  542. }
  543. //=====================================================================
  544. //
  545. // CLocalizationUpgrade::EnumerateInstances
  546. //
  547. // Description:
  548. // Enumerates all instances in a specified namespace
  549. //
  550. // Parameters:
  551. // pNs - We need to retrieve an instance, so we need a namespace handle to do that
  552. //
  553. //=====================================================================
  554. HRESULT CLocalizationUpgrade::EnumerateInstances(CNamespaceHandle *pNs, const wchar_t *wszNewNamespaceHash)
  555. {
  556. unsigned long lRes = 0;
  557. HRESULT hRes = 0;
  558. CFileName wsInstancePath;
  559. if (wsInstancePath == NULL)
  560. return WBEM_E_OUT_OF_MEMORY;
  561. CFileName wsInstanceShortPath;
  562. if (wsInstanceShortPath == NULL)
  563. return WBEM_E_OUT_OF_MEMORY;
  564. StringCchCopyW(wsInstancePath, wsInstancePath.Length(), pNs->m_wszClassRootDir);
  565. StringCchCatW(wsInstancePath, wsInstancePath.Length(), L"\\" A51_KEYROOTINST_DIR_PREFIX);
  566. //Enumerate all the objects
  567. LPVOID pEnumHandle = NULL;
  568. lRes = g_Glob.m_FileCache.IndexEnumerationBegin(wsInstancePath, &pEnumHandle);
  569. if (lRes == ERROR_SUCCESS)
  570. {
  571. while(1)
  572. {
  573. lRes = g_Glob.m_FileCache.IndexEnumerationNext(pEnumHandle, wsInstanceShortPath, true);
  574. if (lRes == ERROR_NO_MORE_FILES)
  575. {
  576. lRes = ERROR_SUCCESS;
  577. break;
  578. }
  579. else if (lRes)
  580. break;
  581. //Need to strip out the .X.Y.Z and make long path version
  582. wcstok(wsInstanceShortPath, L".");
  583. StringCchCopyW(wsInstancePath + g_Glob.GetRootDirLen()+1, wsInstancePath.Length() - g_Glob.GetRootDirLen() -1, wsInstanceShortPath);
  584. //2 check if this is an INSTANCE or a REFERENCE!
  585. //We are only interested if we are an instance. Instances are ns_..\KI..\I_..x.y.z
  586. //Reference is ns_..\KI_..\IR_..\R_..\I_..x.y.z
  587. //We can validate this by checking for the existance of the _ in the I_ entry!
  588. //for reference it would be an R from the IR_ entry!
  589. if ((wcslen(wsInstanceShortPath) > 73) && (wsInstanceShortPath[73] == L'_'))
  590. {
  591. //2 Retrieve the object blob
  592. DWORD dwLen = 0;
  593. BYTE *pBuffer = NULL;
  594. lRes = g_Glob.m_FileCache.ReadObject(wsInstancePath, &dwLen, &pBuffer);
  595. if (lRes)
  596. {
  597. hRes = A51TranslateErrorCode(lRes);
  598. break;
  599. }
  600. CTempFreeMe tfm(pBuffer, dwLen);
  601. //2 Extract class hash from blob
  602. wchar_t *wsOldClassHash = new wchar_t[MAX_HASH_LEN+1];
  603. wchar_t *wsNewClassHash = NULL;
  604. if (wsOldClassHash == NULL)
  605. {
  606. hRes = WBEM_E_OUT_OF_MEMORY;
  607. break;
  608. }
  609. CVectorDeleteMe<wchar_t> vdm(wsOldClassHash);
  610. StringCchCopyNW(wsOldClassHash, MAX_HASH_LEN+1, (wchar_t*)pBuffer, 32);
  611. hRes = GetNewHash(wsOldClassHash, &wsNewClassHash);
  612. if (hRes == WBEM_E_NOT_FOUND)
  613. hRes = WBEM_NO_ERROR;
  614. else if (FAILED(hRes))
  615. break;
  616. else
  617. StringCchCopyW(wsOldClassHash, MAX_HASH_LEN+1, wsNewClassHash);
  618. //Build up the full class definition fror this class
  619. CFileName wszClassDefinition;
  620. if (wszClassDefinition == NULL)
  621. {
  622. hRes = WBEM_E_OUT_OF_MEMORY;
  623. break;
  624. }
  625. StringCchCopyW(wszClassDefinition, wszClassDefinition.Length(), g_Glob.GetRootDir());
  626. StringCchCatW(wszClassDefinition, wszClassDefinition.Length(), L"\\");
  627. StringCchCatNW(wszClassDefinition, wszClassDefinition.Length(), wsInstanceShortPath, 3+32+1);
  628. StringCchCatW(wszClassDefinition, wszClassDefinition.Length(), L"CD_");
  629. StringCchCatW(wszClassDefinition, wszClassDefinition.Length(), wsOldClassHash);
  630. _IWmiObject *pClass = NULL;
  631. __int64 nTime;
  632. bool bSystemClass;
  633. hRes = pNs->FileToClass(wszClassDefinition, &pClass, false, &nTime, &bSystemClass);
  634. if (FAILED(hRes))
  635. break;
  636. CReleaseMe rm3(pClass);
  637. //2 Get the instance
  638. _IWmiObject* pInstance = NULL;
  639. hRes = pNs->FileToInstance(pClass, wsInstancePath, pBuffer, dwLen, &pInstance, true);
  640. if (FAILED(hRes))
  641. break;
  642. CReleaseMe rm2(pInstance);
  643. //2 Get the path
  644. VARIANT var;
  645. VariantInit(&var);
  646. hRes = pInstance->Get(L"__relpath", 0, &var, 0, 0);
  647. if (FAILED(hRes))
  648. break;
  649. CClearMe cm2(&var);
  650. dwLen = (wcslen(V_BSTR(&var)) + 1) ;
  651. wchar_t *strKey = (WCHAR*)TempAlloc(dwLen* sizeof(WCHAR));
  652. if(strKey == NULL)
  653. {
  654. hRes = WBEM_E_OUT_OF_MEMORY;
  655. break;
  656. }
  657. CTempFreeMe tfm3(strKey, dwLen* sizeof(WCHAR));
  658. bool bIsClass;
  659. LPWSTR __wszClassName = NULL;
  660. hRes = pNs->ComputeKeyFromPath(V_BSTR(&var), strKey, dwLen, &__wszClassName, &bIsClass);
  661. if(FAILED(hRes))
  662. break;
  663. DEBUGTRACE((LOG_REPDRV, "Processing Instance Hash: %S='%S', %S\n", __wszClassName, strKey, wsInstanceShortPath));
  664. TempFree(__wszClassName);
  665. bool bDifferent = false;
  666. hRes = ProcessHash(strKey, &bDifferent);
  667. if (FAILED(hRes))
  668. break;
  669. hRes = ProcessFullPath(wsInstancePath, wszNewNamespaceHash);
  670. if (FAILED(hRes))
  671. break;
  672. }
  673. else
  674. {
  675. DEBUGTRACE((LOG_REPDRV, "Ignoring Instance reference: %S\n", wsInstanceShortPath));
  676. }
  677. }
  678. g_Glob.m_FileCache.IndexEnumerationEnd(pEnumHandle);
  679. }
  680. else
  681. {
  682. if (lRes == ERROR_FILE_NOT_FOUND)
  683. lRes = ERROR_SUCCESS;
  684. }
  685. if (lRes)
  686. hRes = A51TranslateErrorCode(lRes);
  687. return hRes;
  688. }
  689. //=====================================================================
  690. //
  691. // CLocalizationUpgrade::ProcessHash
  692. //
  693. // Description:
  694. // Does the actual comparison of old and new hash of the given string.
  695. // If different it records it for later use.
  696. //
  697. // Parameters:
  698. // wszName Class name, namespace name, instance key.
  699. //
  700. //=====================================================================
  701. HRESULT CLocalizationUpgrade::ProcessHash(const wchar_t *wszName, bool *pDifferent)
  702. {
  703. //Hash using old ToUpper method
  704. //Hash using new ToUpper method
  705. //If they are not the same add to the m_keyHash structure
  706. HRESULT hRes = 0;
  707. wchar_t wszOldHash[MAX_HASH_LEN+1];
  708. wchar_t wszNewHash[MAX_HASH_LEN+1];
  709. hRes = OldHash(wszName, wszOldHash);
  710. if (SUCCEEDED(hRes))
  711. hRes = NewHash(wszName, wszNewHash);
  712. if (SUCCEEDED(hRes))
  713. {
  714. if (wcscmp(wszOldHash, wszNewHash) != 0)
  715. {
  716. DEBUGTRACE((LOG_REPDRV, "Hash difference detected for: %S, %S, %S\n", wszName, wszOldHash, wszNewHash));
  717. //2 The hashes are different! We need to process them
  718. hRes = m_keyHash.AddStrings(wszOldHash, wszNewHash);
  719. *pDifferent = true;
  720. }
  721. }
  722. return hRes;
  723. }
  724. //=====================================================================
  725. //
  726. // CLocalizationUpgrade::ProcessFullPath
  727. //
  728. // Description:
  729. // Takes an key root instance path and checks that the full hash using
  730. // old and new methods match. If they are different it records for later
  731. // usage
  732. //
  733. // Parameters:
  734. // wszOldPath - Instance string c:\windows\...\NS_<hash>\KI_<hash>\I_hash.X.Y.Z
  735. //
  736. //=====================================================================
  737. HRESULT CLocalizationUpgrade::ProcessFullPath(CFileName &wszOldFullPath, const wchar_t *wszNewNamespaceHash)
  738. {
  739. //Hash using old ToUpper method
  740. //Hash using new ToUpper method
  741. //If they are not the same add to the m_pathHash structure
  742. HRESULT hRes = 0;
  743. bool bChanged = false;
  744. wchar_t wszOldHash[MAX_HASH_LEN+1];
  745. wchar_t wszNewHash[MAX_HASH_LEN+1];
  746. CFileName wsOldShortPath;
  747. CFileName wszNewFullPath;
  748. CFileName wszNewShortPath;
  749. if ((wsOldShortPath == NULL) || (wszNewFullPath == NULL) || (wszNewShortPath == NULL))
  750. return WBEM_E_OUT_OF_MEMORY;
  751. //Need to fixup the old path with new hashes before we continue!
  752. //Fixup requires short path to work and we have full path currently!
  753. StringCchCopyW(wsOldShortPath, wsOldShortPath.Length(), wszOldFullPath+g_Glob.GetRootDirLen()+1);
  754. hRes = FixupIndex(wsOldShortPath, wszNewShortPath, bChanged);
  755. if (FAILED(hRes) || !bChanged)
  756. return hRes;
  757. //Copy the new namespace hash into the string to be sure!
  758. wmemcpy(wszNewShortPath+3, wszNewNamespaceHash, 32);
  759. //Now we need to add the FULL path to the start of each path before we hash it. Kind
  760. //of crazy, but that's the way it was done!
  761. StringCchCopyW(wszNewFullPath, wszNewFullPath.Length(), g_Glob.GetRootDir());
  762. StringCchCatW(wszNewFullPath, wszNewFullPath.Length(), L"\\");
  763. StringCchCatW(wszNewFullPath, wszNewFullPath.Length(), wszNewShortPath);
  764. hRes = OldHash(wszOldFullPath, wszOldHash);
  765. if (FAILED(hRes))
  766. return hRes;
  767. hRes = NewHash(wszNewFullPath, wszNewHash);
  768. if (FAILED(hRes))
  769. return hRes;
  770. if (wcscmp(wszOldHash, wszNewHash) != 0)
  771. {
  772. //2 The hashes are different! We need to process them
  773. DEBUGTRACE((LOG_REPDRV, "Path difference detected for: %S, %S, %S, %S\n", wszOldFullPath, wszNewShortPath, wszOldHash, wszNewHash));
  774. hRes = m_pathHash.AddStrings(wszOldHash, wszNewHash);
  775. }
  776. return hRes;
  777. }
  778. //=====================================================================
  779. //
  780. // CLocalizationUpgrade::OldHash
  781. //
  782. // Description:
  783. // Generates a 32 character hash of the given string. It does it in
  784. // the OLD way which is case screwed up
  785. //
  786. // Parameters:
  787. // wszName Name to hash
  788. // wszHash Returns the hash of the name
  789. //
  790. //=====================================================================
  791. 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'};
  792. HRESULT CLocalizationUpgrade::OldHash(const wchar_t *wszName, wchar_t *wszHash)
  793. {
  794. DWORD dwBufferSize = wcslen(wszName)*2+2;
  795. LPWSTR wszBuffer = (WCHAR*)TempAlloc(dwBufferSize);
  796. if (wszBuffer == NULL)
  797. return WBEM_E_OUT_OF_MEMORY;
  798. CTempFreeMe vdm(wszBuffer, dwBufferSize);
  799. OldStringToUpper(wszBuffer, wszName);
  800. BYTE RawHash[16];
  801. MD5::Transform((void*)wszBuffer, wcslen(wszBuffer)*2, RawHash);
  802. WCHAR* pwc = wszHash;
  803. for(int i = 0; i < 16; i++)
  804. {
  805. *(pwc++) = g_HexDigit[RawHash[i]/16];
  806. *(pwc++) = g_HexDigit[RawHash[i]%16];
  807. }
  808. *pwc = 0;
  809. return WBEM_NO_ERROR;
  810. }
  811. //=====================================================================
  812. //
  813. // CLocalizationUpgrade::NewHash
  814. //
  815. // Description:
  816. // Hashes the given name using the new locale invariant specific
  817. // conversion to upper case
  818. //
  819. // Parameters:
  820. // wszName - Name to hash
  821. // wszHash - Returns hash
  822. //
  823. //=====================================================================
  824. HRESULT CLocalizationUpgrade::NewHash(const wchar_t *wszName, wchar_t *wszHash)
  825. {
  826. DWORD dwBufferSize = wcslen(wszName)*2+2;
  827. LPWSTR wszBuffer = (WCHAR*)TempAlloc(dwBufferSize);
  828. if (wszBuffer == NULL)
  829. return WBEM_E_OUT_OF_MEMORY;
  830. CTempFreeMe vdm(wszBuffer, dwBufferSize);
  831. NewStringToUpper(wszBuffer, wszName);
  832. BYTE RawHash[16];
  833. MD5::Transform((void*)wszBuffer, wcslen(wszBuffer)*2, RawHash);
  834. WCHAR* pwc = wszHash;
  835. for(int i = 0; i < 16; i++)
  836. {
  837. *(pwc++) = g_HexDigit[RawHash[i]/16];
  838. *(pwc++) = g_HexDigit[RawHash[i]%16];
  839. }
  840. *pwc = 0;
  841. return WBEM_NO_ERROR;
  842. }
  843. //=====================================================================
  844. //
  845. // CLocalizationUpgrade::FixupBTree
  846. //
  847. // Description:
  848. // Method that bootstraps the fixup of the BTree by iterating through
  849. // all namespaces
  850. //
  851. // Parameters:
  852. //
  853. //=====================================================================
  854. HRESULT CLocalizationUpgrade::FixupBTree()
  855. {
  856. HRESULT hRes = NO_ERROR;
  857. //Lets iterate through the namespace list and iterate through everything in that namespace
  858. //fixing things up and fixing things as we go
  859. for (unsigned int i = 0; i != m_namespaces.Size(); i++)
  860. {
  861. hRes = FixupNamespace(m_namespaces[i]->m_wsz2);
  862. if (FAILED(hRes))
  863. break;
  864. }
  865. return hRes;
  866. }
  867. //=====================================================================
  868. //
  869. // CLocalizationUpgrade::FixupNamespace
  870. //
  871. // Description:
  872. // Enumerates all items within the namespace, andcalls into method to
  873. // do all the work
  874. //
  875. // Parameters:
  876. // wszNamespace - in the format of a FULL namespace path... c:\windows\...\NS_<hash>
  877. //
  878. //=====================================================================
  879. HRESULT CLocalizationUpgrade::FixupNamespace(const wchar_t *wszNamespace)
  880. {
  881. HRESULT hRes = NO_ERROR;
  882. long lRes = NO_ERROR;
  883. CFileName indexEntry;
  884. if (indexEntry == NULL)
  885. return WBEM_E_OUT_OF_MEMORY;
  886. CFileName newEntry;
  887. if (newEntry == NULL)
  888. return WBEM_E_OUT_OF_MEMORY;
  889. bool bChanged = false;
  890. LPVOID pEnumHandle = NULL;
  891. lRes = g_Glob.m_FileCache.IndexEnumerationBegin(wszNamespace, &pEnumHandle);
  892. if (lRes == ERROR_SUCCESS)
  893. {
  894. while(1)
  895. {
  896. lRes = g_Glob.m_FileCache.IndexEnumerationNext(pEnumHandle, indexEntry, true);
  897. if (lRes == ERROR_NO_MORE_FILES)
  898. {
  899. lRes = ERROR_SUCCESS;
  900. break;
  901. }
  902. else if (lRes)
  903. break;
  904. bChanged = false;
  905. hRes = FixupIndex(indexEntry, newEntry, bChanged);
  906. if (FAILED(hRes))
  907. break;
  908. if (bChanged)
  909. {
  910. hRes = WriteIndex(indexEntry, newEntry);
  911. if (FAILED(hRes))
  912. break;
  913. }
  914. if (IsInstanceReference(newEntry))
  915. {
  916. hRes = FixupIndexReferenceBlob(newEntry);
  917. if (FAILED(hRes))
  918. break;
  919. }
  920. if (IsKeyRootInstancePath(newEntry))
  921. {
  922. hRes = FixupInstanceBlob(newEntry);
  923. if (FAILED(hRes))
  924. break;
  925. }
  926. }
  927. g_Glob.m_FileCache.IndexEnumerationEnd(pEnumHandle);
  928. }
  929. else
  930. {
  931. if (lRes == ERROR_FILE_NOT_FOUND)
  932. lRes = ERROR_SUCCESS;
  933. }
  934. if (lRes)
  935. hRes = A51TranslateErrorCode(lRes);
  936. return hRes;
  937. }
  938. //=====================================================================
  939. //
  940. // CLocalizationUpgrade::FixupIndex
  941. //
  942. // Description:
  943. // Fixes up the entry with all the new hashes we detected and returns the new entry
  944. //
  945. // Parameters:
  946. // oldIndexEntry - Entry to fix up, in format of NS_<hash>\....
  947. // newIndexEntry - oldIndexEntry with all hashes substituted to new entries
  948. // bChanged - Returns a flag to say if it was changed
  949. //
  950. //=====================================================================
  951. HRESULT CLocalizationUpgrade::FixupIndex(CFileName &oldIndexEntry, CFileName &newIndexEntry, bool &bChanged)
  952. {
  953. //Need to check each hash to see if it has a problem. To do this we can search for each '_'
  954. //character and check the hash after that entry. If we see a match, we need to correct it.
  955. //Any changes we detect need to be written back, then we need to delete the main entry.
  956. //If we write it back, we need to check an entry doesn't already exist because if it does we
  957. //need to discard this entry, and if we have an associated object we need to delete it, then log
  958. //an event log entry to describe what we did!
  959. CFileName scratchIndex;
  960. if (scratchIndex == NULL)
  961. return WBEM_E_OUT_OF_MEMORY;
  962. StringCchCopyW(scratchIndex, scratchIndex.Length(), oldIndexEntry);
  963. StringCchCopyW(newIndexEntry, newIndexEntry.Length(), oldIndexEntry);
  964. wchar_t *wszSection = wcstok(scratchIndex, L"_");;
  965. wchar_t *wszHash = wcstok(NULL, L"\\.");
  966. wchar_t *pNewHash = NULL;
  967. bool bInstanceReferenceDetected = false;
  968. bool bUsePathHash = false;
  969. HRESULT hRes = 0;
  970. while (wszHash != NULL)
  971. {
  972. if (!bInstanceReferenceDetected)
  973. {
  974. if (wcsncmp(wszSection, A51_INSTREF_DIR_PREFIX, 2) == 0)
  975. {
  976. bInstanceReferenceDetected = true;
  977. }
  978. }
  979. else if (bInstanceReferenceDetected && (wszSection != NULL))
  980. {
  981. if (wcsncmp(wszSection, A51_REF_FILE_PREFIX, 1) == 0)
  982. {
  983. bUsePathHash = true;
  984. }
  985. }
  986. //Now the wszCursor points to just the hash, so we can check the hash out!
  987. if (bUsePathHash)
  988. {
  989. hRes = GetNewPath(wszHash, &pNewHash);
  990. bUsePathHash = false;
  991. }
  992. else
  993. {
  994. hRes = GetNewHash(wszHash, &pNewHash);
  995. }
  996. if (hRes == WBEM_NO_ERROR)
  997. {
  998. if ((m_pass != 3) && (wcsncmp(wszSection, L"NS_", 3) == 0))
  999. {
  1000. //Do nothing!
  1001. }
  1002. else
  1003. {
  1004. //We have a difference
  1005. bChanged = true;
  1006. wmemcpy(((wchar_t*)newIndexEntry)+(wszHash-((wchar_t*)scratchIndex)), pNewHash, MAX_HASH_LEN);
  1007. }
  1008. }
  1009. else if (hRes == WBEM_E_NOT_FOUND)
  1010. hRes = WBEM_NO_ERROR;
  1011. //Search for next extry
  1012. wszSection = wcstok(NULL, L"_");
  1013. if (wszSection)
  1014. wszHash = wcstok(NULL, L"\\.");
  1015. else
  1016. wszHash = NULL;
  1017. }
  1018. if (bChanged)
  1019. {
  1020. DEBUGTRACE((LOG_REPDRV, "Fixed up index: %S, %S\n", (const wchar_t *)oldIndexEntry, (const wchar_t *)newIndexEntry));
  1021. }
  1022. return hRes;
  1023. }
  1024. //=====================================================================
  1025. //
  1026. // CLocalizationUpgrade::GetNewHash
  1027. //
  1028. // Description:
  1029. // Given an old hash, returns a new hash if one exists, otherwise WBEM_E_NOT_FOUND
  1030. //
  1031. // Parameters:
  1032. // wszOldHash - Old hash string to search for - 32 character string
  1033. // pNewHash - pointer to a 32-character string of new entry if one exists, NULL otherwise
  1034. //
  1035. // Return Code
  1036. // WBEM_E_NOT_FOUND if a HASH is not found
  1037. //
  1038. //=====================================================================
  1039. HRESULT CLocalizationUpgrade::GetNewHash(const wchar_t *wszOldHash, wchar_t **pNewHash)
  1040. {
  1041. return m_keyHash.FindStrings(wszOldHash, pNewHash);
  1042. }
  1043. //=====================================================================
  1044. //
  1045. // CLocalizationUpgrade::GetNewPath
  1046. //
  1047. // Description:
  1048. // Given an old hash, returns a new hash if one exists, otherwise WBEM_E_NOT_FOUND
  1049. //
  1050. // Parameters:
  1051. // wszOldHash - Old hash string to search for - 32 character string
  1052. // pNewHash - pointer to a 32-character string of new entry if one exists, NULL otherwise
  1053. //
  1054. // Return Code
  1055. // WBEM_E_NOT_FOUND if a HASH is not found
  1056. //
  1057. //=====================================================================
  1058. HRESULT CLocalizationUpgrade::GetNewPath(const wchar_t *wszOldHash, wchar_t **pNewHash)
  1059. {
  1060. return m_pathHash.FindStrings(wszOldHash, pNewHash);
  1061. }
  1062. //=====================================================================
  1063. //
  1064. // CLocalizationUpgrade::WriteIndex
  1065. //
  1066. // Description:
  1067. // Checks if the new index exists. If not writes the new entry and deletes the old one. If the link points to an
  1068. // object then it deletes that, unless this is the instance class link object link.
  1069. // If there is a conflict calls into the method to deal with that.
  1070. //
  1071. // Parameters:
  1072. // wszOldIndex - old path of format NS_<hash>\...
  1073. // wszNewIndex - new path of format NS_<hash>\...
  1074. //
  1075. //=====================================================================
  1076. HRESULT CLocalizationUpgrade::WriteIndex(CFileName &wszOldIndex, const wchar_t *wszNewIndex)
  1077. {
  1078. //We need to determine if we have a collision before we write the index. Therefore we
  1079. //need to strip off the X.Y.Z entry if it exists and retrieve it. If it exists then we have
  1080. //to delete our index and delete the associated object
  1081. CFileName wszScratchIndex;
  1082. if (wszScratchIndex == NULL)
  1083. return WBEM_E_OUT_OF_MEMORY;
  1084. StringCchCopyW(wszScratchIndex, wszScratchIndex.Length(), wszNewIndex);
  1085. wchar_t *wszObjectLocation = NULL;
  1086. if (wcstok(wszScratchIndex, L".") != NULL)
  1087. wszObjectLocation = wcstok(NULL, L"");
  1088. CFileName wszFullPath;
  1089. if (wszFullPath == NULL)
  1090. return WBEM_E_OUT_OF_MEMORY;
  1091. StringCchCopyW(wszFullPath, wszFullPath.Length(), g_Glob.GetRootDir());
  1092. StringCchCatW(wszFullPath, wszFullPath.Length(), L"\\");
  1093. StringCchCatW(wszFullPath, wszFullPath.Length(), wszScratchIndex);
  1094. HRESULT hRes = IndexExists(wszFullPath);
  1095. if (hRes == WBEM_NO_ERROR)
  1096. {
  1097. //2 We have a conflict, therefore we need to delete the OLD entry!
  1098. long lRes = 0;
  1099. DEBUGTRACE((LOG_REPDRV, "Index Collision detected: %S\n", (const wchar_t *)wszOldIndex));
  1100. hRes = FixupIndexConflict(wszOldIndex);
  1101. }
  1102. else if (hRes == WBEM_E_NOT_FOUND)
  1103. {
  1104. hRes = WBEM_NO_ERROR;
  1105. //2 Write the new index
  1106. if (wszObjectLocation)
  1107. {
  1108. //Put the .X.Y.Z on the end!
  1109. StringCchCatW(wszFullPath, wszFullPath.Length(), L".");
  1110. StringCchCatW(wszFullPath, wszFullPath.Length(), wszObjectLocation);
  1111. }
  1112. long lRes = g_Glob.m_FileCache.WriteLink(wszFullPath);
  1113. if(lRes != ERROR_SUCCESS)
  1114. hRes = A51TranslateErrorCode(lRes);
  1115. else
  1116. {
  1117. //2 Delete the old link
  1118. //strip off .X.Y.Z off old entry
  1119. StringCchCopyW(wszScratchIndex, wszScratchIndex.Length(), wszOldIndex);
  1120. wcstok(wszScratchIndex, L".");
  1121. //Build path
  1122. StringCchCopyW(wszFullPath, wszFullPath.Length(), g_Glob.GetRootDir());
  1123. StringCchCatW(wszFullPath, wszFullPath.Length(), L"\\");
  1124. StringCchCatW(wszFullPath, wszFullPath.Length(), wszScratchIndex);
  1125. //Do delete
  1126. lRes = g_Glob.m_FileCache.DeleteLink(wszFullPath);
  1127. if(lRes != ERROR_SUCCESS)
  1128. hRes = A51TranslateErrorCode(lRes);
  1129. }
  1130. }
  1131. return hRes;
  1132. }
  1133. //=====================================================================
  1134. //
  1135. // CLocalizationUpgrade::WriteClassIndex
  1136. //
  1137. // Description:
  1138. // Checks if the new index exists. If not writes the new entry and deletes the old one. If the link points to an
  1139. // object then it deletes that, unless this is the instance class link object link.
  1140. // If there is a conflict calls into the method to deal with that.
  1141. //
  1142. // Parameters:
  1143. // wszOldIndex - old path of format NS_<hash>\...
  1144. // wszNewIndex - new path of format NS_<hash>\...
  1145. //
  1146. //=====================================================================
  1147. HRESULT CLocalizationUpgrade::WriteClassIndex(CNamespaceHandle *pNs, CFileName &wszOldIndex, const wchar_t *wszNewIndex, bool *pClassDeleted)
  1148. {
  1149. //We need to re-read the old index because we don't have the .X.Y.X on the end.
  1150. HRESULT hRes = g_Glob.m_FileCache.ReadNextIndex(wszOldIndex, wszOldIndex);
  1151. if (FAILED(hRes))
  1152. return hRes;
  1153. //Save off and remove the .X.Y.Z
  1154. wchar_t *wszObjectLocation = NULL;
  1155. if (wcstok(wszOldIndex, L".") != NULL)
  1156. wszObjectLocation = wcstok(NULL, L"");
  1157. //We need to determine if we have a collision before we write the index.
  1158. //If it exists then we have
  1159. //to delete our index and delete the associated object
  1160. CFileName wszFullPath;
  1161. if (wszFullPath == NULL)
  1162. return WBEM_E_OUT_OF_MEMORY;
  1163. StringCchCopyW(wszFullPath, wszFullPath.Length(), g_Glob.GetRootDir());
  1164. StringCchCatW(wszFullPath, wszFullPath.Length(), L"\\");
  1165. StringCchCatW(wszFullPath, wszFullPath.Length(), wszNewIndex);
  1166. hRes = IndexExists(wszFullPath);
  1167. if (hRes == WBEM_NO_ERROR)
  1168. {
  1169. //2 We have a conflict, therefore we need to delete the old class!
  1170. DEBUGTRACE((LOG_REPDRV, "Class Index Collision detected: %S\n", (const wchar_t *)wszOldIndex));
  1171. *pClassDeleted = true;
  1172. hRes = DeleteClass(pNs, wszOldIndex);
  1173. }
  1174. else if (hRes == WBEM_E_NOT_FOUND)
  1175. {
  1176. hRes = WBEM_NO_ERROR;
  1177. //2 Write the new index
  1178. if (wszObjectLocation)
  1179. {
  1180. //Put the .X.Y.Z on the end!
  1181. StringCchCatW(wszFullPath, wszFullPath.Length(), L".");
  1182. StringCchCatW(wszFullPath, wszFullPath.Length(), wszObjectLocation);
  1183. }
  1184. long lRes = g_Glob.m_FileCache.WriteLink(wszFullPath);
  1185. if(lRes != ERROR_SUCCESS)
  1186. hRes = A51TranslateErrorCode(lRes);
  1187. else
  1188. {
  1189. //2 Delete the old link
  1190. //Build path
  1191. StringCchCopyW(wszFullPath, wszFullPath.Length(), g_Glob.GetRootDir());
  1192. StringCchCatW(wszFullPath, wszFullPath.Length(), L"\\");
  1193. StringCchCatW(wszFullPath, wszFullPath.Length(), wszOldIndex);
  1194. //Do delete
  1195. lRes = g_Glob.m_FileCache.DeleteLink(wszFullPath);
  1196. if(lRes != ERROR_SUCCESS)
  1197. hRes = A51TranslateErrorCode(lRes);
  1198. }
  1199. }
  1200. return hRes;
  1201. }
  1202. //=====================================================================
  1203. //
  1204. // CLocalizationUpgrade::IndexExists
  1205. //
  1206. // Description:
  1207. // Checks to see if a specific index exists. Returns WBEM_E_NOT_FOUND if not, or WBEM_NO_ERROR if it
  1208. // does.
  1209. //
  1210. // Parameters:
  1211. // wszIndex - full path of index to find - c:\windows\...\ns_<>\....
  1212. //
  1213. // Returns:
  1214. // WBEM_E_NOT_FOUND if index does not exist
  1215. // WBEM_NO_ERROR if it exists.
  1216. //
  1217. //=====================================================================
  1218. HRESULT CLocalizationUpgrade::IndexExists(const wchar_t *wszIndex)
  1219. {
  1220. HRESULT hRes = NO_ERROR;
  1221. long lRes = NO_ERROR;
  1222. CFileName indexEntry;
  1223. if (indexEntry == NULL)
  1224. return WBEM_E_OUT_OF_MEMORY;
  1225. LPVOID pEnumHandle = NULL;
  1226. lRes = g_Glob.m_FileCache.IndexEnumerationBegin(wszIndex, &pEnumHandle);
  1227. if (lRes == ERROR_SUCCESS)
  1228. {
  1229. lRes = g_Glob.m_FileCache.IndexEnumerationNext(pEnumHandle, indexEntry, true);
  1230. g_Glob.m_FileCache.IndexEnumerationEnd(pEnumHandle);
  1231. }
  1232. if (lRes)
  1233. hRes = A51TranslateErrorCode(lRes);
  1234. //make sure index we retrieved was from this index
  1235. if (SUCCEEDED(hRes))
  1236. if (wcsncmp(wszIndex+g_Glob.GetRootDirLen()+1, indexEntry, wcslen(wszIndex+g_Glob.GetRootDirLen()+1)) != 0)
  1237. hRes = WBEM_E_NOT_FOUND;
  1238. return hRes;
  1239. }
  1240. //=====================================================================
  1241. //
  1242. // CLocalizationUpgrade::ProcessNamespaceCollisions
  1243. //
  1244. // Description:
  1245. // Searches through the namespace list for collisions. If one exists then we delete the namespace
  1246. // recursively
  1247. //
  1248. // Parameters:
  1249. //
  1250. //=====================================================================
  1251. HRESULT CLocalizationUpgrade::ProcessNamespaceCollisions()
  1252. {
  1253. HRESULT hRes = NO_ERROR;
  1254. wchar_t thisNamespace[MAX_HASH_LEN+1];
  1255. wchar_t thatNamespace[MAX_HASH_LEN+1];
  1256. bool bDeletedSomething = false;
  1257. //Lets iterate through the namespace list and calculate the hash.
  1258. //Then we will itterate through the rest of the namespace list and check the
  1259. //hash with that one. If we have a collision, we need to delete it!
  1260. do
  1261. {
  1262. bDeletedSomething = false;
  1263. for (int i = 0; i != m_namespaces.Size(); i++)
  1264. {
  1265. //Hash this entry
  1266. hRes = NewHash(m_namespaces[i]->m_wsz1, thisNamespace);
  1267. if (FAILED(hRes))
  1268. break;
  1269. for (int j = (i+1); j < m_namespaces.Size(); j++)
  1270. {
  1271. //Hash this entry
  1272. hRes = NewHash(m_namespaces[j]->m_wsz1, thatNamespace);
  1273. if (FAILED(hRes))
  1274. break;
  1275. //If they are the same we need to delete this one
  1276. if (wcscmp(thisNamespace, thatNamespace) == 0)
  1277. {
  1278. //OK, so we have a collision! Lets deal with it!
  1279. hRes = DeleteNamespaceRecursive(m_namespaces[i]->m_wsz1);
  1280. if (FAILED(hRes))
  1281. break;
  1282. //We need to start again with the iteration as we may have deleted several entries
  1283. //from the array at this point
  1284. bDeletedSomething = true;
  1285. break;
  1286. }
  1287. }
  1288. if (FAILED(hRes) || bDeletedSomething)
  1289. break;
  1290. }
  1291. } while (SUCCEEDED(hRes) && bDeletedSomething);
  1292. return hRes;
  1293. }
  1294. //=====================================================================
  1295. //
  1296. // CLocalizationUpgrade::DeleteNamespaceRecursive
  1297. //
  1298. // Description:
  1299. // Searches through the namespace list for any which start with the one we passed in. Any matches are
  1300. // deleted
  1301. //
  1302. // Parameters:
  1303. // wszNamespace - namespace name in the format like root\default
  1304. //
  1305. //=====================================================================
  1306. HRESULT CLocalizationUpgrade::DeleteNamespaceRecursive(const wchar_t *wszNamespace)
  1307. {
  1308. LONG lRes = 0;
  1309. HRESULT hRes = NO_ERROR;
  1310. wchar_t *wszNamespaceHash = new wchar_t[MAX_HASH_LEN+1];
  1311. if (wszNamespaceHash == NULL)
  1312. return WBEM_E_OUT_OF_MEMORY;
  1313. hRes = OldHash(wszNamespace, wszNamespaceHash);
  1314. if (FAILED(hRes))
  1315. return hRes;
  1316. CFileName wszNamespacePath;
  1317. if (wszNamespacePath == NULL)
  1318. return WBEM_E_OUT_OF_MEMORY;
  1319. //Create the hashed path to the Key Root for the namespace
  1320. StringCchCopyW(wszNamespacePath, MAX_PATH, g_Glob.GetRootDir());
  1321. StringCchCatW(wszNamespacePath, MAX_PATH, L"\\NS_");
  1322. StringCchCatW(wszNamespacePath, MAX_PATH, wszNamespaceHash);
  1323. DEBUGTRACE((LOG_REPDRV, "Deleting namespace (recursive): %S, %S\n", wszNamespace, wszNamespacePath+g_Glob.GetRootDirLen()+1));
  1324. //2 Create a CNamespaceHandle so we can access objects in this namespace
  1325. CNamespaceHandle *pNs = new CNamespaceHandle(m_pControl, m_pRepository);
  1326. if (pNs == NULL)
  1327. return WBEM_E_OUT_OF_MEMORY;
  1328. CDeleteMe<CNamespaceHandle> cdm(pNs);
  1329. hRes = pNs->Initialize2(wszNamespace, wszNamespaceHash);
  1330. if (FAILED(hRes))
  1331. return hRes;
  1332. StringCchCatW(wszNamespacePath, MAX_PATH, L"\\" A51_KEYROOTINST_DIR_PREFIX);
  1333. StringCchCatW(wszNamespacePath, MAX_PATH, m_namespaceClassHash);
  1334. StringCchCatW(wszNamespacePath, MAX_PATH, L"\\" A51_INSTDEF_FILE_PREFIX);
  1335. //2 Enumerate all the child namespaces
  1336. LPVOID pEnumHandle = NULL;
  1337. lRes = g_Glob.m_FileCache.ObjectEnumerationBegin(wszNamespacePath, &pEnumHandle);
  1338. if (lRes == ERROR_SUCCESS)
  1339. {
  1340. BYTE *pBlob = NULL;
  1341. DWORD dwSize = 0;
  1342. while(1)
  1343. {
  1344. lRes = g_Glob.m_FileCache.ObjectEnumerationNext(pEnumHandle, wszNamespacePath, &pBlob, &dwSize);
  1345. if (lRes == ERROR_NO_MORE_FILES)
  1346. {
  1347. lRes = ERROR_SUCCESS;
  1348. break;
  1349. }
  1350. else if (lRes)
  1351. break;
  1352. //Get the instance
  1353. _IWmiObject* pInstance = NULL;
  1354. hRes = pNs->FileToInstance(NULL, wszNamespacePath, pBlob, dwSize, &pInstance, true);
  1355. //Free the blob
  1356. g_Glob.m_FileCache.ObjectEnumerationFree(pEnumHandle, pBlob);
  1357. if (FAILED(hRes))
  1358. break;
  1359. CReleaseMe rm2(pInstance);
  1360. //Extract the string from the object
  1361. VARIANT vName;
  1362. VariantInit(&vName);
  1363. CClearMe cm(&vName);
  1364. hRes = pInstance->Get(L"Name", 0, &vName, NULL, NULL);
  1365. if(FAILED(hRes))
  1366. break;
  1367. if(V_VT(&vName) != VT_BSTR)
  1368. {
  1369. hRes = WBEM_E_INVALID_OBJECT;
  1370. break;
  1371. }
  1372. //Create the full namespace path
  1373. wchar_t *wszChildNamespacePath = new wchar_t[wcslen(wszNamespace)+1+wcslen(V_BSTR(&vName)) + 1];
  1374. if (wszChildNamespacePath == NULL)
  1375. {
  1376. hRes = WBEM_E_OUT_OF_MEMORY;
  1377. break;
  1378. }
  1379. CVectorDeleteMe<wchar_t> vdm(wszChildNamespacePath);
  1380. StringCchCopyW(wszChildNamespacePath, MAX_PATH, wszNamespace);
  1381. StringCchCatW(wszChildNamespacePath, MAX_PATH, L"\\");
  1382. StringCchCatW(wszChildNamespacePath, MAX_PATH, V_BSTR(&vName));
  1383. //2 Process all child namespaces in this namespace
  1384. hRes = DeleteNamespaceRecursive(wszChildNamespacePath);
  1385. if (FAILED(hRes))
  1386. break;
  1387. }
  1388. g_Glob.m_FileCache.ObjectEnumerationEnd(pEnumHandle);
  1389. }
  1390. else
  1391. {
  1392. if (lRes == ERROR_FILE_NOT_FOUND)
  1393. lRes = ERROR_SUCCESS;
  1394. }
  1395. if (lRes)
  1396. hRes = A51TranslateErrorCode(lRes);
  1397. if (SUCCEEDED(hRes))
  1398. {
  1399. StringCchCopyW(wszNamespacePath, MAX_PATH, g_Glob.GetRootDir());
  1400. StringCchCatW(wszNamespacePath, MAX_PATH, L"\\NS_");
  1401. StringCchCatW(wszNamespacePath, MAX_PATH, wszNamespaceHash);
  1402. hRes = DeleteNamespace(wszNamespace, wszNamespacePath);
  1403. }
  1404. //2 Remote namespace path
  1405. if (SUCCEEDED(hRes))
  1406. {
  1407. hRes = m_namespaces.RemoveString(wszNamespace);
  1408. //Small chance that we get NOT_FOUND if we have not done full enumeration yet!
  1409. if (hRes == WBEM_E_NOT_FOUND)
  1410. hRes = WBEM_NO_ERROR;
  1411. }
  1412. return hRes;
  1413. }
  1414. //=====================================================================
  1415. //
  1416. // CLocalizationUpgrade::DeleteNamespace
  1417. //
  1418. // Description:
  1419. // Deletes the specified namespace using the DeleteNode, then goes into the parent namespace and deletes
  1420. // the instance from that namespace
  1421. //
  1422. // Parameters:
  1423. // wszNamespaceName - namespace name in format root\default
  1424. // wszNamespaceHash - Full namespace hash in format c:\windows\...\NS_<hash>
  1425. //
  1426. //=====================================================================
  1427. HRESULT CLocalizationUpgrade::DeleteNamespace(const wchar_t *wszNamespaceName,const wchar_t *wszNamespaceHash)
  1428. {
  1429. HRESULT hRes = NO_ERROR;
  1430. LONG lRes = NO_ERROR;
  1431. DEBUGTRACE((LOG_REPDRV, "Deleting namespace: %S, %S\n", wszNamespaceName, wszNamespaceHash+g_Glob.GetRootDirLen()+1));
  1432. //2 Delete the actual namespace contents
  1433. lRes = g_Glob.m_FileCache.DeleteNode(wszNamespaceHash);
  1434. if (lRes != 0)
  1435. return A51TranslateErrorCode(lRes);
  1436. //2 Calculate parent namespace name
  1437. wchar_t *wszParentNamespaceName = new wchar_t[wcslen(wszNamespaceName)+1];
  1438. wchar_t *wszThisNamespaceName = NULL;
  1439. if (wszParentNamespaceName == NULL)
  1440. return WBEM_E_OUT_OF_MEMORY;
  1441. StringCchCopyW(wszParentNamespaceName, wcslen(wszNamespaceName)+1, wszNamespaceName);
  1442. for (int i = wcslen(wszParentNamespaceName) - 1; i != 0; i--)
  1443. {
  1444. if (wszParentNamespaceName[i] == L'\\')
  1445. {
  1446. wszParentNamespaceName[i] = L'\0';
  1447. wszThisNamespaceName = wszParentNamespaceName+i+1;
  1448. break;
  1449. }
  1450. }
  1451. //2 Calculate parent namespace hash
  1452. wchar_t wszParentNamespaceHash[MAX_HASH_LEN+1];
  1453. hRes = OldHash(wszParentNamespaceName, wszParentNamespaceHash);
  1454. if (FAILED(hRes))
  1455. return hRes;
  1456. //2Calculate this namespaces hash
  1457. wchar_t wszThisNamespaceHash[MAX_HASH_LEN+1];
  1458. hRes = OldHash(wszThisNamespaceName, wszThisNamespaceHash);
  1459. if (FAILED(hRes))
  1460. return hRes;
  1461. //2 Calculate __namespace class hash
  1462. wchar_t wszNamespaceClassHash[MAX_HASH_LEN+1];
  1463. hRes = OldHash(L"__namespace", wszNamespaceClassHash);
  1464. if (FAILED(hRes))
  1465. return hRes;
  1466. CFileName wszKI;
  1467. CFileName wszCI;
  1468. if ((wszKI == NULL) || (wszCI == NULL))
  1469. return WBEM_E_OUT_OF_MEMORY;
  1470. //2 Build KI instance path
  1471. StringCchCopyW(wszKI,wszKI.Length(), g_Glob.GetRootDir());
  1472. StringCchCatW(wszKI, wszKI.Length(), L"\\NS_");
  1473. StringCchCatW(wszKI, wszKI.Length(), wszParentNamespaceHash);
  1474. StringCchCopyW(wszCI, wszCI.Length(), wszKI);
  1475. StringCchCatW(wszKI, wszKI.Length(), L"\\KI_");
  1476. StringCchCatW(wszKI, wszKI.Length(), wszNamespaceClassHash);
  1477. StringCchCatW(wszKI, wszKI.Length(), L"\\I_");
  1478. StringCchCatW(wszKI, wszKI.Length(), wszThisNamespaceHash);
  1479. //2 Retrieve instance blob so we can get the class hash for this instance
  1480. wchar_t wszClassHash[MAX_HASH_LEN+1];
  1481. BYTE *pBuffer = NULL;
  1482. DWORD dwLen = 0;
  1483. lRes = g_Glob.m_FileCache.ReadObject(wszKI, &dwLen, &pBuffer, false);
  1484. if (lRes)
  1485. {
  1486. //If this object does not exist, then we have probably already deleted the parent namespace!
  1487. if (lRes == ERROR_FILE_NOT_FOUND)
  1488. lRes = 0;
  1489. return A51TranslateErrorCode(lRes);
  1490. }
  1491. StringCchCopyNW(wszClassHash, MAX_HASH_LEN+1, (wchar_t*)pBuffer, MAX_HASH_LEN);
  1492. TempFree(pBuffer, dwLen);
  1493. //2 Build the CI instance path
  1494. StringCchCatW(wszCI, wszCI.Length(), L"\\CI_");
  1495. StringCchCatW(wszCI, wszCI.Length(), wszClassHash);
  1496. StringCchCatW(wszCI, wszCI.Length(), L"\\IL_");
  1497. StringCchCatW(wszCI, wszCI.Length(), wszThisNamespaceHash);
  1498. //2 Delete the KI link and object
  1499. lRes = g_Glob.m_FileCache.DeleteObject(wszKI);
  1500. if (lRes)
  1501. return A51TranslateErrorCode(lRes);
  1502. //2Delete the CI link only
  1503. lRes = g_Glob.m_FileCache.DeleteLink(wszCI);
  1504. if (lRes)
  1505. return A51TranslateErrorCode(lRes);
  1506. //OK, now, in theory, we should really, if we were really good citizens, delete any references that could be in this object!
  1507. //However nothing too bad will happen if we don't, so we won't!
  1508. return hRes;
  1509. }
  1510. //=====================================================================
  1511. //
  1512. // CLocalizationUpgrade::FixupIndexConflict
  1513. //
  1514. // Description:
  1515. // Method is called if the old and new index exists. If the link is for a class definition, we have a lot more
  1516. // work to do, so call into the handling method. Otherwise we just delete the old index, and object
  1517. // if it exists. If it is a KI_ index then we do not delete the object because the CI index entry will
  1518. // delete it instead
  1519. //
  1520. // Parameters:
  1521. // wszOldIndex -- Index to update in format NS_<hash>\KI_<>\I_<>.X.Y.Z. It must have the
  1522. // X.Y.Z entry if one exists
  1523. //
  1524. //=====================================================================
  1525. HRESULT CLocalizationUpgrade::FixupIndexConflict(CFileName &wszOldIndex)
  1526. {
  1527. //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.
  1528. //If the class is derived from __namespace then we need to delete the namespace recursively as well
  1529. if (IsClassDefinitionPath(wszOldIndex))
  1530. {
  1531. DEBUGTRACE((LOG_REPDRV, "TRYING TO FIX UP A CLASS IN THE WRONG PLACE\n"));
  1532. _ASSERT(1, L"TRYING TO FIX UP A CLASS IN THE WRONG PLACE");
  1533. return WBEM_E_FAILED;
  1534. }
  1535. else
  1536. {
  1537. LONG lRes = 0;
  1538. //This is the simple case, we just have to delete the old link or object
  1539. CFileName wszFullPath;
  1540. if (wszFullPath == NULL)
  1541. return WBEM_E_OUT_OF_MEMORY;
  1542. StringCchCopyW(wszFullPath, wszFullPath.Length(), g_Glob.GetRootDir());
  1543. StringCchCatW(wszFullPath, wszFullPath.Length(), L"\\");
  1544. StringCchCatW(wszFullPath, wszFullPath.Length(), wszOldIndex);
  1545. //Strip off the .X.Y.Z entry if it exists
  1546. wchar_t *wszObjectLocation = wcstok(wszFullPath+g_Glob.GetRootDirLen()+1, L".");
  1547. if (wszObjectLocation)
  1548. wszObjectLocation = wcstok(NULL, L"");
  1549. if (wszObjectLocation && !IsKeyRootInstancePath(wszOldIndex))
  1550. lRes = g_Glob.m_FileCache.DeleteObject(wszFullPath);
  1551. else
  1552. lRes = g_Glob.m_FileCache.DeleteLink(wszFullPath);
  1553. return A51TranslateErrorCode(lRes);
  1554. }
  1555. }
  1556. //=====================================================================
  1557. //
  1558. // CLocalizationUpgrade::IsClassDefinitionPath
  1559. //
  1560. // Description:
  1561. // Checks the link to see if this is a class definition or not
  1562. //
  1563. // Parameters:
  1564. // wszPath - link in the format NS_<>\CD_<>, or something else
  1565. //
  1566. // Returns:
  1567. // true - link is a class definition
  1568. // false - is not one
  1569. //
  1570. //=====================================================================
  1571. bool CLocalizationUpgrade::IsClassDefinitionPath(const wchar_t *wszPath)
  1572. {
  1573. WCHAR* pDot = wcschr(wszPath, L'\\');
  1574. if(pDot == NULL)
  1575. return false;
  1576. pDot++;
  1577. if ((*pDot == L'C') && (*(pDot+1) == L'D')&& (*(pDot+2) == L'_'))
  1578. return true;
  1579. else
  1580. return false;
  1581. }
  1582. //=====================================================================
  1583. //
  1584. // CLocalizationUpgrade::IsKeyRootInstancePath
  1585. //
  1586. // Description:
  1587. // Returns if this is a key root instance entry
  1588. //
  1589. // Parameters:
  1590. // wszPath - index in format NS_<>\KI_<>\I_, or somthing like that
  1591. //
  1592. // Returns:
  1593. // true - if this is a KI_<>\I_<> entry
  1594. // false - otherwise
  1595. //
  1596. //=====================================================================
  1597. bool CLocalizationUpgrade::IsKeyRootInstancePath(const wchar_t *wszPath)
  1598. {
  1599. WCHAR* pDot = wcschr(wszPath, L'\\');
  1600. if(pDot == NULL)
  1601. return false;
  1602. pDot++;
  1603. pDot = wcschr(pDot, L'\\');
  1604. if(pDot == NULL)
  1605. return false;
  1606. pDot++;
  1607. if ((*pDot == L'I') && (*(pDot+1) == L'_'))
  1608. return true;
  1609. else
  1610. return false;
  1611. }
  1612. //=====================================================================
  1613. //
  1614. // CLocalizationUpgrade::IsInstanceReference
  1615. //
  1616. // Description:
  1617. // Returns if this is a instance reference entry
  1618. //
  1619. // Parameters:
  1620. // wszPath - index in format NS_<>\KI_<>\IR_<>\R, or somthing like that
  1621. //
  1622. // Returns:
  1623. // true - if this is a NS_<>\KI_<>\IR_<>\R entry
  1624. // false - otherwise
  1625. //
  1626. //=====================================================================
  1627. bool CLocalizationUpgrade::IsInstanceReference(const wchar_t *wszPath)
  1628. {
  1629. WCHAR* pDot = wcschr(wszPath, L'\\');
  1630. if(pDot == NULL)
  1631. return false;
  1632. pDot++;
  1633. pDot = wcschr(pDot, L'\\');
  1634. if(pDot == NULL)
  1635. return false;
  1636. pDot++;
  1637. pDot = wcschr(pDot, L'\\');
  1638. if(pDot == NULL)
  1639. return false;
  1640. pDot++;
  1641. if ((*pDot == L'R') && (*(pDot+1) == L'_'))
  1642. return true;
  1643. else
  1644. return false;
  1645. }
  1646. //=====================================================================
  1647. //
  1648. // CLocalizationUpgrade::DeleteClass
  1649. //
  1650. // Description:
  1651. // Recursively deletes the class definition, sub-classes and instances. If the instance is
  1652. // a namespace then we need to delete that also
  1653. //
  1654. // Parameters:
  1655. // wszClassDefinitionPath - short path of class definition (ns_...\CD_....X.Y.Z. XYZ is optional! We kill it!
  1656. //
  1657. //=====================================================================
  1658. HRESULT CLocalizationUpgrade::DeleteClass(CNamespaceHandle *pNs, CFileName &wszClassDefinitionPath)
  1659. {
  1660. HRESULT hRes =0;
  1661. LONG lRes = 0;
  1662. DEBUGTRACE((LOG_REPDRV, "Deleting Class: %S\n", wszClassDefinitionPath));
  1663. CFileName wszKeyRootClass;
  1664. if (wszKeyRootClass == NULL)
  1665. return WBEM_E_OUT_OF_MEMORY;
  1666. CFileName wszFullPath;
  1667. if (wszFullPath == NULL)
  1668. hRes = WBEM_E_OUT_OF_MEMORY;
  1669. wchar_t *wszParentClassHash = new wchar_t[MAX_HASH_LEN+1];
  1670. if (wszParentClassHash == NULL)
  1671. return WBEM_E_OUT_OF_MEMORY;
  1672. //Kill the .X.Y.Z on the end of the definition, in case it was passed in that way
  1673. wcstok((wchar_t*)wszClassDefinitionPath,L".");
  1674. StringCchCopyW(wszFullPath, wszFullPath.Length(), g_Glob.GetRootDir());
  1675. StringCchCatW(wszFullPath, wszFullPath.Length(), L"\\");
  1676. StringCchCatW(wszFullPath, wszFullPath.Length(), wszClassDefinitionPath);
  1677. hRes = DeleteChildClasses(pNs, wszClassDefinitionPath);
  1678. if (SUCCEEDED(hRes))
  1679. hRes = RetrieveKeyRootClass(wszClassDefinitionPath, wszKeyRootClass);
  1680. if (SUCCEEDED(hRes))
  1681. {
  1682. hRes = RetrieveParentClassHash(wszFullPath, wszParentClassHash);
  1683. if (hRes == WBEM_S_NO_MORE_DATA)
  1684. hRes = 0;
  1685. }
  1686. if (SUCCEEDED(hRes) && wcslen(wszKeyRootClass) > 0)
  1687. hRes = DeleteInstances(pNs, wszClassDefinitionPath, wszKeyRootClass);
  1688. if (SUCCEEDED(hRes))
  1689. {
  1690. //Need to build the full path
  1691. lRes = g_Glob.m_FileCache.DeleteObject(wszFullPath);
  1692. hRes = A51TranslateErrorCode(lRes);
  1693. }
  1694. if (SUCCEEDED(hRes))
  1695. hRes = DeleteClassRelationships(wszFullPath, wszParentClassHash);
  1696. return hRes;
  1697. }
  1698. //=====================================================================
  1699. //
  1700. // CLocalizationUpgrade::DeleteChildClasses
  1701. //
  1702. // Description:
  1703. // Enumerates child classes from a given parent class definition, and calls DeleteClass on each
  1704. //
  1705. // Parameters:
  1706. // wszParentClassDefinition - NS_<>\CD_<> of parent class
  1707. //
  1708. //=====================================================================
  1709. HRESULT CLocalizationUpgrade::DeleteChildClasses(CNamespaceHandle *pNs, const wchar_t *wszParentClassDefinition)
  1710. {
  1711. HRESULT hRes= 0;
  1712. unsigned long lRes = 0;
  1713. //Build up a string for this classes c:\...\NS_...\CR_...\C_ enumeration
  1714. CFileName wszChildClasses;
  1715. if (wszChildClasses == NULL)
  1716. return WBEM_E_OUT_OF_MEMORY;
  1717. CFileName wszClassDefinition;
  1718. if (wszClassDefinition == NULL)
  1719. return WBEM_E_OUT_OF_MEMORY;
  1720. StringCchCopyW(wszClassDefinition, wszClassDefinition.Length(), wszParentClassDefinition);
  1721. //Create full class definition path
  1722. StringCchCopyW(wszChildClasses, wszChildClasses.Length(), g_Glob.GetRootDir());
  1723. StringCchCatW(wszChildClasses, wszChildClasses.Length(), L"\\");
  1724. StringCchCatW(wszChildClasses, wszChildClasses.Length(), wszParentClassDefinition);
  1725. //change the CD_ into CR_
  1726. wszChildClasses[g_Glob.GetRootDirLen()+1+3+32+2] = L'R';
  1727. //Add the \C_ on the end
  1728. StringCchCatW(wszChildClasses, wszChildClasses.Length(), L"\\C_");
  1729. //Enumerate the child classes
  1730. LPVOID pEnumHandle = NULL;
  1731. lRes = g_Glob.m_FileCache.IndexEnumerationBegin(wszChildClasses, &pEnumHandle);
  1732. if (lRes == ERROR_SUCCESS)
  1733. {
  1734. while(1)
  1735. {
  1736. lRes = g_Glob.m_FileCache.IndexEnumerationNext(pEnumHandle, wszChildClasses, true);
  1737. if (lRes == ERROR_NO_MORE_FILES)
  1738. {
  1739. hRes = ERROR_SUCCESS;
  1740. break;
  1741. }
  1742. else if (lRes)
  1743. {
  1744. hRes = A51TranslateErrorCode(lRes);
  1745. break;
  1746. }
  1747. //Build a NS_...\CD_... from the NS_...\CR_...\C_... path, using last hash
  1748. StringCchCopyW(wszClassDefinition+wcslen(wszClassDefinition) - 32,
  1749. wszClassDefinition.Length() - wcslen(wszClassDefinition) + 32,
  1750. wszChildClasses + wcslen(wszChildClasses)-32);
  1751. //Delete all child classes
  1752. hRes = DeleteClass(pNs, wszClassDefinition);
  1753. if (FAILED(hRes))
  1754. break;
  1755. }
  1756. g_Glob.m_FileCache.IndexEnumerationEnd(pEnumHandle);
  1757. }
  1758. else
  1759. {
  1760. if (lRes == ERROR_FILE_NOT_FOUND)
  1761. lRes = ERROR_SUCCESS;
  1762. if (lRes)
  1763. hRes = A51TranslateErrorCode(lRes);
  1764. }
  1765. return hRes;
  1766. }
  1767. //=====================================================================
  1768. //
  1769. // CLocalizationUpgrade::DeleteInstances
  1770. //
  1771. // Description:
  1772. // Enumerates all instances for a specified class definition and calls DeleteInstance
  1773. //
  1774. // Parameters:
  1775. // wszClassDefinition - NS_<>\CD_<> of class whose instances are to be deleted
  1776. // wszKeyRootClass - hash of key root class in 32-character format
  1777. //
  1778. //=====================================================================
  1779. HRESULT CLocalizationUpgrade::DeleteInstances(CNamespaceHandle *pNs, const wchar_t *wszClassDefinition, CFileName &wszKeyRootClass)
  1780. {
  1781. LONG lRes = 0;
  1782. HRESULT hRes = 0;
  1783. //Need to enumerate all NS_\CI_<class defn hash>\IL_...
  1784. //for each, we need to deltete the instance
  1785. CFileName wszClassInstance;
  1786. if (wszClassInstance == NULL)
  1787. return WBEM_E_OUT_OF_MEMORY;
  1788. StringCchCopyW(wszClassInstance, wszClassInstance.Length(), g_Glob.GetRootDir());
  1789. StringCchCatW(wszClassInstance, wszClassInstance.Length(), L"\\");
  1790. StringCchCatW(wszClassInstance, wszClassInstance.Length(), wszClassDefinition);
  1791. wszClassInstance[g_Glob.GetRootDirLen() + 1+3+32+1+1] = L'I';
  1792. StringCchCatW(wszClassInstance, wszClassInstance.Length(), L"\\IL_");
  1793. //Enumerate the instances
  1794. LPVOID pEnumHandle = NULL;
  1795. lRes = g_Glob.m_FileCache.IndexEnumerationBegin(wszClassInstance, &pEnumHandle);
  1796. if (lRes == ERROR_SUCCESS)
  1797. {
  1798. while(1)
  1799. {
  1800. lRes = g_Glob.m_FileCache.IndexEnumerationNext(pEnumHandle, wszClassInstance, true);
  1801. if (lRes == ERROR_NO_MORE_FILES)
  1802. {
  1803. hRes = ERROR_SUCCESS;
  1804. break;
  1805. }
  1806. else if (lRes)
  1807. {
  1808. hRes = A51TranslateErrorCode(lRes);
  1809. break;
  1810. }
  1811. hRes = DeleteInstance(pNs, wszClassInstance, wszKeyRootClass);
  1812. if (FAILED(hRes))
  1813. break;
  1814. }
  1815. g_Glob.m_FileCache.IndexEnumerationEnd(pEnumHandle);
  1816. }
  1817. else
  1818. {
  1819. if (lRes == ERROR_FILE_NOT_FOUND)
  1820. lRes = ERROR_SUCCESS;
  1821. if (lRes)
  1822. hRes = A51TranslateErrorCode(lRes);
  1823. }
  1824. return hRes;
  1825. }
  1826. //=====================================================================
  1827. //
  1828. // CLocalizationUpgrade::DeleteInstance
  1829. //
  1830. // Description:
  1831. // Deletes the instance links for a given instance
  1832. //
  1833. // Parameters:
  1834. // wszClassInstanceLink - NS_<>\CI_<>\IL_<> format of instance to delete
  1835. // wszKeyRoot - Hash of key root class for this instance
  1836. //
  1837. //=====================================================================
  1838. HRESULT CLocalizationUpgrade::DeleteInstance(CNamespaceHandle *pNs, const wchar_t *wszClassInstanceLink, CFileName &wszKeyRoot)
  1839. {
  1840. HRESULT hRes = 0;
  1841. LONG lRes = 0;
  1842. //Remove .X.Y.Z from end of string if it exists
  1843. wcstok((wchar_t *)wszClassInstanceLink, L".");
  1844. DEBUGTRACE((LOG_REPDRV, "Deleting Instance: %S\n", wszClassInstanceLink));
  1845. if (wcscmp(wszKeyRoot, m_namespaceClassHash) == 0)
  1846. {
  1847. return DeleteInstanceAsNamespace(pNs, wszClassInstanceLink);
  1848. }
  1849. //build KI entry and delete the object
  1850. CFileName wszKI;
  1851. if (wszKI == NULL)
  1852. return NULL;
  1853. StringCchCopyW(wszKI, wszKI.Length(), g_Glob.GetRootDir());
  1854. StringCchCatW(wszKI, wszKI.Length(), L"\\");
  1855. StringCchCatNW(wszKI, wszKI.Length(), wszClassInstanceLink, 3+32);
  1856. StringCchCatW(wszKI, wszKI.Length(), L"\\KI_");
  1857. StringCchCatW(wszKI, wszKI.Length(), wszKeyRoot);
  1858. StringCchCatW(wszKI, wszKI.Length(), L"\\I_");
  1859. StringCchCatW(wszKI, wszKI.Length(), wszClassInstanceLink + wcslen(wszClassInstanceLink) - 32);
  1860. lRes = g_Glob.m_FileCache.DeleteObject(wszKI);
  1861. if (lRes)
  1862. return A51TranslateErrorCode(lRes);
  1863. //Build instance reference enumerator link
  1864. StringCchCopyW(wszKI, wszKI.Length(), g_Glob.GetRootDir());
  1865. StringCchCatW(wszKI, wszKI.Length(), L"\\");
  1866. StringCchCatNW(wszKI, wszKI.Length(), wszClassInstanceLink, 3+32);
  1867. StringCchCatW(wszKI, wszKI.Length(), L"\\KI_");
  1868. StringCchCatW(wszKI, wszKI.Length(), wszKeyRoot);
  1869. StringCchCatW(wszKI, wszKI.Length(), L"\\IR_");
  1870. StringCchCatW(wszKI, wszKI.Length(), wszClassInstanceLink + wcslen(wszClassInstanceLink) - 32);
  1871. StringCchCatW(wszKI, wszKI.Length(), L"\\R_");
  1872. hRes = DeleteInstanceReferences(wszKI);
  1873. if (SUCCEEDED(hRes))
  1874. {
  1875. //Now delete the class instance link
  1876. StringCchCopyW(wszKI, wszKI.Length(), g_Glob.GetRootDir());
  1877. StringCchCatW(wszKI, wszKI.Length(), L"\\");
  1878. StringCchCatW(wszKI, wszKI.Length(), wszClassInstanceLink);
  1879. lRes = g_Glob.m_FileCache.DeleteLink(wszKI);
  1880. if (lRes)
  1881. hRes = A51TranslateErrorCode(lRes);
  1882. }
  1883. return hRes;
  1884. }
  1885. //=====================================================================
  1886. //
  1887. // CLocalizationUpgrade::DeleteInstanceReferences
  1888. //
  1889. // Description:
  1890. // Enumerates the instance references for the given instance link and deletes the link and object
  1891. //
  1892. // Parameters:
  1893. // wszInstLink - key root instance link of references to be deleted in format NS_<>\KI_<>\I_<>
  1894. //
  1895. //=====================================================================
  1896. //NOTE: FULL LINK PASSED IN!
  1897. HRESULT CLocalizationUpgrade::DeleteInstanceReferences(CFileName &wszInstLink)
  1898. {
  1899. LONG lRes = 0;
  1900. CFileName wszFullPath;
  1901. if (wszFullPath == NULL)
  1902. return WBEM_E_OUT_OF_MEMORY;
  1903. StringCchCopyW(wszFullPath, wszFullPath.Length(), g_Glob.GetRootDir());
  1904. StringCchCatW(wszFullPath, wszFullPath.Length(), L"\\");
  1905. //Enumerate the instances
  1906. LPVOID pEnumHandle = NULL;
  1907. lRes = g_Glob.m_FileCache.IndexEnumerationBegin(wszInstLink, &pEnumHandle);
  1908. if (lRes == ERROR_SUCCESS)
  1909. {
  1910. while(1)
  1911. {
  1912. lRes = g_Glob.m_FileCache.IndexEnumerationNext(pEnumHandle, wszInstLink, true);
  1913. if (lRes == ERROR_NO_MORE_FILES)
  1914. {
  1915. lRes = ERROR_SUCCESS;
  1916. break;
  1917. }
  1918. else if (lRes)
  1919. {
  1920. break;
  1921. }
  1922. //Convert to a FULL path
  1923. StringCchCatW(wszFullPath+g_Glob.GetRootDirLen()+1, wszFullPath.Length()-g_Glob.GetRootDirLen()-1, wszInstLink);
  1924. lRes = g_Glob.m_FileCache.DeleteObject(wszFullPath);
  1925. if (lRes)
  1926. break;
  1927. }
  1928. g_Glob.m_FileCache.IndexEnumerationEnd(pEnumHandle);
  1929. }
  1930. else
  1931. {
  1932. if (lRes == ERROR_FILE_NOT_FOUND)
  1933. lRes = ERROR_SUCCESS;
  1934. }
  1935. return A51TranslateErrorCode(lRes);;
  1936. }
  1937. //=====================================================================
  1938. //
  1939. // CLocalizationUpgrade::DeleteClassRelationships
  1940. //
  1941. // Description:
  1942. // Deletes all class relationships, including parent/child and references
  1943. //
  1944. // Parameters:
  1945. // wszPath - Full path of class definition, c:\windows\...\NS_<>\CD_<>
  1946. //
  1947. //=====================================================================
  1948. HRESULT CLocalizationUpgrade::DeleteClassRelationships(CFileName &wszPath,
  1949. const wchar_t wszParentClassHash[MAX_HASH_LEN+1])
  1950. {
  1951. //Convert from the class definition to a class relationship path
  1952. CFileName wszCRLink;
  1953. if (wszCRLink == NULL)
  1954. return WBEM_E_OUT_OF_MEMORY;
  1955. StringCchCopyW(wszCRLink, wszCRLink.Length(), wszPath);
  1956. wszCRLink[g_Glob.GetRootDirLen()+1+3+32+1+1] = L'R';
  1957. HRESULT hRes = 0;
  1958. LONG lRes = 0;
  1959. CFileName wszFullPath;
  1960. if (wszFullPath == NULL)
  1961. return WBEM_E_OUT_OF_MEMORY;
  1962. StringCchCopyW(wszFullPath, wszFullPath.Length(), g_Glob.GetRootDir());
  1963. StringCchCatW(wszFullPath, wszFullPath.Length(), L"\\");
  1964. //Enumerate the instances
  1965. LPVOID pEnumHandle = NULL;
  1966. lRes = g_Glob.m_FileCache.IndexEnumerationBegin(wszCRLink, &pEnumHandle);
  1967. if (lRes == ERROR_SUCCESS)
  1968. {
  1969. while(1)
  1970. {
  1971. lRes = g_Glob.m_FileCache.IndexEnumerationNext(pEnumHandle, wszCRLink, true);
  1972. if (lRes == ERROR_NO_MORE_FILES)
  1973. {
  1974. lRes = ERROR_SUCCESS;
  1975. break;
  1976. }
  1977. else if (lRes)
  1978. {
  1979. break;
  1980. }
  1981. //Convert to a FULL path
  1982. StringCchCopyW(wszFullPath+g_Glob.GetRootDirLen()+1, wszFullPath.Length()-g_Glob.GetRootDirLen()-1, wszCRLink);
  1983. lRes = g_Glob.m_FileCache.DeleteLink(wszFullPath);
  1984. if (lRes)
  1985. break;
  1986. }
  1987. g_Glob.m_FileCache.IndexEnumerationEnd(pEnumHandle);
  1988. }
  1989. else
  1990. {
  1991. if (lRes == ERROR_FILE_NOT_FOUND)
  1992. lRes = ERROR_SUCCESS;
  1993. }
  1994. hRes = A51TranslateErrorCode(lRes);
  1995. if (SUCCEEDED(hRes))
  1996. {
  1997. //Now we need to delete our parent's relationship to us!
  1998. StringCchCopyW(wszCRLink, wszCRLink.Length(), wszPath);
  1999. wszCRLink[g_Glob.GetRootDirLen()+1+3+32+1+1] = L'R';
  2000. StringCchCopyW(wszCRLink+g_Glob.GetRootDirLen()+1+3+32+1+3, wszCRLink.Length()-g_Glob.GetRootDirLen()-1-3-32-1-3, wszParentClassHash);
  2001. StringCchCatW(wszCRLink, wszCRLink.Length(), L"\\C_");
  2002. StringCchCatW(wszCRLink, wszCRLink.Length(), wszPath+g_Glob.GetRootDirLen()+1+3+32+1+3);
  2003. lRes = g_Glob.m_FileCache.DeleteLink(wszCRLink);
  2004. hRes = A51TranslateErrorCode(lRes);
  2005. }
  2006. return hRes;
  2007. }
  2008. //=====================================================================
  2009. //
  2010. // CLocalizationUpgrade::RetrieveKeyRootClass
  2011. //
  2012. // Description:
  2013. // Searches for instances under KI_<> for all classes in the hierarchy chain for the specified class.
  2014. // This is a slower process because we have to retrieve each class blob and get the hash of the
  2015. // parent class
  2016. //
  2017. // Parameters:
  2018. // wszClassDefinitionPath - Path of class definition to retrieve key root class, NS_<>\CD_<>
  2019. // wszKeyRootClass - This is where we put the 32-character hash of the key root class
  2020. // or empty string if there is none!
  2021. //
  2022. //=====================================================================
  2023. HRESULT CLocalizationUpgrade::RetrieveKeyRootClass(CFileName &wszClassDefinitionPath, CFileName &wszKeyRootClass)
  2024. {
  2025. HRESULT hRes = 0;
  2026. LONG lRes = 0;
  2027. CFileName wszFullClassPath;
  2028. if (wszFullClassPath == NULL)
  2029. return WBEM_E_OUT_OF_MEMORY;
  2030. CFileName wszFullKIPath;
  2031. if (wszFullKIPath == NULL)
  2032. return WBEM_E_OUT_OF_MEMORY;
  2033. StringCchCopyW(wszFullClassPath, wszFullClassPath.Length(), g_Glob.GetRootDir());
  2034. StringCchCatW(wszFullClassPath, wszFullClassPath.Length(), L"\\");
  2035. StringCchCatW(wszFullClassPath, wszFullClassPath.Length(), wszClassDefinitionPath);
  2036. StringCchCopyW(wszFullKIPath, wszFullKIPath.Length(), g_Glob.GetRootDir());
  2037. StringCchCatW(wszFullKIPath, wszFullKIPath.Length(), L"\\");
  2038. StringCchCatW(wszFullKIPath, wszFullKIPath.Length(), wszClassDefinitionPath);
  2039. //convert the class definition to a instance definition
  2040. wszFullKIPath[g_Glob.GetRootDirLen()+1+3+32+1]=L'K';
  2041. wszFullKIPath[g_Glob.GetRootDirLen()+1+3+32+2]=L'I';
  2042. StringCchCatW(wszFullKIPath, wszFullKIPath.Length(), L"\\I_");
  2043. wszKeyRootClass[0] = L'\0';
  2044. do
  2045. {
  2046. //Check if we have any instances
  2047. hRes = IndexExists(wszFullKIPath);
  2048. if (SUCCEEDED(hRes))
  2049. {
  2050. //We have the entry we are looking for
  2051. StringCchCopyNW(wszKeyRootClass, wszKeyRootClass.Length(), wszFullKIPath+g_Glob.GetRootDirLen()+1+3+32+1+3, 32);
  2052. break;
  2053. }
  2054. else if (hRes != WBEM_E_NOT_FOUND)
  2055. {
  2056. break;
  2057. }
  2058. hRes = 0;
  2059. //Retrieve the class hash of the parent class
  2060. hRes = RetrieveParentClassHash(wszFullClassPath, wszFullKIPath + g_Glob.GetRootDirLen() + 1 + 3 + 32 + 1 + 3);
  2061. if (hRes == WBEM_S_NO_MORE_DATA)
  2062. {
  2063. hRes = 0;
  2064. break;
  2065. }
  2066. StringCchCatW(wszFullKIPath, wszFullKIPath.Length(), L"\\I_");
  2067. StringCchCopyNW(wszFullClassPath + g_Glob.GetRootDirLen() + 1 + 3 + 32 + 1 + 3,
  2068. wszFullClassPath.Length() - g_Glob.GetRootDirLen() - 1 - 3 - 32 - 1 - 3,
  2069. wszFullKIPath + g_Glob.GetRootDirLen() + 1 + 3 + 32 + 1 + 3,
  2070. 32);
  2071. if (FAILED(hRes))
  2072. break;
  2073. } while (1);
  2074. return hRes;
  2075. }
  2076. HRESULT CLocalizationUpgrade::RetrieveParentClassHash(CFileName &wszFullClassPath,
  2077. wchar_t wszParentClassHash[MAX_HASH_LEN+1])
  2078. {
  2079. LONG lRes = 0;
  2080. HRESULT hRes = 0;
  2081. //Retrieve the class hash of the parent class
  2082. BYTE *pBuffer = NULL;
  2083. DWORD dwLen = 0;
  2084. lRes = g_Glob.m_FileCache.ReadObject(wszFullClassPath, &dwLen, &pBuffer, true);
  2085. if (lRes == ERROR_FILE_NOT_FOUND)
  2086. {
  2087. //This is probably a class from the system namespace!
  2088. CFileName wszSysClassPath;
  2089. if (wszSysClassPath == NULL)
  2090. return WBEM_E_OUT_OF_MEMORY;
  2091. StringCchCopyW(wszSysClassPath, wszSysClassPath.Length(), wszFullClassPath);
  2092. wmemcpy(wszSysClassPath+g_Glob.GetRootDirLen()+1+3, m_systemNamespaceHash, 32);
  2093. lRes = g_Glob.m_FileCache.ReadObject(wszSysClassPath, &dwLen, &pBuffer, true);
  2094. if (lRes)
  2095. return A51TranslateErrorCode(lRes);
  2096. }
  2097. else if (lRes)
  2098. {
  2099. return A51TranslateErrorCode(lRes);
  2100. }
  2101. CTempFreeMe tfm(pBuffer, dwLen);
  2102. //Null terminate the class name - safe to update buffer as it is always bigger than
  2103. //just the name!
  2104. wchar_t *wszSuperclassName = (wchar_t*)(pBuffer+sizeof(DWORD));
  2105. wszSuperclassName[*(DWORD*)pBuffer] = L'\0';
  2106. //Now we need to validate that this parent is generated using the OldHash
  2107. //method and not NewHash!
  2108. wchar_t wszOldHash[MAX_HASH_LEN+1];
  2109. wchar_t wszNewHash[MAX_HASH_LEN+1];
  2110. hRes = OldHash(wszSuperclassName, wszOldHash);
  2111. if (FAILED(hRes))
  2112. return hRes;
  2113. hRes = NewHash(wszSuperclassName, wszNewHash);
  2114. if (FAILED(hRes))
  2115. return hRes;
  2116. if (wcsncmp(L"", wszSuperclassName, *((DWORD*)pBuffer)) == 0)
  2117. {
  2118. StringCchCopyW(wszParentClassHash, MAX_HASH_LEN+1, wszNewHash);
  2119. return WBEM_S_NO_MORE_DATA;
  2120. }
  2121. if (wcscmp(wszOldHash, wszNewHash) == 0)
  2122. {
  2123. //No difference so nothing extra to do!
  2124. StringCchCopyW(wszParentClassHash, MAX_HASH_LEN+1, wszNewHash);
  2125. return WBEM_NO_ERROR;
  2126. }
  2127. //There is a possibility of using either new or old, so we need to dig deeper!
  2128. CFileName wszParentClass;
  2129. if (wszParentClass == NULL)
  2130. return WBEM_E_OUT_OF_MEMORY;
  2131. StringCchCopyW(wszParentClass, wszParentClass.Length(), wszFullClassPath);
  2132. wmemcpy(wszParentClass+g_Glob.GetRootDirLen()+1+3+32+1+3, wszOldHash, 32);
  2133. hRes = IndexExists(wszParentClass);
  2134. if (hRes == WBEM_E_NOT_FOUND)
  2135. {
  2136. //Try with the other hash!
  2137. wmemcpy(wszParentClass+g_Glob.GetRootDirLen()+1+3+32+1+3, wszNewHash, 32);
  2138. hRes = IndexExists(wszParentClass);
  2139. if (hRes == WBEM_NO_ERROR)
  2140. StringCchCopyW(wszParentClassHash, MAX_HASH_LEN+1, wszNewHash);
  2141. }
  2142. else if (hRes == WBEM_NO_ERROR)
  2143. {
  2144. StringCchCopyW(wszParentClassHash, MAX_HASH_LEN+1, wszOldHash);
  2145. }
  2146. return hRes;
  2147. }
  2148. HRESULT CLocalizationUpgrade::DeleteInstanceAsNamespace(CNamespaceHandle *pNs,
  2149. const wchar_t *wszClassInstanceLink)
  2150. {
  2151. HRESULT hRes = NULL;
  2152. //Retrieve the instance and get the key from it
  2153. CFileName wszKIInstanceLink;
  2154. if (wszKIInstanceLink == NULL)
  2155. return WBEM_E_OUT_OF_MEMORY;
  2156. StringCchCopyW(wszKIInstanceLink, wszKIInstanceLink.Length(),g_Glob.GetRootDir());
  2157. StringCchCatW(wszKIInstanceLink, wszKIInstanceLink.Length(), L"\\");
  2158. StringCchCatNW(wszKIInstanceLink, wszKIInstanceLink.Length(), wszClassInstanceLink, 3+32);
  2159. StringCchCatW(wszKIInstanceLink, wszKIInstanceLink.Length(), L"\\KI_");
  2160. StringCchCatW(wszKIInstanceLink, wszKIInstanceLink.Length(), m_namespaceClassHash);
  2161. StringCchCatW(wszKIInstanceLink, wszKIInstanceLink.Length(), L"\\I_");
  2162. StringCchCatW(wszKIInstanceLink, wszKIInstanceLink.Length(), wszClassInstanceLink + wcslen(wszClassInstanceLink) - 32);
  2163. _IWmiObject *pInstance = NULL;
  2164. hRes = pNs->FileToInstance(NULL, wszKIInstanceLink, NULL, 0, &pInstance, true);
  2165. if (FAILED(hRes))
  2166. return hRes;
  2167. CReleaseMe rm2(pInstance);
  2168. //Extract the string from the object
  2169. VARIANT vName;
  2170. VariantInit(&vName);
  2171. CClearMe cm(&vName);
  2172. hRes = pInstance->Get(L"Name", 0, &vName, NULL, NULL);
  2173. if(FAILED(hRes))
  2174. return hRes;
  2175. if(V_VT(&vName) != VT_BSTR)
  2176. {
  2177. return WBEM_E_INVALID_OBJECT;
  2178. }
  2179. //Build the full namespace name
  2180. size_t len = wcslen(pNs->m_wsNamespace) + 1 + wcslen(V_BSTR(&vName)) + 1;
  2181. wchar_t *wszNamespaceName = new wchar_t[len];
  2182. if (wszNamespaceName == NULL)
  2183. return WBEM_E_OUT_OF_MEMORY;
  2184. StringCchCopyW(wszNamespaceName, len, pNs->m_wsNamespace);
  2185. StringCchCatW(wszNamespaceName, len, L"\\");
  2186. StringCchCatW(wszNamespaceName, len, V_BSTR(&vName));
  2187. return DeleteNamespaceRecursive(wszNamespaceName);
  2188. }
  2189. //=====================================================================
  2190. //
  2191. // CLocalizationUpgrade::FixupIndexReferenceBlob
  2192. //
  2193. // Description:
  2194. // Retrieves the instance reference blob and fixes up the entry in
  2195. // there, then writes it back.
  2196. //
  2197. // Parameters:
  2198. // wszReferenceIndex - Path to an index reference path: ns\ki\ir\r
  2199. //
  2200. //=====================================================================
  2201. HRESULT CLocalizationUpgrade::FixupIndexReferenceBlob(CFileName &wszReferenceIndex)
  2202. {
  2203. HRESULT hRes =0;
  2204. //Create full path name
  2205. CFileName wszFullPath;
  2206. if (wszFullPath == NULL)
  2207. return WBEM_E_OUT_OF_MEMORY;
  2208. StringCchCopyW(wszFullPath, wszFullPath.Length(), g_Glob.GetRootDir());
  2209. StringCchCatW(wszFullPath, wszFullPath.Length(), L"\\");
  2210. StringCchCatW(wszFullPath, wszFullPath.Length(), wszReferenceIndex);
  2211. //remove the .X.Y.Z as this would screw everything up - both reading and writing
  2212. wcstok(wszFullPath + g_Glob.GetRootDirLen(), L".");
  2213. //Retrieve the blob
  2214. LONG lRes = 0;
  2215. DWORD dwLen = 0;
  2216. BYTE *pBuffer = NULL;
  2217. lRes = g_Glob.m_FileCache.ReadObject(wszFullPath, &dwLen, &pBuffer);
  2218. if (lRes)
  2219. return A51TranslateErrorCode(lRes);
  2220. CTempFreeMe tfm(pBuffer, dwLen);
  2221. //Find the path
  2222. BYTE *pPath = pBuffer;
  2223. DWORD dwLen2;
  2224. memcpy(&dwLen2, pPath, sizeof(DWORD));
  2225. pPath += (sizeof(wchar_t)*dwLen2) + sizeof(DWORD);
  2226. memcpy(&dwLen2, pPath, sizeof(DWORD));
  2227. pPath += (sizeof(wchar_t)*dwLen2) + sizeof(DWORD);
  2228. memcpy(&dwLen2, pPath, sizeof(DWORD));
  2229. pPath += (sizeof(wchar_t)*dwLen2) + sizeof(DWORD);
  2230. memcpy(&dwLen2, pPath, sizeof(DWORD));
  2231. pPath += sizeof(DWORD) + sizeof(L'\\');
  2232. dwLen2 --;
  2233. //Extract the path
  2234. CFileName wszInstPath, wszNewInstPath;
  2235. if ((wszInstPath == NULL) || (wszNewInstPath == NULL))
  2236. return WBEM_E_OUT_OF_MEMORY;
  2237. StringCchCopyNW(wszInstPath, wszInstPath.Length(), (wchar_t*)pPath, dwLen2);
  2238. //fixup the path
  2239. bool bChanged = false;
  2240. hRes = FixupIndex(wszInstPath, wszNewInstPath, bChanged);
  2241. if (FAILED(hRes))
  2242. return hRes;
  2243. if (bChanged)
  2244. {
  2245. DEBUGTRACE((LOG_REPDRV, "Fixing up instance path in reference blob: %S\n", wszReferenceIndex));
  2246. //re-insert into the blob
  2247. wmemcpy((wchar_t*)pPath, wszNewInstPath, dwLen2);
  2248. //write back
  2249. lRes = g_Glob.m_FileCache.WriteObject(wszFullPath, NULL, dwLen, pBuffer);
  2250. if (lRes)
  2251. return A51TranslateErrorCode(lRes);
  2252. }
  2253. return 0;
  2254. }
  2255. //=====================================================================
  2256. //
  2257. // CLocalizationUpgrade::FixupInstanceBlob
  2258. //
  2259. // Description:
  2260. // Retrieves the instance blob and fixes up the class entry in
  2261. // there, then writes it back.
  2262. //
  2263. // Parameters:
  2264. // wszInstanceIndex - Path to an instance reference path: ns\ki\i
  2265. //
  2266. //=====================================================================
  2267. HRESULT CLocalizationUpgrade::FixupInstanceBlob(CFileName &wszInstanceIndex)
  2268. {
  2269. HRESULT hRes =0;
  2270. //Create full path name
  2271. CFileName wszFullPath;
  2272. if (wszFullPath == NULL)
  2273. return WBEM_E_OUT_OF_MEMORY;
  2274. StringCchCopyW(wszFullPath, wszFullPath.Length(), g_Glob.GetRootDir());
  2275. StringCchCatW(wszFullPath, wszFullPath.Length(), L"\\");
  2276. StringCchCatW(wszFullPath, wszFullPath.Length(), wszInstanceIndex);
  2277. //remove the .X.Y.Z as this would screw everything up - both reading and writing
  2278. wcstok(wszFullPath + g_Glob.GetRootDirLen(), L".");
  2279. //Retrieve the blob
  2280. LONG lRes = 0;
  2281. DWORD dwLen = 0;
  2282. BYTE *pBuffer = NULL;
  2283. lRes = g_Glob.m_FileCache.ReadObject(wszFullPath, &dwLen, &pBuffer);
  2284. if (lRes)
  2285. return A51TranslateErrorCode(lRes);
  2286. CTempFreeMe tfm(pBuffer, dwLen);
  2287. //Extract the class hash
  2288. wchar_t *wszClassHash = new wchar_t [MAX_HASH_LEN+1];
  2289. if (wszClassHash == NULL)
  2290. return WBEM_E_OUT_OF_MEMORY;
  2291. StringCchCopyNW(wszClassHash, MAX_HASH_LEN+1, (wchar_t*)pBuffer, 32);
  2292. //fixup the path
  2293. wchar_t *wszNewHash = NULL;
  2294. hRes = GetNewHash(wszClassHash, &wszNewHash);
  2295. if (hRes == WBEM_E_NOT_FOUND)
  2296. return WBEM_NO_ERROR;
  2297. else if (FAILED(hRes))
  2298. return hRes;
  2299. else
  2300. {
  2301. DEBUGTRACE((LOG_REPDRV, "Fixing up class hash in instance blob: %S\n", wszInstanceIndex));
  2302. //re-insert into the blob
  2303. wmemcpy((wchar_t*)pBuffer, wszNewHash, 32);
  2304. //Build the CI full path also as we need to write both back
  2305. CFileName wsCIPath;
  2306. if (wsCIPath == NULL)
  2307. return WBEM_E_OUT_OF_MEMORY;
  2308. StringCchCopyW(wsCIPath, wsCIPath.Length(), g_Glob.GetRootDir());
  2309. StringCchCatW(wsCIPath, wsCIPath.Length(), L"\\");
  2310. StringCchCatNW(wsCIPath, wsCIPath.Length(), wszInstanceIndex, 3+32);
  2311. StringCchCatW(wsCIPath, wsCIPath.Length(), L"\\CI_");
  2312. StringCchCatW(wsCIPath, wsCIPath.Length(), wszNewHash);
  2313. StringCchCatW(wsCIPath, wsCIPath.Length(), L"\\IL_");
  2314. StringCchCatN(wsCIPath, wsCIPath.Length(), wszInstanceIndex + 3+32+1+3+32+1+2, 32);
  2315. //write back
  2316. lRes = g_Glob.m_FileCache.WriteObject(wszFullPath, wsCIPath, dwLen, pBuffer);
  2317. if (lRes)
  2318. return A51TranslateErrorCode(lRes);
  2319. }
  2320. return 0;
  2321. }