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.

402 lines
14 KiB

  1. /*++
  2. Copyright (C) 1996-2000 Microsoft Corporation
  3. Module Name:
  4. EXPORT.CPP
  5. Abstract:
  6. Exporting
  7. History:
  8. --*/
  9. #include "precomp.h"
  10. #include "Time.h"
  11. #include "WbemCli.h"
  12. #include "DbRep.h"
  13. #include "Export.h"
  14. #include "WbemUtil.h"
  15. void CRepExporter::DumpInstanceString(INSTDEF* pInstDef, const wchar_t *wszKey, const wchar_t *pszClass)
  16. {
  17. if (wszKey)
  18. {
  19. //Dump an instance block header
  20. DWORD dwSize = 0;
  21. DWORD adwBuffer[2];
  22. adwBuffer[0] = REP_EXPORT_INST_STR_TAG;
  23. adwBuffer[1] = (wcslen(wszKey) + 1) * sizeof (wchar_t);
  24. if ((WriteFile(g_hFile, adwBuffer, sizeof(adwBuffer), &dwSize, NULL) == 0) || (dwSize != sizeof(adwBuffer)))
  25. {
  26. DEBUGTRACE((LOG_WBEMCORE, "Failed to write instance %S for class %S header.\n", wszKey, pszClass));
  27. throw FAILURE_WRITE;
  28. }
  29. if ((WriteFile(g_hFile, wszKey, (wcslen(wszKey) + 1) * sizeof (wchar_t), &dwSize, NULL) == 0) || (dwSize != (wcslen(wszKey) + 1) * sizeof (wchar_t)))
  30. {
  31. DEBUGTRACE((LOG_WBEMCORE, "Failed to write instance %S for class %S.\n", wszKey, pszClass));
  32. throw FAILURE_WRITE;
  33. }
  34. }
  35. {
  36. //Dump the block
  37. DWORD dwSize = 0;
  38. DWORD *pdwObjectStream = Fixup((DWORD*)pInstDef->m_poObjectStream);
  39. DWORD dwCurSize = *(pdwObjectStream - 1);
  40. dwCurSize -= GetMMFBlockOverhead();
  41. if ((WriteFile(g_hFile, &dwCurSize, sizeof(DWORD), &dwSize, NULL) == 0) || (dwSize != sizeof(DWORD)))
  42. {
  43. if (wszKey)
  44. {
  45. DEBUGTRACE((LOG_WBEMCORE, "Failed to write data header of instance %S for class %S.\n", wszKey, pszClass));
  46. }
  47. else
  48. {
  49. DEBUGTRACE((LOG_WBEMCORE, "Failed to write data header of class definition for class %S.\n", pszClass));
  50. }
  51. throw FAILURE_WRITE;
  52. }
  53. if ((WriteFile(g_hFile, pdwObjectStream, dwCurSize, &dwSize, NULL) == 0) || (dwSize != dwCurSize))
  54. {
  55. if (wszKey)
  56. {
  57. DEBUGTRACE((LOG_WBEMCORE, "Failed to write instance %S for class %S.\n", wszKey, pszClass));
  58. }
  59. else
  60. {
  61. DEBUGTRACE((LOG_WBEMCORE, "Failed to write class definition for class %S.\n", pszClass));
  62. }
  63. throw FAILURE_WRITE;
  64. }
  65. }
  66. }
  67. void CRepExporter::DumpInstanceInt(INSTDEF* pInstDef, INT_PTR nKey, const wchar_t *pszClass)
  68. {
  69. {
  70. //Dump an instance block header
  71. DWORD dwSize = 0;
  72. DWORD dwBuffer;
  73. dwBuffer = REP_EXPORT_INST_INT_TAG;
  74. if ((WriteFile(g_hFile, &dwBuffer, sizeof(DWORD), &dwSize, NULL) == 0) || (dwSize != sizeof(DWORD)))
  75. {
  76. DEBUGTRACE((LOG_WBEMCORE, "Failed to write instance %d for class %S object and header.\n", nKey, pszClass));
  77. throw FAILURE_WRITE;
  78. }
  79. if ((WriteFile(g_hFile, &nKey, sizeof(INT_PTR), &dwSize, NULL) == 0) || (dwSize != sizeof(INT_PTR)))
  80. {
  81. DEBUGTRACE((LOG_WBEMCORE, "Failed to write instance %d for class %S object and header.\n", nKey, pszClass));
  82. throw FAILURE_WRITE;
  83. }
  84. }
  85. {
  86. //Dump the block
  87. DWORD dwSize = 0;
  88. DWORD *pObjectStream = Fixup((DWORD*)pInstDef->m_poObjectStream);
  89. DWORD dwCurSize = *(pObjectStream - 1);
  90. dwCurSize -= GetMMFBlockOverhead();
  91. if ((WriteFile(g_hFile, &dwCurSize, sizeof(DWORD), &dwSize, NULL) == 0) || (dwSize != sizeof(DWORD)))
  92. {
  93. DEBUGTRACE((LOG_WBEMCORE, "Failed to write data header of instance %%d for class %S.\n", nKey, pszClass));
  94. throw FAILURE_WRITE;
  95. }
  96. if ((WriteFile(g_hFile, pObjectStream, dwCurSize, &dwSize, NULL) == 0) || (dwSize != dwCurSize))
  97. {
  98. DEBUGTRACE((LOG_WBEMCORE, "Failed to write instance %d for class %S.\n", nKey, pszClass));
  99. throw FAILURE_WRITE;
  100. }
  101. }
  102. }
  103. void CRepExporter::IterateKeyTree(const wchar_t *wszClassName, CLASSDEF *pOwningClass, AVLNode *pInstNode, BOOL bStringKey)
  104. {
  105. if (pInstNode->poLeft)
  106. {
  107. IterateKeyTree(wszClassName, pOwningClass, Fixup(pInstNode->poLeft), bStringKey);
  108. }
  109. //If this is a top-level class then we dump the class, otherwise the class dump will get child classes...
  110. INSTDEF *pInstDef = Fixup((INSTDEF*)pInstNode->poData);
  111. if (Fixup(pInstDef->m_poOwningClass) == pOwningClass)
  112. {
  113. if (bStringKey)
  114. DumpInstanceString(pInstDef, Fixup((wchar_t*)pInstNode->nKey), wszClassName);
  115. else
  116. DumpInstanceInt(pInstDef, pInstNode->nKey, wszClassName);
  117. }
  118. if (pInstNode->poRight)
  119. {
  120. IterateKeyTree(wszClassName, pOwningClass, Fixup(pInstNode->poRight), bStringKey);
  121. }
  122. }
  123. void CRepExporter::DumpClass(CLASSDEF* pClassDef, const wchar_t *wszClassName)
  124. {
  125. DWORD dwSize = 0;
  126. DWORD adwBuffer[6];
  127. adwBuffer[0] = REP_EXPORT_CLASS_TAG;
  128. adwBuffer[1] = (wcslen(wszClassName) + 1) * sizeof (wchar_t);
  129. if ((WriteFile(g_hFile, adwBuffer, 8, &dwSize, NULL) == 0) || (dwSize != 8))
  130. {
  131. DEBUGTRACE((LOG_WBEMCORE, "Failed to write clas %S header.\n", wszClassName));
  132. throw FAILURE_WRITE;
  133. }
  134. if ((WriteFile(g_hFile, wszClassName, (wcslen(wszClassName) + 1) * sizeof (wchar_t), &dwSize, NULL) == 0) || (dwSize != (wcslen(wszClassName) + 1) * sizeof (wchar_t)))
  135. {
  136. DEBUGTRACE((LOG_WBEMCORE, "Failed to write clas %S class name.\n", wszClassName));
  137. throw FAILURE_WRITE;
  138. }
  139. DumpInstanceString(Fixup(pClassDef->m_poClassDef), NULL, wszClassName);
  140. //Dump the children classes...
  141. AVLNode *pTreeNode = Fixup((AVLNode*)(((DWORD_PTR*)Fixup(Fixup(pClassDef->m_poOwningNs)->m_poClassTree))[0]));
  142. IterateClassNodes(pTreeNode, Fixdown(pClassDef));
  143. //Special cases! We do not dump instances for the following classes...
  144. if ((_wcsicmp(wszClassName, L"__CIMOMIdentification") != 0))
  145. {
  146. //If we own the key tree, then we need to iterate through this...
  147. if (pClassDef->m_poKeyTree)
  148. {
  149. DWORD_PTR dwTreeNode = (((DWORD*)Fixup(pClassDef->m_poKeyTree))[0]);
  150. if (dwTreeNode)
  151. {
  152. AVLNode *pTreeNode2 = Fixup((AVLNode*)dwTreeNode);
  153. int keyType = GetAvlTreeNodeType(Fixup(pClassDef->m_poKeyTree));
  154. IterateKeyTree(wszClassName, pClassDef, pTreeNode2, (keyType == 0x1f));
  155. }
  156. }
  157. }
  158. adwBuffer[0] = REP_EXPORT_CLASS_END_TAG;
  159. adwBuffer[1] = REP_EXPORT_END_TAG_SIZE;
  160. memset(&(adwBuffer[2]), REP_EXPORT_END_TAG_MARKER, REP_EXPORT_END_TAG_SIZE);
  161. if ((WriteFile(g_hFile, adwBuffer, 24, &dwSize, NULL) == 0) || (dwSize != 24))
  162. {
  163. DEBUGTRACE((LOG_WBEMCORE, "Failed to write class %S end marker.\n", wszClassName));
  164. throw FAILURE_WRITE;
  165. }
  166. }
  167. void CRepExporter::IterateClassNodes(AVLNode *pClassNode, CLASSDEF *poParentClass)
  168. {
  169. if (pClassNode->poLeft)
  170. {
  171. IterateClassNodes(Fixup((AVLNode *)pClassNode->poLeft), poParentClass);
  172. }
  173. //If this is a top-level class then we dump the class, otherwise the class dump will get child classes...
  174. CLASSDEF *pClassDef = Fixup((CLASSDEF*)pClassNode->poData);
  175. if (pClassDef->m_poSuperclass == poParentClass)
  176. {
  177. DumpClass(pClassDef, Fixup((wchar_t*)pClassNode->nKey));
  178. }
  179. if (pClassNode->poRight)
  180. {
  181. IterateClassNodes(Fixup((AVLNode *)pClassNode->poRight), poParentClass);
  182. }
  183. }
  184. void CRepExporter::IterateChildNamespaceTree(AVLNode *pNsNode)
  185. {
  186. if (pNsNode->poLeft)
  187. {
  188. IterateChildNamespaceTree(Fixup((AVLNode *)pNsNode->poLeft));
  189. }
  190. //If this is a top-level class then we dump the class, otherwise the class dump will get child classes...
  191. NSREP *pNsDef = Fixup((NSREP*)pNsNode->poData);
  192. DumpNamespace(pNsDef);
  193. if (pNsNode->poRight)
  194. {
  195. IterateChildNamespaceTree(Fixup((AVLNode *)pNsNode->poRight));
  196. }
  197. }
  198. void CRepExporter::IterateChildNamespaces(RepCollection *childNamespaces)
  199. {
  200. DWORD dwType;
  201. DWORD dwSize;
  202. DWORD_PTR dwItems;
  203. dwType = ((DWORD*)childNamespaces)[0];
  204. dwSize = ((DWORD*)childNamespaces)[1];
  205. dwItems = ((DWORD*)childNamespaces)[2];
  206. if ((dwType == 0) || (dwSize == 0))
  207. return;
  208. else if (dwType == 1)
  209. {
  210. //This is a pointer to a RepCollectionItem!
  211. RepCollectionItem *pRepCollectionItem = Fixup((RepCollectionItem*)dwItems);
  212. DumpNamespace(Fixup((NSREP*)pRepCollectionItem->poItem));
  213. }
  214. else if (dwType == 2)
  215. {
  216. CDbArray *pDbArray = Fixup((CDbArray*)dwItems);
  217. RepCollectionItem** apNsRepItem;
  218. apNsRepItem = Fixup((RepCollectionItem**)(((DWORD_PTR*)pDbArray)[3]));
  219. for (DWORD i = 0; i != dwSize; i++)
  220. {
  221. DumpNamespace(Fixup((NSREP*)(Fixup(apNsRepItem[i])->poItem)));
  222. }
  223. }
  224. else if (dwType == 3)
  225. {
  226. //This is a tree
  227. AVLNode *pTreeNode = Fixup((AVLNode*)(((DWORD_PTR*)Fixup(dwItems))[0]));
  228. IterateChildNamespaceTree(pTreeNode);
  229. }
  230. else
  231. {
  232. //this is a bug!
  233. }
  234. }
  235. void CRepExporter::DumpNamespace(NSREP *pNsRep)
  236. {
  237. wchar_t *pszCurNs = Fixup(pNsRep->m_poName);
  238. DWORD dwSize = 0;
  239. DWORD dwBuffer[6];
  240. dwBuffer[0] = REP_EXPORT_NAMESPACE_TAG;
  241. dwBuffer[1] = (wcslen(pszCurNs) + 1) * sizeof(wchar_t);
  242. if ((WriteFile(g_hFile, dwBuffer, 8, &dwSize, NULL) == 0) || (dwSize != 8))
  243. {
  244. DEBUGTRACE((LOG_WBEMCORE, "Failed to write namespace %S header.\n", pszCurNs));
  245. throw FAILURE_WRITE;
  246. }
  247. if ((WriteFile(g_hFile, pszCurNs, (wcslen(pszCurNs) + 1) * sizeof(wchar_t), &dwSize, NULL) == 0) || (dwSize != (wcslen(pszCurNs) + 1) * sizeof(wchar_t)))
  248. {
  249. DEBUGTRACE((LOG_WBEMCORE, "Failed to write namespace %S.\n", pszCurNs));
  250. throw FAILURE_WRITE;
  251. }
  252. DumpNamespaceSecurity(pNsRep);
  253. AVLNode *pTreeNode = Fixup((AVLNode*)(((DWORD_PTR*)Fixup(pNsRep->m_poClassTree))[0]));
  254. IterateClassNodes(pTreeNode, 0);
  255. IterateChildNamespaces(Fixup(pNsRep->m_poNamespaces));
  256. dwBuffer[0] = REP_EXPORT_NAMESPACE_END_TAG;
  257. dwBuffer[1] = REP_EXPORT_END_TAG_SIZE;
  258. memset(&(dwBuffer[2]), REP_EXPORT_END_TAG_MARKER, REP_EXPORT_END_TAG_SIZE);
  259. if ((WriteFile(g_hFile, dwBuffer, 24, &dwSize, NULL) == 0) || (dwSize != 24))
  260. {
  261. DEBUGTRACE((LOG_WBEMCORE, "Failed to write namespace %S end marker.\n", pszCurNs));
  262. throw FAILURE_WRITE;
  263. }
  264. }
  265. void CRepExporter::DumpNamespaceSecurity(NSREP *pNsRep)
  266. {
  267. //Default version does not have a security descriptor, so we need to
  268. //just dump a blank entry.
  269. DWORD dwSize = 0;
  270. DWORD dwBuffer[2];
  271. dwBuffer[0] = REP_EXPORT_NAMESPACE_SEC_TAG;
  272. dwBuffer[1] = dwSize;
  273. if ((WriteFile(g_hFile, dwBuffer, 8, &dwSize, NULL) == 0) || (dwSize != 8))
  274. {
  275. DEBUGTRACE((LOG_WBEMCORE, "Failed to write namespace security, %S.\n", Fixup(pNsRep->m_poName)));
  276. throw FAILURE_WRITE;
  277. }
  278. }
  279. void CRepExporter::DumpRootBlock(DBROOT *pRootBlock)
  280. {
  281. if (pRootBlock->m_dwFlags & DB_ROOT_INUSE)
  282. {
  283. DEBUGTRACE((LOG_WBEMCORE, "Failed to write file header block.\n"));
  284. throw FAILURE_DIRTY;
  285. }
  286. char *pBuffer = REP_EXPORT_FILE_START_TAG;
  287. DWORD dwSizeBuffer = strlen(pBuffer);
  288. DWORD dwSize = 0;
  289. if ((WriteFile(g_hFile, pBuffer, dwSizeBuffer, &dwSize, NULL) == 0) || (dwSize != dwSizeBuffer))
  290. {
  291. throw(FAILURE_WRITE);
  292. }
  293. DumpNamespace(Fixup((NSREP*)pRootBlock->m_poRootNs));
  294. DWORD dwBuffer[6];
  295. dwBuffer[0] = REP_EXPORT_FILE_END_TAG;
  296. dwBuffer[1] = REP_EXPORT_END_TAG_SIZE;
  297. memset(&(dwBuffer[2]), REP_EXPORT_END_TAG_MARKER, REP_EXPORT_END_TAG_SIZE);
  298. if ((WriteFile(g_hFile, dwBuffer, 24, &dwSize, NULL) == 0) || (dwSize != 24))
  299. {
  300. DEBUGTRACE((LOG_WBEMCORE, "Failed to write file trailer block.\n"));
  301. throw FAILURE_WRITE;
  302. }
  303. }
  304. void CRepExporter::DumpMMFHeader()
  305. {
  306. MMF_ARENA_HEADER *pMMFHeader = m_pDbArena->GetMMFHeader();
  307. DumpRootBlock(Fixup((DBROOT*)pMMFHeader->m_dwRootBlock));
  308. }
  309. int CRepExporter::Export(CMMFArena2 *pDbArena, const TCHAR *pszFilename)
  310. {
  311. DWORD dwVersion = NULL;
  312. HMODULE hModule = NULL;
  313. const char *pszDllName = NULL;
  314. int nRet = 0;
  315. m_pDbArena = pDbArena;
  316. g_hFile = CreateFile(pszFilename, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
  317. if (g_hFile != INVALID_HANDLE_VALUE)
  318. {
  319. try
  320. {
  321. DumpMMFHeader();
  322. CloseHandle(g_hFile);
  323. }
  324. catch (int dProblem)
  325. {
  326. switch(dProblem)
  327. {
  328. case FAILURE_DIRTY:
  329. DEBUGTRACE((LOG_WBEMCORE, "Repository is marked as corrupt, therefore cannot export it.\n"));
  330. break;
  331. case FAILURE_WRITE:
  332. DEBUGTRACE((LOG_WBEMCORE, "Failure writing to the export file. May be out of disk space, or may not have write access to this directory.\n"));
  333. break;
  334. default:
  335. DEBUGTRACE((LOG_WBEMCORE, "An unknown problem happened while traversing the repository.\n"));
  336. break;
  337. }
  338. CloseHandle(g_hFile);
  339. nRet = 1;
  340. }
  341. catch (...)
  342. {
  343. DEBUGTRACE((LOG_WBEMCORE, "Traversal of repository file failed. It may be corrupt.\n"));
  344. CloseHandle(g_hFile);
  345. DeleteFile(pszFilename);
  346. nRet = 1;
  347. }
  348. }
  349. else
  350. {
  351. DEBUGTRACE((LOG_WBEMCORE, "Failed to create file %s to export the repository.\n", pszFilename));
  352. nRet = 1;
  353. }
  354. return nRet;
  355. }