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.

455 lines
13 KiB

  1. #include <windows.h>
  2. #include <stdio.h>
  3. #include <pagemgr.h>
  4. #include <varobjheap.h>
  5. #include <sync.h>
  6. #include <wbemcomn.h>
  7. #define MAP_LEADING_SIGNATURE 0xABCD
  8. #define MAP_TRAILING_SIGNATURE 0xDCBA
  9. typedef std::vector <DWORD, wbem_allocator<DWORD> > XFilesMap;
  10. DWORD ReadMapFile(const wchar_t *sFilename, XFilesMap &aPageMap, XFilesMap & aPhysFreeList);
  11. DWORD DumpHeapAdminPages(const wchar_t *sFilename, XFilesMap &aHeapMap, XFilesMap &aHeapFreeList);
  12. DWORD GetHeapManagedPageCount(const wchar_t *sFilename, XFilesMap &aHeapMap, DWORD &dwNumAdminPages, DWORD &dwNumMultiBlockPages, DWORD &dwNumMultiBlockObjects);
  13. DWORD GetMapUsageCount(XFilesMap &aHeapMap, DWORD &dwHeapMapUsed, DWORD &dwHeapMapFree);
  14. DWORD DumpMap(XFilesMap &aMap);
  15. void __cdecl main(int argc, char *argv[ ])
  16. {
  17. printf("WMI XFiles repository dumper\n\n");
  18. bool bDumpHeapAdminPage = false;
  19. bool bDumpTreeMap = false;
  20. bool bDumpHeapMap = false;
  21. for (int i = 1; i != argc; i++)
  22. {
  23. if ((_stricmp(argv[i], "/?") == 0) ||
  24. (_stricmp(argv[i], "-?") == 0))
  25. {
  26. printf("Usage: DumpTool.exe /? - display this message\n"
  27. " DumpTool.exe /DumpAdminPages - dumps the heap admin tables\n"
  28. " DumpTool.exe /DumpTreeMap - dumps the tree map usage\n"
  29. " DumpTool.exe /DumpHeapMap - dumps the heap map usage\n");
  30. return;
  31. }
  32. else if (_stricmp(argv[i], "/DumpAdminPages") == 0)
  33. {
  34. bDumpHeapAdminPage = true;
  35. }
  36. else if (_stricmp(argv[i], "/DumpTreeMap") == 0)
  37. {
  38. bDumpTreeMap = true;
  39. }
  40. else if (_stricmp(argv[i], "/DumpHeapMap") == 0)
  41. {
  42. bDumpHeapMap = true;
  43. }
  44. }
  45. DWORD dwRet;
  46. XFilesMap aBTreeMap;
  47. XFilesMap aBTreeFreeList;
  48. DWORD dwBTreeSize = 0;
  49. DWORD dwBTreeUsed = 0;
  50. DWORD dwBTreeFree = 0;
  51. XFilesMap aHeapMap;
  52. XFilesMap aHeapFreeList;
  53. DWORD dwHeapSize = 0;
  54. DWORD dwHeapUsed = 0;
  55. DWORD dwHeapFree = 0;
  56. //Read MAP Files
  57. dwRet = ReadMapFile(L"index.map", aBTreeMap, aBTreeFreeList);
  58. if (dwRet)
  59. {
  60. printf("Failed to retrieve index.map details. Please run from within the repository\\fs directory\n");
  61. return;
  62. }
  63. GetMapUsageCount(aBTreeMap, dwBTreeUsed, dwBTreeFree);
  64. dwRet = ReadMapFile(L"objects.map", aHeapMap, aHeapFreeList);
  65. if (dwRet)
  66. {
  67. printf("Failed to retrieve objects.map details. Please run from within the repository\\fs directory\n");
  68. return;
  69. }
  70. GetMapUsageCount(aHeapMap, dwHeapUsed, dwHeapFree);
  71. WIN32_FILE_ATTRIBUTE_DATA fileInfo;
  72. dwRet = GetFileAttributesEx(L"INDEX.BTR", GetFileExInfoStandard, &fileInfo);
  73. if (dwRet == 0)
  74. {
  75. printf("Failed to retrieve size of index.btr file\n");
  76. return;
  77. }
  78. dwBTreeSize = fileInfo.nFileSizeLow / WMIREP_PAGE_SIZE;
  79. dwRet = GetFileAttributesEx(L"OBJECTS.DATA", GetFileExInfoStandard, &fileInfo);
  80. if (dwRet == 0)
  81. {
  82. printf("Failed to retrieve size of objects.data file\n");
  83. return;
  84. }
  85. dwHeapSize = fileInfo.nFileSizeLow / WMIREP_PAGE_SIZE;
  86. //Dump MAP file usage and free space sumary
  87. printf("BTree has %lu pages in it, of which %lu pages are in use and %lu pages are free\n",
  88. dwBTreeSize, dwBTreeUsed, dwBTreeSize - dwBTreeUsed);
  89. printf("Heap has %lu pages in it, of which %lu pages are in use and %lu pages are free\n",
  90. dwHeapSize, dwHeapUsed, dwHeapSize - dwHeapUsed);
  91. //Get number of managed pages for heap...
  92. DWORD dwNumAdminPages = 0;
  93. DWORD dwNumMultiBlockPages = 0;
  94. DWORD dwNumMultiBlockObjects = 0;
  95. dwRet = GetHeapManagedPageCount(L"OBJECTS.DATA", aHeapMap, dwNumAdminPages, dwNumMultiBlockPages, dwNumMultiBlockObjects);
  96. if (dwRet)
  97. {
  98. printf("Failed to retrieve number of pages used in object heap\n");
  99. return;
  100. }
  101. printf("Heap has %lu admin pages, \n\t%lu pages used for small block allocation, total of %lu small block allocations, \n\t%lu pages for large block allocations\n",
  102. dwNumAdminPages,
  103. dwNumMultiBlockPages,
  104. dwNumMultiBlockObjects,
  105. dwHeapSize - (dwHeapSize - dwHeapUsed) - dwNumAdminPages - dwNumMultiBlockPages);
  106. if (bDumpHeapAdminPage)
  107. {
  108. dwRet = DumpHeapAdminPages(L"OBJECTS.DATA", aHeapMap, aHeapFreeList);
  109. if (dwRet)
  110. {
  111. printf("Failed to dump the admin pages in the heap\n");
  112. return;
  113. }
  114. }
  115. if (bDumpTreeMap)
  116. {
  117. printf("**** BTree MAP Usage ****\n");
  118. DumpMap(aBTreeMap);
  119. }
  120. if (bDumpHeapMap)
  121. {
  122. printf("**** Heap MAP Usage ****\n");
  123. DumpMap(aHeapMap);
  124. }
  125. }
  126. DWORD ReadMapFile(const wchar_t *sFilename, XFilesMap &aPageMap,XFilesMap & aPhysFreeList)
  127. {
  128. BOOL bRes;
  129. HANDLE hFile = CreateFileW(sFilename, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
  130. if (hFile == INVALID_HANDLE_VALUE)
  131. {
  132. DWORD dwRet = GetLastError();
  133. return dwRet;
  134. }
  135. AutoClose _(hFile);
  136. // If here, read it.
  137. // =================
  138. DWORD dwSignature = 0;
  139. DWORD dwRead = 0;
  140. bRes = ReadFile(hFile, &dwSignature, sizeof(DWORD), &dwRead, 0);
  141. if (!bRes || dwRead != sizeof(DWORD) || dwSignature != MAP_LEADING_SIGNATURE)
  142. {
  143. return ERROR_INVALID_DATA;
  144. }
  145. // Read transaction version.
  146. // =========================
  147. DWORD dwTransVersion;
  148. bRes = ReadFile(hFile, &dwTransVersion, sizeof(DWORD), &dwRead, 0);
  149. if (!bRes || dwRead != sizeof(DWORD))
  150. {
  151. return ERROR_INVALID_DATA;
  152. }
  153. // Read in physical page count.
  154. // ============================
  155. DWORD dwPhysPages;
  156. bRes = ReadFile(hFile, &dwPhysPages, sizeof(DWORD), &dwRead, 0);
  157. if (!bRes || dwRead != sizeof(DWORD))
  158. {
  159. return ERROR_INVALID_DATA;
  160. }
  161. // Read in the page map length and page map.
  162. // =========================================
  163. DWORD dwNumPages = 0;
  164. bRes = ReadFile(hFile, &dwNumPages, sizeof(DWORD), &dwRead, 0);
  165. if (!bRes || dwRead != sizeof(DWORD))
  166. {
  167. return ERROR_INVALID_DATA;
  168. }
  169. try
  170. {
  171. aPageMap.resize(dwNumPages);
  172. }
  173. catch (CX_MemoryException &)
  174. {
  175. return ERROR_OUTOFMEMORY;
  176. }
  177. bRes = ReadFile(hFile, &aPageMap[0], sizeof(DWORD)*dwNumPages, &dwRead, 0);
  178. if (!bRes || dwRead != sizeof(DWORD)*dwNumPages)
  179. return ERROR_INVALID_DATA;
  180. // Now, read in the physical free list.
  181. // ====================================
  182. DWORD dwFreeListSize = 0;
  183. bRes = ReadFile(hFile, &dwFreeListSize, sizeof(DWORD), &dwRead, 0);
  184. if (!bRes || dwRead != sizeof(DWORD))
  185. {
  186. return ERROR_INVALID_DATA;
  187. }
  188. try
  189. {
  190. aPhysFreeList.resize(dwFreeListSize);
  191. }
  192. catch (CX_MemoryException &)
  193. {
  194. return ERROR_OUTOFMEMORY;
  195. }
  196. bRes = ReadFile(hFile, &aPhysFreeList[0], sizeof(DWORD)*dwFreeListSize, &dwRead, 0);
  197. if (!bRes || dwRead != sizeof(DWORD)*dwFreeListSize)
  198. {
  199. return ERROR_INVALID_DATA;
  200. }
  201. // Read trailing signature.
  202. // ========================
  203. bRes = ReadFile(hFile, &dwSignature, sizeof(DWORD), &dwRead, 0);
  204. if (!bRes || dwRead != sizeof(DWORD) || dwSignature != MAP_TRAILING_SIGNATURE)
  205. {
  206. return ERROR_INVALID_DATA;
  207. }
  208. return ERROR_SUCCESS;
  209. }
  210. DWORD DumpHeapAdminPages(const wchar_t *sFilename, XFilesMap &aHeapMap, XFilesMap &aHeapFreeList)
  211. {
  212. //Open the file...
  213. HANDLE hFile = CreateFile(sFilename, GENERIC_READ, FILE_SHARE_WRITE|FILE_SHARE_READ, NULL, OPEN_EXISTING, 0,NULL);
  214. if (hFile == INVALID_HANDLE_VALUE)
  215. return GetLastError();
  216. HANDLE hMapping = CreateFileMapping(hFile, NULL, PAGE_READONLY, 0, 0, NULL);
  217. if (hMapping == NULL)
  218. {
  219. DWORD dwErr = GetLastError();
  220. CloseHandle(hFile);
  221. return dwErr;
  222. }
  223. BYTE *pObj = (BYTE *)MapViewOfFile(hMapping, FILE_MAP_READ, 0,0,0);
  224. if (pObj == NULL)
  225. {
  226. DWORD dwErr = GetLastError();
  227. CloseHandle(hMapping);
  228. CloseHandle(hFile);
  229. return dwErr;;
  230. }
  231. //Do stuff...
  232. DWORD dwVirtualPageId = 0;
  233. DWORD dwTotalObjectCount = 0;
  234. printf("Heap admin page dump...\n");
  235. do
  236. {
  237. DWORD dwPhysicalPageId = aHeapMap[dwVirtualPageId];
  238. VarObjHeapAdminPage *pAdminPageHeader = (VarObjHeapAdminPage *)(pObj + (dwPhysicalPageId * WMIREP_PAGE_SIZE));
  239. VarObjHeapFreeList *pAdminPageEntry = (VarObjHeapFreeList *)((BYTE*)pAdminPageHeader + sizeof(VarObjHeapAdminPage));
  240. printf("Admin page %lu (physical page %lu): number of page entries %lu\n", dwVirtualPageId, dwPhysicalPageId, pAdminPageHeader->dwNumberEntriesOnPage);
  241. for (DWORD dwIndex = 0; dwIndex != pAdminPageHeader->dwNumberEntriesOnPage; dwIndex++)
  242. {
  243. DWORD dwNumObjectsOnPage = 0;
  244. VarObjObjOffsetEntry *pObjPage = (VarObjObjOffsetEntry*)(pObj + (aHeapMap[pAdminPageEntry[dwIndex].dwPageId] * WMIREP_PAGE_SIZE));
  245. for (DWORD dwIndex2 = 0; pObjPage[dwIndex2].dwOffsetId != 0; dwIndex2++)
  246. {
  247. dwNumObjectsOnPage++;
  248. }
  249. printf("\tPage % 6lu (physical page % 6lu): %4lu bytes free (% 2lu%%), %4lu objects on page\n",
  250. pAdminPageEntry[dwIndex].dwPageId,
  251. aHeapMap[pAdminPageEntry[dwIndex].dwPageId],
  252. pAdminPageEntry[dwIndex].dwFreeSpace,
  253. (pAdminPageEntry[dwIndex].dwFreeSpace * 100) / WMIREP_PAGE_SIZE,
  254. dwNumObjectsOnPage);
  255. }
  256. dwVirtualPageId = pAdminPageHeader->dwNextAdminPage;
  257. } while (dwVirtualPageId != 0);
  258. //Tidy up
  259. UnmapViewOfFile(pObj);
  260. CloseHandle(hMapping);
  261. CloseHandle(hFile);
  262. return ERROR_SUCCESS;
  263. }
  264. DWORD GetHeapManagedPageCount(const wchar_t *sFilename, XFilesMap &aHeapMap, DWORD &dwNumAdminPages, DWORD &dwNumMultiBlockPages, DWORD &dwNumMultiBlockObjects)
  265. {
  266. //Open the file...
  267. HANDLE hFile = CreateFile(sFilename, GENERIC_READ, FILE_SHARE_WRITE|FILE_SHARE_READ, NULL, OPEN_EXISTING, 0,NULL);
  268. if (hFile == INVALID_HANDLE_VALUE)
  269. return GetLastError();
  270. HANDLE hMapping = CreateFileMapping(hFile, NULL, PAGE_READONLY, 0, 0, NULL);
  271. if (hMapping == NULL)
  272. {
  273. DWORD dwErr = GetLastError();
  274. CloseHandle(hFile);
  275. return dwErr;
  276. }
  277. BYTE *pObj = (BYTE *)MapViewOfFile(hMapping, FILE_MAP_READ, 0,0,0);
  278. if (pObj == NULL)
  279. {
  280. DWORD dwErr = GetLastError();
  281. CloseHandle(hMapping);
  282. CloseHandle(hFile);
  283. return dwErr;;
  284. }
  285. //Do stuff...
  286. DWORD dwVirtualPageId = 0;
  287. do
  288. {
  289. dwNumAdminPages++;
  290. DWORD dwPhysicalPageId = aHeapMap[dwVirtualPageId];
  291. VarObjHeapAdminPage *pAdminPageHeader = (VarObjHeapAdminPage *)(pObj + (dwPhysicalPageId * WMIREP_PAGE_SIZE));
  292. VarObjHeapFreeList *pAdminPageEntry = (VarObjHeapFreeList *)((BYTE*)pAdminPageHeader + sizeof(VarObjHeapAdminPage));
  293. for (DWORD dwIndex = 0; dwIndex != pAdminPageHeader->dwNumberEntriesOnPage; dwIndex++)
  294. {
  295. dwNumMultiBlockPages++;
  296. DWORD dwNumObjectsOnPage = 0;
  297. VarObjObjOffsetEntry *pObjPage = (VarObjObjOffsetEntry*)(pObj + (aHeapMap[pAdminPageEntry[dwIndex].dwPageId] * WMIREP_PAGE_SIZE));
  298. for (DWORD dwIndex2 = 0; pObjPage[dwIndex2].dwOffsetId != 0; dwIndex2++)
  299. {
  300. dwNumMultiBlockObjects++;
  301. }
  302. }
  303. dwVirtualPageId = pAdminPageHeader->dwNextAdminPage;
  304. } while (dwVirtualPageId != 0);
  305. //Tidy up
  306. UnmapViewOfFile(pObj);
  307. CloseHandle(hMapping);
  308. CloseHandle(hFile);
  309. return ERROR_SUCCESS;
  310. }
  311. DWORD GetMapUsageCount(XFilesMap &aMap, DWORD &dwMapUsed, DWORD &dwMapFree)
  312. {
  313. for (DWORD i = 0; i < aMap.size(); i++)
  314. {
  315. if (aMap[i] == WMIREP_INVALID_PAGE)
  316. dwMapFree++;
  317. else
  318. dwMapUsed++;
  319. }
  320. return ERROR_SUCCESS;
  321. }
  322. void ShellSort(XFilesMap &Array)
  323. {
  324. for (int nInterval = 1; nInterval < Array.size() / 9; nInterval = nInterval * 3 + 1);
  325. while (nInterval)
  326. {
  327. for (int iCursor = nInterval; iCursor < Array.size(); iCursor++)
  328. {
  329. int iBackscan = iCursor;
  330. while (iBackscan - nInterval >= 0 && Array[iBackscan] < Array[iBackscan-nInterval])
  331. {
  332. DWORD dwTemp = Array[iBackscan-nInterval];
  333. Array[iBackscan-nInterval] = Array[iBackscan];
  334. Array[iBackscan] = dwTemp;
  335. iBackscan -= nInterval;
  336. }
  337. }
  338. nInterval /= 3;
  339. }
  340. }
  341. DWORD DumpMap(XFilesMap &aMap)
  342. {
  343. //Need to sort it... and need our own copy...
  344. XFilesMap aNewMap = aMap;
  345. ShellSort(aNewMap);
  346. printf("**** Usage dump... **** \n");
  347. DWORD dwStartId = aNewMap[0];
  348. for (DWORD dwOffset = 1; dwOffset < aNewMap.size(); dwOffset++)
  349. {
  350. if (dwStartId == 0xFFFFFFFF)
  351. break;
  352. //Work up to the end of this run
  353. for (DWORD dwCurrentRun = 1; (dwStartId+dwCurrentRun) == aNewMap[dwOffset]; dwOffset++, dwCurrentRun++)
  354. {
  355. }
  356. //Finished slot... dump usage use
  357. if (dwStartId == aNewMap[dwOffset-1])
  358. {
  359. //Single location slot...
  360. printf("% 6lu Used\n", dwStartId);
  361. }
  362. else
  363. {
  364. //Multiple location slot...
  365. printf("% 6lu - % 6lu Used\n", dwStartId, aNewMap[dwOffset-1]);
  366. }
  367. if (dwOffset+1 <= aNewMap.size())
  368. {
  369. //Dump free space usage now
  370. if (aNewMap[dwOffset-1]+1 == aNewMap[dwOffset]-1)
  371. {
  372. //Single location slot...
  373. printf("% 6lu Free\n", aNewMap[dwOffset-1]+1);
  374. }
  375. else
  376. {
  377. //Multiple location slot...
  378. printf("% 6lu - % 6lu Free\n", aNewMap[dwOffset-1]+1, aNewMap[dwOffset]-1);
  379. }
  380. dwStartId = aNewMap[dwOffset];
  381. }
  382. }
  383. return ERROR_SUCCESS;
  384. }