Source code of Windows XP (NT5)
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.

622 lines
15 KiB

  1. /*++
  2. Copyright (C) 1996-2001 Microsoft Corporation
  3. Module Name:
  4. A51Imp.cpp
  5. Abstract:
  6. Imports an export file into the repository. This uses the export file format defined
  7. in A51Exp.cpp.
  8. History:
  9. 08-Dec-2000 paulall Created.
  10. --*/
  11. #include <windows.h>
  12. #include <ql.h>
  13. #include "A51Rep.h"
  14. #include "A51Exp.h"
  15. #include "A51Imp.h"
  16. //extern CFileCache* g_FileCache;
  17. extern CGlobals g_Glob;
  18. /*=============================================================================
  19. *
  20. * A51Import::A51Import
  21. *
  22. *=============================================================================
  23. */
  24. A51Import::A51Import()
  25. : m_hFile(INVALID_HANDLE_VALUE),
  26. m_bSkipMode(false)
  27. {
  28. }
  29. /*=============================================================================
  30. *
  31. * A51Import::~A51Import
  32. *
  33. *=============================================================================
  34. */
  35. A51Import::~A51Import()
  36. {
  37. }
  38. /*=============================================================================
  39. *
  40. * A51Import::Import
  41. *
  42. *=============================================================================
  43. */
  44. HRESULT A51Import::Import(const wchar_t *wszFilename, DWORD dwFlags, CRepository *pRepository)
  45. {
  46. HRESULT hRes = WBEM_S_NO_ERROR;
  47. m_pRepository = pRepository;
  48. //Open the import file for reading
  49. m_hFile = CreateFileW(wszFilename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING,
  50. FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN,
  51. NULL);
  52. if (m_hFile == INVALID_HANDLE_VALUE)
  53. hRes = WBEM_E_FAILED;
  54. try
  55. {
  56. //Check the header is valid, in case we were given an invalid file format
  57. if (SUCCEEDED(hRes))
  58. hRes = ImportHeader();
  59. //Retrieve the type of the next object to process
  60. DWORD dwObjectType;
  61. if (SUCCEEDED(hRes))
  62. {
  63. hRes = ReadObjectType(&dwObjectType);
  64. }
  65. //While we are not at the end of the file, loop through the items
  66. while (SUCCEEDED(hRes) && (dwObjectType != A51_EXPORT_FILE_END_TAG))
  67. {
  68. //Only namespace objects should reside at this level!
  69. switch (dwObjectType)
  70. {
  71. case A51_EXPORT_NAMESPACE_TAG:
  72. {
  73. hRes = ImportNamespace();
  74. break;
  75. }
  76. default:
  77. {
  78. hRes = WBEM_E_FAILED;
  79. break;
  80. }
  81. }
  82. //Get the next type of object
  83. if (SUCCEEDED(hRes))
  84. {
  85. hRes = ReadObjectType(&dwObjectType);
  86. }
  87. }
  88. }
  89. catch (...)
  90. {
  91. hRes = WBEM_E_CRITICAL_ERROR;
  92. ERRORTRACE((LOG_WBEMCORE, "Critical error happened while re-importing the repository, error <0x%X>\n", hRes));
  93. }
  94. if (m_hFile)
  95. {
  96. CloseHandle(m_hFile);
  97. m_hFile = INVALID_HANDLE_VALUE;
  98. }
  99. m_hFile = INVALID_HANDLE_VALUE;
  100. return hRes;
  101. }
  102. /*=============================================================================
  103. *
  104. * A51Import::ImportHeader
  105. *
  106. * File Header Block:
  107. * BYTE wszFileHeader[8] = A51_EXPORT_FILE_START_TAG ("a51exp1")
  108. *
  109. *=============================================================================
  110. */
  111. HRESULT A51Import::ImportHeader()
  112. {
  113. HRESULT hRes = WBEM_S_NO_ERROR;
  114. char *pszExpectedHeader = A51_EXPORT_FILE_START_TAG;
  115. DWORD dwSize = sizeof(A51_EXPORT_FILE_START_TAG);
  116. char *pszActualHeader = new char[dwSize];
  117. CVectorDeleteMe<char> vdm1(pszActualHeader);
  118. if (pszActualHeader == NULL)
  119. {
  120. hRes = WBEM_E_OUT_OF_MEMORY;
  121. }
  122. //Read header
  123. if (SUCCEEDED(hRes) &&
  124. ((!ReadFile(m_hFile, pszActualHeader, dwSize, &dwSize, NULL)) ||
  125. (dwSize != sizeof(A51_EXPORT_FILE_START_TAG))))
  126. {
  127. hRes = WBEM_E_FAILED;
  128. }
  129. //If last character is not a NULL terminator then it fails outright!
  130. if (SUCCEEDED(hRes) && (pszActualHeader[sizeof(A51_EXPORT_FILE_START_TAG) - 1] != '\0'))
  131. {
  132. hRes = WBEM_E_FAILED;
  133. }
  134. //Do check to see if rest is the same....
  135. if ((SUCCEEDED(hRes)) && (lstrcmpA(pszExpectedHeader, pszActualHeader) != 0))
  136. {
  137. hRes = WBEM_E_FAILED;
  138. }
  139. return hRes;
  140. }
  141. /*=============================================================================
  142. *
  143. * A51Import::ImportNamespace
  144. *
  145. * Namespace Block:
  146. * DWORD dwObjectType = A51_EXPORT_NAMESPACE_TAG
  147. * DWORD dwNamespaceNameSize
  148. * BYTE wszNamespaceName[dwNamespaceNameSize] = Full namespace name
  149. *
  150. *=============================================================================
  151. */
  152. HRESULT A51Import::ImportNamespace()
  153. {
  154. HRESULT hRes;
  155. DWORD dwLength = 0;
  156. wchar_t *wszNamespaceName = NULL;
  157. //Retrieve the namespace name from the import file
  158. hRes = ReadBufferWithLength(&dwLength, (void**) &wszNamespaceName);
  159. CVectorDeleteMe<wchar_t> vdm1(wszNamespaceName);
  160. //Create a namespace object for this namespace
  161. CNamespaceHandle *pNs = NULL;
  162. if (SUCCEEDED(hRes))
  163. {
  164. DEBUGTRACE((LOG_WBEMCORE, "Namespace import for namespace <%S>\n", wszNamespaceName));
  165. pNs = new CNamespaceHandle(NULL, m_pRepository);
  166. if (pNs == NULL)
  167. hRes = WBEM_E_OUT_OF_MEMORY;
  168. else
  169. {
  170. pNs->AddRef();
  171. hRes = pNs->Initialize(wszNamespaceName);
  172. }
  173. }
  174. CReleaseMe rm1(pNs);
  175. if (FAILED(hRes))
  176. {
  177. ERRORTRACE((LOG_WBEMCORE, "Namespace import failed for namespace <%S>, error <0x%X>\n", wszNamespaceName, hRes));
  178. }
  179. //Retrieve the type of the next object in the import file
  180. DWORD dwObjectType;
  181. if (SUCCEEDED(hRes))
  182. {
  183. hRes = ReadObjectType(&dwObjectType);
  184. }
  185. //Loop through all things that hang off this namespace
  186. while (SUCCEEDED(hRes) && (dwObjectType != A51_EXPORT_NAMESPACE_END_TAG))
  187. {
  188. //Classes and namespaces are the only valid things to hang off a namespace
  189. switch (dwObjectType)
  190. {
  191. case A51_EXPORT_CLASS_TAG:
  192. {
  193. //TODO: Need to create an empty class to pass through here!
  194. hRes = ImportClass(pNs, NULL, NULL);
  195. break;
  196. }
  197. case A51_EXPORT_NAMESPACE_TAG:
  198. {
  199. hRes = ImportNamespace();
  200. break;
  201. }
  202. default:
  203. hRes = WBEM_E_FAILED;
  204. break;
  205. }
  206. if (SUCCEEDED(hRes))
  207. {
  208. hRes = ReadObjectType(&dwObjectType);
  209. }
  210. }
  211. if (FAILED(hRes))
  212. {
  213. ERRORTRACE((LOG_WBEMCORE, "Namespace import failed for child classes/namespace <%S>, error <0x%X>\n", wszNamespaceName, hRes));
  214. }
  215. return hRes;
  216. }
  217. /*=============================================================================
  218. *
  219. * A51Import::ImportClass
  220. *
  221. * Class Block:
  222. * DWORD dwObjectType = A51_EXPORT_CLASS_TAG
  223. * DWORD dwClassNameSize
  224. * BYTE wszClassName[dwClassNameSize] = Class name (my_class_name)
  225. * DWORD dwClassObjectSize
  226. * BYTE adwClassObject[dwClassObjectSize]
  227. *
  228. *=============================================================================
  229. */
  230. HRESULT A51Import::ImportClass(CNamespaceHandle *pNs,
  231. _IWmiObject *pOldParentClass,
  232. _IWmiObject *pNewParentClass)
  233. {
  234. HRESULT hRes;
  235. DWORD dwLength = 0;
  236. _IWmiObject *pOldClass = NULL;
  237. _IWmiObject *pNewClass = NULL;
  238. wchar_t *wszClassName = NULL;
  239. //Retrieve the class name from the import file
  240. hRes = ReadBufferWithLength(&dwLength, (void**) &wszClassName);
  241. CVectorDeleteMe<wchar_t> vdm1(wszClassName );
  242. {//scope to free everything we don't need when recursing to lower levels
  243. //Retrieve the class object from the import file
  244. BYTE *pClassBlob = NULL;
  245. if (SUCCEEDED(hRes))
  246. {
  247. DEBUGTRACE((LOG_WBEMCORE, "Class import for class <%S>\n", wszClassName));
  248. hRes = ReadBufferWithLength(&dwLength, (void**) &pClassBlob);
  249. }
  250. CVectorDeleteMe<BYTE> vdm2(pClassBlob);
  251. //For Skip Mode we have to read everything from the import file, but not process anything
  252. //until the flag is reset...
  253. if (!m_bSkipMode)
  254. {
  255. //if pOldParentClass is NULL, we need to create a blank class
  256. if (SUCCEEDED(hRes) && (pOldParentClass == NULL))
  257. {
  258. hRes = pNs->GetObjectByPath(L"", 0, IID__IWmiObject, (void**)&pOldParentClass);
  259. if (FAILED(hRes))
  260. {
  261. ERRORTRACE((LOG_WBEMCORE, "Class import failed for class <%S>, error <0x%X>, GetObjectByPath(L\"\",...)\n", wszClassName, hRes));
  262. }
  263. }
  264. //Create the current version of this class
  265. if (SUCCEEDED(hRes))
  266. {
  267. hRes = pOldParentClass->Merge(WMIOBJECT_MERGE_FLAG_CLASS, dwLength, pClassBlob, &pOldClass);
  268. if (FAILED(hRes))
  269. {
  270. ERRORTRACE((LOG_WBEMCORE, "Class import failed for class <%S>, error <0x%X>, Merge\n", wszClassName, hRes));
  271. }
  272. }
  273. //Now we need to upgrade this class based on the new parent class...
  274. _IWmiObject *pTmpNewClass = NULL;
  275. if (SUCCEEDED(hRes))
  276. {
  277. hRes = pOldClass->Upgrade(pNewParentClass, 0, &pTmpNewClass );
  278. if (FAILED(hRes))
  279. {
  280. ERRORTRACE((LOG_WBEMCORE, "Class import failed for class <%S>, error <0x%X>, Upgrade\n", wszClassName, hRes));
  281. }
  282. }
  283. CReleaseMe rm2(pTmpNewClass );
  284. //Write the new class back to the repository if it is not a system class
  285. if (SUCCEEDED(hRes) && (wszClassName[0] != L'_'))
  286. {
  287. hRes = BeginTransaction();
  288. if (SUCCEEDED(hRes))
  289. {
  290. try
  291. {
  292. CEventCollector aEvents;
  293. hRes = pNs->PutObject(IID__IWmiObject, pTmpNewClass , WBEM_FLAG_UPDATE_FORCE_MODE,
  294. WMIDB_HANDLE_TYPE_COOKIE, 0, aEvents);
  295. if (FAILED(hRes))
  296. {
  297. AbortTransaction();
  298. ERRORTRACE((LOG_WBEMCORE, "Class import failed for class <%S>, error <0x%X>, PutObject\n", wszClassName, hRes));
  299. }
  300. else
  301. {
  302. hRes = CommitTransaction();
  303. if (FAILED(hRes))
  304. {
  305. AbortTransaction();
  306. }
  307. }
  308. }
  309. catch (...)
  310. {
  311. AbortTransaction();
  312. throw;
  313. }
  314. }
  315. }
  316. //Now we need to get that object back from the repository before we do anything
  317. if (SUCCEEDED(hRes))
  318. {
  319. hRes = pNs->GetObjectByPath(wszClassName, 0, IID__IWmiObject, (void**)&pNewClass);
  320. if (FAILED(hRes))
  321. {
  322. ERRORTRACE((LOG_WBEMCORE, "Class import failed for class <%S>, error <0x%X>, GetObjectByPath(wszClassName,...)\n", wszClassName, hRes));
  323. }
  324. if (hRes == WBEM_E_NOT_FOUND)
  325. {
  326. m_bSkipMode = true;
  327. hRes = WBEM_S_NO_ERROR;
  328. }
  329. }
  330. }
  331. }
  332. CReleaseMe rm1(pOldClass);
  333. CReleaseMe rm3(pNewClass);
  334. if (FAILED(hRes))
  335. {
  336. ERRORTRACE((LOG_WBEMCORE, "Class import failed for class <%S>, error <0x%X>\n", wszClassName, hRes));
  337. }
  338. //Process the next object...
  339. DWORD dwObjectType;
  340. if (SUCCEEDED(hRes))
  341. {
  342. hRes = ReadObjectType(&dwObjectType);
  343. }
  344. //Loop through all things that hang off this class
  345. while (SUCCEEDED(hRes) && (dwObjectType != A51_EXPORT_CLASS_END_TAG))
  346. {
  347. //Classes and namespaces are the only valid things to hang off a namespace
  348. switch (dwObjectType)
  349. {
  350. case A51_EXPORT_CLASS_TAG:
  351. {
  352. hRes = ImportClass(pNs, pOldClass, pNewClass);
  353. break;
  354. }
  355. case A51_EXPORT_INST_TAG:
  356. {
  357. hRes = ImportInstance(pNs, pOldClass, pNewClass);
  358. break;
  359. }
  360. default:
  361. hRes = WBEM_E_FAILED;
  362. break;
  363. }
  364. if (SUCCEEDED(hRes))
  365. {
  366. hRes = ReadObjectType(&dwObjectType);
  367. }
  368. }
  369. if (FAILED(hRes))
  370. {
  371. ERRORTRACE((LOG_WBEMCORE, "Namespace import failed for child classes/instances <%S>, error <0x%X>\n", wszClassName, hRes));
  372. }
  373. m_bSkipMode = false;
  374. return hRes;
  375. }
  376. /*=============================================================================
  377. *
  378. * A51Import::ImportInstance
  379. *
  380. * Instance Block - key of type string
  381. * DWORD dwObjectType = A51_EXPORT_INST_TAG
  382. * DWORD dwInstanceKeySize
  383. * BYTE dwInstanceKey[dwInstanceKeySize] = Instance key
  384. * DWORD dwInstanceObjectSize
  385. * BYTE adwInstanceObject[dwInstanceObjectSize]
  386. *
  387. *=============================================================================
  388. */
  389. HRESULT A51Import::ImportInstance(CNamespaceHandle *pNs,
  390. _IWmiObject *pOldParentClass,
  391. _IWmiObject *pNewParentClass)
  392. {
  393. HRESULT hRes;
  394. DWORD dwLength = 0;
  395. //Retrieve the key string from the import file
  396. wchar_t *wszKeyString = NULL;
  397. hRes = ReadBufferWithLength(&dwLength, (void**) &wszKeyString) ;
  398. CVectorDeleteMe<wchar_t> vdm1(wszKeyString);
  399. //Retrieve the instance object from the import file
  400. BYTE *pInstBlob = NULL;
  401. if (SUCCEEDED(hRes))
  402. {
  403. DEBUGTRACE((LOG_WBEMCORE, "Instance import for instance <%S>\n", wszKeyString));
  404. hRes = ReadBufferWithLength(&dwLength, (void**) &pInstBlob);
  405. }
  406. CVectorDeleteMe<BYTE> vdm2(pInstBlob);
  407. if (!m_bSkipMode)
  408. {
  409. _IWmiObject *pOldInstance = NULL;
  410. //Merge the old instance part with the old instance class
  411. if (SUCCEEDED(hRes))
  412. {
  413. hRes = pOldParentClass->Merge(WMIOBJECT_MERGE_FLAG_INSTANCE,
  414. dwLength, pInstBlob, &pOldInstance);
  415. }
  416. CReleaseMe rm1(pOldInstance);
  417. //Upgrade the instance to work with the new class
  418. _IWmiObject *pNewInstance = NULL;
  419. if (SUCCEEDED(hRes))
  420. {
  421. hRes = pOldInstance->Upgrade(pNewParentClass, 0, &pNewInstance);
  422. }
  423. CReleaseMe rm2(pNewInstance);
  424. //Put the instance into the repository
  425. if (SUCCEEDED(hRes))
  426. {
  427. hRes = BeginTransaction();
  428. if (SUCCEEDED(hRes))
  429. {
  430. try
  431. {
  432. CEventCollector aEvents;
  433. hRes = pNs->PutObject(IID__IWmiObject, pNewInstance, 0, WMIDB_HANDLE_TYPE_COOKIE, NULL, aEvents);
  434. if (SUCCEEDED(hRes))
  435. {
  436. hRes = CommitTransaction();
  437. if (FAILED(hRes))
  438. {
  439. AbortTransaction();
  440. }
  441. }
  442. else
  443. {
  444. AbortTransaction();
  445. }
  446. }
  447. catch (...)
  448. {
  449. AbortTransaction();
  450. throw;
  451. }
  452. }
  453. }
  454. }
  455. if (FAILED(hRes))
  456. {
  457. ERRORTRACE((LOG_WBEMCORE, "Instance import failed for instance <%S>, error <0x%X>\n", wszKeyString, hRes));
  458. }
  459. return hRes;
  460. }
  461. /*=============================================================================
  462. *
  463. * A51Import::ReadBufferWithLength
  464. *
  465. *=============================================================================
  466. */
  467. HRESULT A51Import::ReadBufferWithLength(DWORD *pdwBufferSize, void **ppBuffer)
  468. {
  469. HRESULT hRes = WBEM_S_NO_ERROR;
  470. DWORD dwSize;
  471. //Write buffer length
  472. if (!ReadFile(m_hFile, pdwBufferSize, sizeof(DWORD), &dwSize, NULL) || (dwSize != sizeof(DWORD)))
  473. {
  474. hRes = WBEM_E_FAILED;
  475. }
  476. if (SUCCEEDED(hRes))
  477. {
  478. *ppBuffer = (void*)new BYTE[*pdwBufferSize];
  479. if (*ppBuffer == NULL)
  480. hRes = WBEM_E_OUT_OF_MEMORY;
  481. }
  482. //Write buffer
  483. if (SUCCEEDED(hRes) &&
  484. (!ReadFile(m_hFile, *ppBuffer, *pdwBufferSize, &dwSize, NULL) || (*pdwBufferSize != dwSize)))
  485. {
  486. hRes = WBEM_E_FAILED;
  487. }
  488. if (FAILED(hRes))
  489. {
  490. delete [] *ppBuffer;
  491. *ppBuffer = NULL;
  492. *pdwBufferSize = 0;
  493. }
  494. return hRes;
  495. }
  496. /*=============================================================================
  497. *
  498. * A51Import::ReadObjectType
  499. *
  500. *
  501. *=============================================================================
  502. */
  503. HRESULT A51Import::ReadObjectType(DWORD *pdwObjectType)
  504. {
  505. HRESULT hRes = WBEM_S_NO_ERROR;
  506. DWORD dwSize;
  507. if (!ReadFile(m_hFile, pdwObjectType, sizeof(DWORD), &dwSize, NULL) || (dwSize != sizeof(DWORD)))
  508. {
  509. hRes = WBEM_E_FAILED;
  510. }
  511. return hRes;
  512. }
  513. /*=============================================================================
  514. *
  515. * A51Import::BeginTransaction
  516. *
  517. *
  518. *=============================================================================
  519. */
  520. HRESULT A51Import::BeginTransaction()
  521. {
  522. return A51TranslateErrorCode(g_Glob.GetFileCache()->BeginTransaction());
  523. }
  524. /*=============================================================================
  525. *
  526. * A51Import::CommitTransaction
  527. *
  528. *
  529. *=============================================================================
  530. */
  531. HRESULT A51Import::CommitTransaction()
  532. {
  533. return A51TranslateErrorCode(g_Glob.GetFileCache()->CommitTransaction());
  534. }
  535. /*=============================================================================
  536. *
  537. * A51Import::AbortTransaction
  538. *
  539. *
  540. *=============================================================================
  541. */
  542. HRESULT A51Import::AbortTransaction()
  543. {
  544. return A51TranslateErrorCode(g_Glob.GetFileCache()->AbortTransaction());
  545. }