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.
 
 
 
 
 
 

456 lines
13 KiB

#include <windows.h>
#include <stdio.h>
#include <pagemgr.h>
#include <varobjheap.h>
#include <sync.h>
#include <wbemcomn.h>
#define MAP_LEADING_SIGNATURE 0xABCD
#define MAP_TRAILING_SIGNATURE 0xDCBA
typedef std::vector <DWORD, wbem_allocator<DWORD> > XFilesMap;
DWORD ReadMapFile(const wchar_t *sFilename, XFilesMap &aPageMap, XFilesMap & aPhysFreeList);
DWORD DumpHeapAdminPages(const wchar_t *sFilename, XFilesMap &aHeapMap, XFilesMap &aHeapFreeList);
DWORD GetHeapManagedPageCount(const wchar_t *sFilename, XFilesMap &aHeapMap, DWORD &dwNumAdminPages, DWORD &dwNumMultiBlockPages, DWORD &dwNumMultiBlockObjects);
DWORD GetMapUsageCount(XFilesMap &aHeapMap, DWORD &dwHeapMapUsed, DWORD &dwHeapMapFree);
DWORD DumpMap(XFilesMap &aMap);
void __cdecl main(int argc, char *argv[ ])
{
printf("WMI XFiles repository dumper\n\n");
bool bDumpHeapAdminPage = false;
bool bDumpTreeMap = false;
bool bDumpHeapMap = false;
for (int i = 1; i != argc; i++)
{
if ((_stricmp(argv[i], "/?") == 0) ||
(_stricmp(argv[i], "-?") == 0))
{
printf("Usage: DumpTool.exe /? - display this message\n"
" DumpTool.exe /DumpAdminPages - dumps the heap admin tables\n"
" DumpTool.exe /DumpTreeMap - dumps the tree map usage\n"
" DumpTool.exe /DumpHeapMap - dumps the heap map usage\n");
return;
}
else if (_stricmp(argv[i], "/DumpAdminPages") == 0)
{
bDumpHeapAdminPage = true;
}
else if (_stricmp(argv[i], "/DumpTreeMap") == 0)
{
bDumpTreeMap = true;
}
else if (_stricmp(argv[i], "/DumpHeapMap") == 0)
{
bDumpHeapMap = true;
}
}
DWORD dwRet;
XFilesMap aBTreeMap;
XFilesMap aBTreeFreeList;
DWORD dwBTreeSize = 0;
DWORD dwBTreeUsed = 0;
DWORD dwBTreeFree = 0;
XFilesMap aHeapMap;
XFilesMap aHeapFreeList;
DWORD dwHeapSize = 0;
DWORD dwHeapUsed = 0;
DWORD dwHeapFree = 0;
//Read MAP Files
dwRet = ReadMapFile(L"index.map", aBTreeMap, aBTreeFreeList);
if (dwRet)
{
printf("Failed to retrieve index.map details. Please run from within the repository\\fs directory\n");
return;
}
GetMapUsageCount(aBTreeMap, dwBTreeUsed, dwBTreeFree);
dwRet = ReadMapFile(L"objects.map", aHeapMap, aHeapFreeList);
if (dwRet)
{
printf("Failed to retrieve objects.map details. Please run from within the repository\\fs directory\n");
return;
}
GetMapUsageCount(aHeapMap, dwHeapUsed, dwHeapFree);
WIN32_FILE_ATTRIBUTE_DATA fileInfo;
dwRet = GetFileAttributesEx(L"INDEX.BTR", GetFileExInfoStandard, &fileInfo);
if (dwRet == 0)
{
printf("Failed to retrieve size of index.btr file\n");
return;
}
dwBTreeSize = fileInfo.nFileSizeLow / WMIREP_PAGE_SIZE;
dwRet = GetFileAttributesEx(L"OBJECTS.DATA", GetFileExInfoStandard, &fileInfo);
if (dwRet == 0)
{
printf("Failed to retrieve size of objects.data file\n");
return;
}
dwHeapSize = fileInfo.nFileSizeLow / WMIREP_PAGE_SIZE;
//Dump MAP file usage and free space sumary
printf("BTree has %lu pages in it, of which %lu pages are in use and %lu pages are free\n",
dwBTreeSize, dwBTreeUsed, dwBTreeSize - dwBTreeUsed);
printf("Heap has %lu pages in it, of which %lu pages are in use and %lu pages are free\n",
dwHeapSize, dwHeapUsed, dwHeapSize - dwHeapUsed);
//Get number of managed pages for heap...
DWORD dwNumAdminPages = 0;
DWORD dwNumMultiBlockPages = 0;
DWORD dwNumMultiBlockObjects = 0;
dwRet = GetHeapManagedPageCount(L"OBJECTS.DATA", aHeapMap, dwNumAdminPages, dwNumMultiBlockPages, dwNumMultiBlockObjects);
if (dwRet)
{
printf("Failed to retrieve number of pages used in object heap\n");
return;
}
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",
dwNumAdminPages,
dwNumMultiBlockPages,
dwNumMultiBlockObjects,
dwHeapSize - (dwHeapSize - dwHeapUsed) - dwNumAdminPages - dwNumMultiBlockPages);
if (bDumpHeapAdminPage)
{
dwRet = DumpHeapAdminPages(L"OBJECTS.DATA", aHeapMap, aHeapFreeList);
if (dwRet)
{
printf("Failed to dump the admin pages in the heap\n");
return;
}
}
if (bDumpTreeMap)
{
printf("**** BTree MAP Usage ****\n");
DumpMap(aBTreeMap);
}
if (bDumpHeapMap)
{
printf("**** Heap MAP Usage ****\n");
DumpMap(aHeapMap);
}
}
DWORD ReadMapFile(const wchar_t *sFilename, XFilesMap &aPageMap,XFilesMap & aPhysFreeList)
{
BOOL bRes;
HANDLE hFile = CreateFileW(sFilename, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
if (hFile == INVALID_HANDLE_VALUE)
{
DWORD dwRet = GetLastError();
return dwRet;
}
AutoClose _(hFile);
// If here, read it.
// =================
DWORD dwSignature = 0;
DWORD dwRead = 0;
bRes = ReadFile(hFile, &dwSignature, sizeof(DWORD), &dwRead, 0);
if (!bRes || dwRead != sizeof(DWORD) || dwSignature != MAP_LEADING_SIGNATURE)
{
return ERROR_INVALID_DATA;
}
// Read transaction version.
// =========================
DWORD dwTransVersion;
bRes = ReadFile(hFile, &dwTransVersion, sizeof(DWORD), &dwRead, 0);
if (!bRes || dwRead != sizeof(DWORD))
{
return ERROR_INVALID_DATA;
}
// Read in physical page count.
// ============================
DWORD dwPhysPages;
bRes = ReadFile(hFile, &dwPhysPages, sizeof(DWORD), &dwRead, 0);
if (!bRes || dwRead != sizeof(DWORD))
{
return ERROR_INVALID_DATA;
}
// Read in the page map length and page map.
// =========================================
DWORD dwNumPages = 0;
bRes = ReadFile(hFile, &dwNumPages, sizeof(DWORD), &dwRead, 0);
if (!bRes || dwRead != sizeof(DWORD))
{
return ERROR_INVALID_DATA;
}
try
{
aPageMap.resize(dwNumPages);
}
catch (CX_MemoryException &)
{
return ERROR_OUTOFMEMORY;
}
bRes = ReadFile(hFile, &aPageMap[0], sizeof(DWORD)*dwNumPages, &dwRead, 0);
if (!bRes || dwRead != sizeof(DWORD)*dwNumPages)
return ERROR_INVALID_DATA;
// Now, read in the physical free list.
// ====================================
DWORD dwFreeListSize = 0;
bRes = ReadFile(hFile, &dwFreeListSize, sizeof(DWORD), &dwRead, 0);
if (!bRes || dwRead != sizeof(DWORD))
{
return ERROR_INVALID_DATA;
}
try
{
aPhysFreeList.resize(dwFreeListSize);
}
catch (CX_MemoryException &)
{
return ERROR_OUTOFMEMORY;
}
bRes = ReadFile(hFile, &aPhysFreeList[0], sizeof(DWORD)*dwFreeListSize, &dwRead, 0);
if (!bRes || dwRead != sizeof(DWORD)*dwFreeListSize)
{
return ERROR_INVALID_DATA;
}
// Read trailing signature.
// ========================
bRes = ReadFile(hFile, &dwSignature, sizeof(DWORD), &dwRead, 0);
if (!bRes || dwRead != sizeof(DWORD) || dwSignature != MAP_TRAILING_SIGNATURE)
{
return ERROR_INVALID_DATA;
}
return ERROR_SUCCESS;
}
DWORD DumpHeapAdminPages(const wchar_t *sFilename, XFilesMap &aHeapMap, XFilesMap &aHeapFreeList)
{
//Open the file...
HANDLE hFile = CreateFile(sFilename, GENERIC_READ, FILE_SHARE_WRITE|FILE_SHARE_READ, NULL, OPEN_EXISTING, 0,NULL);
if (hFile == INVALID_HANDLE_VALUE)
return GetLastError();
HANDLE hMapping = CreateFileMapping(hFile, NULL, PAGE_READONLY, 0, 0, NULL);
if (hMapping == NULL)
{
DWORD dwErr = GetLastError();
CloseHandle(hFile);
return dwErr;
}
BYTE *pObj = (BYTE *)MapViewOfFile(hMapping, FILE_MAP_READ, 0,0,0);
if (pObj == NULL)
{
DWORD dwErr = GetLastError();
CloseHandle(hMapping);
CloseHandle(hFile);
return dwErr;;
}
//Do stuff...
DWORD dwVirtualPageId = 0;
DWORD dwTotalObjectCount = 0;
printf("Heap admin page dump...\n");
do
{
DWORD dwPhysicalPageId = aHeapMap[dwVirtualPageId];
VarObjHeapAdminPage *pAdminPageHeader = (VarObjHeapAdminPage *)(pObj + (dwPhysicalPageId * WMIREP_PAGE_SIZE));
VarObjHeapFreeList *pAdminPageEntry = (VarObjHeapFreeList *)((BYTE*)pAdminPageHeader + sizeof(VarObjHeapAdminPage));
printf("Admin page %lu (physical page %lu): number of page entries %lu\n", dwVirtualPageId, dwPhysicalPageId, pAdminPageHeader->dwNumberEntriesOnPage);
for (DWORD dwIndex = 0; dwIndex != pAdminPageHeader->dwNumberEntriesOnPage; dwIndex++)
{
DWORD dwNumObjectsOnPage = 0;
VarObjObjOffsetEntry *pObjPage = (VarObjObjOffsetEntry*)(pObj + (aHeapMap[pAdminPageEntry[dwIndex].dwPageId] * WMIREP_PAGE_SIZE));
for (DWORD dwIndex2 = 0; pObjPage[dwIndex2].dwOffsetId != 0; dwIndex2++)
{
dwNumObjectsOnPage++;
}
printf("\tPage % 6lu (physical page % 6lu): %4lu bytes free (% 2lu%%), %4lu objects on page\n",
pAdminPageEntry[dwIndex].dwPageId,
aHeapMap[pAdminPageEntry[dwIndex].dwPageId],
pAdminPageEntry[dwIndex].dwFreeSpace,
(pAdminPageEntry[dwIndex].dwFreeSpace * 100) / WMIREP_PAGE_SIZE,
dwNumObjectsOnPage);
}
dwVirtualPageId = pAdminPageHeader->dwNextAdminPage;
} while (dwVirtualPageId != 0);
//Tidy up
UnmapViewOfFile(pObj);
CloseHandle(hMapping);
CloseHandle(hFile);
return ERROR_SUCCESS;
}
DWORD GetHeapManagedPageCount(const wchar_t *sFilename, XFilesMap &aHeapMap, DWORD &dwNumAdminPages, DWORD &dwNumMultiBlockPages, DWORD &dwNumMultiBlockObjects)
{
//Open the file...
HANDLE hFile = CreateFile(sFilename, GENERIC_READ, FILE_SHARE_WRITE|FILE_SHARE_READ, NULL, OPEN_EXISTING, 0,NULL);
if (hFile == INVALID_HANDLE_VALUE)
return GetLastError();
HANDLE hMapping = CreateFileMapping(hFile, NULL, PAGE_READONLY, 0, 0, NULL);
if (hMapping == NULL)
{
DWORD dwErr = GetLastError();
CloseHandle(hFile);
return dwErr;
}
BYTE *pObj = (BYTE *)MapViewOfFile(hMapping, FILE_MAP_READ, 0,0,0);
if (pObj == NULL)
{
DWORD dwErr = GetLastError();
CloseHandle(hMapping);
CloseHandle(hFile);
return dwErr;;
}
//Do stuff...
DWORD dwVirtualPageId = 0;
do
{
dwNumAdminPages++;
DWORD dwPhysicalPageId = aHeapMap[dwVirtualPageId];
VarObjHeapAdminPage *pAdminPageHeader = (VarObjHeapAdminPage *)(pObj + (dwPhysicalPageId * WMIREP_PAGE_SIZE));
VarObjHeapFreeList *pAdminPageEntry = (VarObjHeapFreeList *)((BYTE*)pAdminPageHeader + sizeof(VarObjHeapAdminPage));
for (DWORD dwIndex = 0; dwIndex != pAdminPageHeader->dwNumberEntriesOnPage; dwIndex++)
{
dwNumMultiBlockPages++;
DWORD dwNumObjectsOnPage = 0;
VarObjObjOffsetEntry *pObjPage = (VarObjObjOffsetEntry*)(pObj + (aHeapMap[pAdminPageEntry[dwIndex].dwPageId] * WMIREP_PAGE_SIZE));
for (DWORD dwIndex2 = 0; pObjPage[dwIndex2].dwOffsetId != 0; dwIndex2++)
{
dwNumMultiBlockObjects++;
}
}
dwVirtualPageId = pAdminPageHeader->dwNextAdminPage;
} while (dwVirtualPageId != 0);
//Tidy up
UnmapViewOfFile(pObj);
CloseHandle(hMapping);
CloseHandle(hFile);
return ERROR_SUCCESS;
}
DWORD GetMapUsageCount(XFilesMap &aMap, DWORD &dwMapUsed, DWORD &dwMapFree)
{
for (DWORD i = 0; i < aMap.size(); i++)
{
if (aMap[i] == WMIREP_INVALID_PAGE)
dwMapFree++;
else
dwMapUsed++;
}
return ERROR_SUCCESS;
}
void ShellSort(XFilesMap &Array)
{
for (int nInterval = 1; nInterval < Array.size() / 9; nInterval = nInterval * 3 + 1);
while (nInterval)
{
for (int iCursor = nInterval; iCursor < Array.size(); iCursor++)
{
int iBackscan = iCursor;
while (iBackscan - nInterval >= 0 && Array[iBackscan] < Array[iBackscan-nInterval])
{
DWORD dwTemp = Array[iBackscan-nInterval];
Array[iBackscan-nInterval] = Array[iBackscan];
Array[iBackscan] = dwTemp;
iBackscan -= nInterval;
}
}
nInterval /= 3;
}
}
DWORD DumpMap(XFilesMap &aMap)
{
//Need to sort it... and need our own copy...
XFilesMap aNewMap = aMap;
ShellSort(aNewMap);
printf("**** Usage dump... **** \n");
DWORD dwStartId = aNewMap[0];
for (DWORD dwOffset = 1; dwOffset < aNewMap.size(); dwOffset++)
{
if (dwStartId == 0xFFFFFFFF)
break;
//Work up to the end of this run
for (DWORD dwCurrentRun = 1; (dwStartId+dwCurrentRun) == aNewMap[dwOffset]; dwOffset++, dwCurrentRun++)
{
}
//Finished slot... dump usage use
if (dwStartId == aNewMap[dwOffset-1])
{
//Single location slot...
printf("% 6lu Used\n", dwStartId);
}
else
{
//Multiple location slot...
printf("% 6lu - % 6lu Used\n", dwStartId, aNewMap[dwOffset-1]);
}
if (dwOffset+1 <= aNewMap.size())
{
//Dump free space usage now
if (aNewMap[dwOffset-1]+1 == aNewMap[dwOffset]-1)
{
//Single location slot...
printf("% 6lu Free\n", aNewMap[dwOffset-1]+1);
}
else
{
//Multiple location slot...
printf("% 6lu - % 6lu Free\n", aNewMap[dwOffset-1]+1, aNewMap[dwOffset]-1);
}
dwStartId = aNewMap[dwOffset];
}
}
return ERROR_SUCCESS;
}