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.
 
 
 
 
 
 

602 lines
17 KiB

/*++
Copyright (c) 1992-2001 Microsoft Corporation
Module Name:
diskspace.cpp
Abstract:
WinDbg Extension Api
Environment:
Kernel Mode.
Revision History:
Mike McCracken (mmccr) 09/17/2001
Prints out free space for a specifed volume
--*/
#include "precomp.h"
#pragma hdrstop
ULONG GetUNICODE_STRING(ULONG64 ul64Address, CHAR *pszBuffer, ULONG ulSize)
{
ULONG64 ul64Buffer = 0;
ULONG ulLength = 0;
ULONG ulBytesRead = 0;
WCHAR wszLocalBuffer[MAX_PATH + 1] = {0};
if ((!pszBuffer) || (!ulSize))
{
return E_FAIL;
}
if (GetFieldValue(ul64Address, "nt!_UNICODE_STRING",
"Length", ulLength))
{
dprintf("Cannot get UNICODE_STRING length!\n");
return E_FAIL;
}
if (GetFieldValue(ul64Address, "nt!_UNICODE_STRING",
"Buffer", ul64Buffer))
{
dprintf("Cannot get UNICODE_STRING buffer!\n");
return E_FAIL;
}
if (!ReadMemory(ul64Buffer,
wszLocalBuffer,
(ulLength < (MAX_PATH * 2)) ? ulLength : (MAX_PATH * 2),
&ulBytesRead))
{
dprintf("Failed ReadMemory at 0x%I64x!\n", ul64Buffer);
return E_FAIL;
}
wcstombs(pszBuffer, wszLocalBuffer, ulSize);
return S_OK;
}
ULONG64 GetObpRootDirectoryObjectAddress()
{
ULONG64 ul64Temp = 0;
ULONG64 ul64ObjRoot = 0;
//Get the address of the pointer
GetExpressionEx("nt!ObpRootDirectoryObject", &ul64Temp, NULL);
//Get the value in the pointer
ReadPtr(ul64Temp, &ul64ObjRoot);
return ul64ObjRoot;
}
ULONG GetNumberOfHashBuckets()
{
FIELD_INFO Field = {(PUCHAR)"HashBuckets", NULL, 0, DBG_DUMP_FIELD_NO_CALLBACK_REQ , 0, NULL};
SYM_DUMP_PARAM Sym = {sizeof(SYM_DUMP_PARAM), (PUCHAR)"nt!_OBJECT_DIRECTORY", DBG_DUMP_NO_PRINT, 0,
NULL, NULL, NULL, sizeof (Field) / sizeof(FIELD_INFO), &Field};
// Get the size of the HashBuckets member
if (Ioctl(IG_DUMP_SYMBOL_INFO,
&Sym,
sizeof(Sym)))
{
dprintf("Failed to get size of HashBuckets!\n");
return 0;
}
return (Field.size / (IsPtr64() ? 8 : 4));
}
ULONG GetObjectTypeName(ULONG64 ul64Object, CHAR *pszTypeName, ULONG ulSize)
{
ULONG ulTypeNameOffset = 0;
ULONG ulObjectBodyOffset = 0;
ULONG64 ul64Type = 0;
// Get the offset of the object body
if (GetFieldOffset("nt!_OBJECT_HEADER", "Body", &ulObjectBodyOffset))
{
dprintf("Cannot get ObjectBody offset!\n");
return E_FAIL;
}
if (GetFieldValue(ul64Object - ulObjectBodyOffset, "nt!_OBJECT_HEADER", "Type", ul64Type))
{
dprintf("Failed to get Type value at 0x%I64x!\n", ul64Object);
return E_FAIL;
}
if (GetFieldOffset("nt!_OBJECT_TYPE", "Name", &ulTypeNameOffset))
{
dprintf("Cannot get TypeName offset!\n");
return E_FAIL;
}
return GetUNICODE_STRING(ul64Type + ulTypeNameOffset, pszTypeName, ulSize);
}
ULONG64 GetObjectChildDirectory(ULONG64 ul64Object)
{
CHAR szTypeName[MAX_PATH + 1] = {0};
if (GetObjectTypeName(ul64Object, szTypeName, sizeof(szTypeName)))
{
return 0;
}
if (!_stricmp(szTypeName, "Directory"))
{
return ul64Object;
}
return 0;
}
ULONG GetRealDeviceForSymbolicLink(ULONG64 ul64Object, CHAR *pszDevicePath, ULONG ulSize)
{
CHAR szTypeName[MAX_PATH + 1] = {0};
ULONG ulLinkTargetOffset = 0;
if (GetObjectTypeName(ul64Object, szTypeName, sizeof(szTypeName)))
{
dprintf("Could not get TypeName for object in GetRealDeviceForSymbolicLink!\n");
return E_FAIL;
}
if (_stricmp(szTypeName, "SymbolicLink"))
{
dprintf("Object in GetRealDeviceForSymbolicLink is a %s\n", szTypeName);
return E_FAIL;
}
// Get the offset of the object body
if (GetFieldOffset("nt!_OBJECT_SYMBOLIC_LINK", "LinkTarget", &ulLinkTargetOffset))
{
dprintf("Cannot get LinkTarget offset!\n");
return E_FAIL;
}
return GetUNICODE_STRING(ul64Object + ulLinkTargetOffset, pszDevicePath, ulSize);
}
ULONG64 FindObjectByName(CHAR *ObjectPath, ULONG64 ul64StartPoint)
{
ULONG64 ul64ObjRoot = ul64StartPoint;
ULONG64 ul64DirEntry = 0;
ULONG ulNumberOfBuckets = 0;
ULONG ulPointerSize = 4;
ULONG ulHashOffset = 0;
ULONG ulObjectBodyOffset = 0;
ULONG ulNameInfoNameOffset = 0;
ULONG i = 0;
CHAR PathCopy[MAX_PATH + 1] = {0};
CHAR *PathPtr = ObjectPath;
if (!PathPtr)
{
return NULL;
}
while (PathPtr[0] == '\\')
{
PathPtr++;
}
//Copy the Path String
strncpy(PathCopy, PathPtr, min(sizeof(PathCopy)-1, strlen(PathPtr)));
if (ul64ObjRoot == 0)
{
// Get the address of the Root Directory Object
ul64ObjRoot = GetObpRootDirectoryObjectAddress();
if (!ul64ObjRoot)
{
dprintf("Could not get the address of the ObpRootDirectoryObject!\n");
return NULL;
}
}
if (ObjectPath[0] == '\0')
{
return ul64ObjRoot;
}
PathPtr = PathCopy;
while ((PathPtr[0] != '\\') && (PathPtr[0] != '\0'))
{
PathPtr++;
}
if (PathPtr[0] == '\\')
{
PathPtr[0] = '\0';
PathPtr++;
}
//Get the offset of the hashbuckets field in the _OBJECT_DIRECTORY structure
if (GetFieldOffset("nt!_OBJECT_DIRECTORY", "HashBuckets", &ulHashOffset))
{
dprintf("Cannot get HashBuckets offset!\n");
return NULL;
}
// Get the pointer size for our architecture
ulPointerSize = (IsPtr64() ? 8 : 4);
// Try to dynamically determine the number of HashBuckets in the _OBJECT_DIRECTORY structure
ulNumberOfBuckets = GetNumberOfHashBuckets();
if (!ulNumberOfBuckets)
{
ulNumberOfBuckets = 37; // From ob.h #define NUMBER_HASH_BUCKETS 37
}
// Get the offset of the object body
if (GetFieldOffset("nt!_OBJECT_HEADER", "Body", &ulObjectBodyOffset))
{
dprintf("Cannot get ObjectBody offset!\n");
return NULL;
}
// Get the offset of the object body
if (GetFieldOffset("nt!_OBJECT_HEADER_NAME_INFO", "Name", &ulNameInfoNameOffset))
{
dprintf("Cannot get NameInfo Name Offset!\n");
return NULL;
}
// Iterate through each bucket
for (i=0; i < ulNumberOfBuckets; i++)
{
// Get the address of each _OBJECT_DIRECTORY_ENTRY in the HashBucket array
if (ReadPointer(ul64ObjRoot + ulHashOffset + (i * ulPointerSize), &ul64DirEntry))
{
while (ul64DirEntry)
{
ULONG64 ul64Object = 0;
ULONG64 ul64Header = 0;
ULONG64 ul64NameInfo = 0;
ULONG ulNameInfoOffset = 0;
CHAR szObjName[MAX_PATH + 1] = {0};
// Setup to point at our current object \
// - this is actually a pointer to the body field of the _OBJECT_HEADER Structure
if (GetFieldValue(ul64DirEntry, "nt!_OBJECT_DIRECTORY_ENTRY", "Object", ul64Object))
{
dprintf("Failed to get object value at 0x%I64x!\n", ul64DirEntry);
break;
}
// Find the header for this object by subtracting the body (current) offset
ul64Header = ul64Object - ulObjectBodyOffset;
// Get the offset from the top of the header of the NameInfoObject
if (GetFieldValue(ul64Header, "nt!_OBJECT_HEADER", "NameInfoOffset", ulNameInfoOffset))
{
dprintf("Failed to get NameInfoOffset pointer from objectheader at 0x%I64x!\n", ul64Header);
break;
}
// If zero the object does not have one
if (ulNameInfoOffset == 0)
{
break;
}
// Set our pointer to point to the _OBJECT_HEADER_NAME_INFO structure
ul64NameInfo = ul64Header - ulNameInfoOffset;
// Get the objects name
if (GetUNICODE_STRING(ul64NameInfo + ulNameInfoNameOffset, szObjName, sizeof(szObjName)))
{
dprintf("Could Not Get Name\n");
break;
}
if (!_stricmp(PathCopy, szObjName))
{
ULONG64 ul64NextDirectory = 0;
if (PathPtr[0] == '\0')
{
return ul64Object;
}
ul64NextDirectory = GetObjectChildDirectory(ul64Object);
return FindObjectByName(PathPtr, ul64NextDirectory);
}
//Get the next _OBJECT_DIRECTORY_ENTRY
if (GetFieldValue(ul64DirEntry, "nt!_OBJECT_DIRECTORY_ENTRY", "ChainLink", ul64DirEntry))
{
dprintf("Failed to get next object value at 0x%I64x!\n", ul64Object);
break;
}
} // while loop
} // if statement
} // for loop
return NULL;
}
ULONG64 GetVPBPtrFromDeviceObject(ULONG64 ul64DeviceObject)
{
ULONG64 ul64VpbPtr = 0;
// Get the offset from the top of the header of the NameInfoObject
if (GetFieldValue(ul64DeviceObject, "nt!_DEVICE_OBJECT", "Vpb", ul64VpbPtr))
{
dprintf("Failed to get Vbp pointer from DeviceObject at 0x%I64x!\n", ul64DeviceObject);
return NULL;
}
return ul64VpbPtr;
}
ULONG GetDeviceDriverString(ULONG64 ul64Device, CHAR *pszString, ULONG ulSize)
{
ULONG ulNameOffset = 0;
ULONG64 ul64Driver = 0;
if (GetFieldValue(ul64Device, "nt!_DEVICE_OBJECT", "DriverObject", ul64Driver))
{
dprintf("Failed to get DriverObject from Device pointer at 0x%I64x!\n", ul64Device);
return E_FAIL;
}
// Get the offset of the DriverName in the _DRIVER_OBJECT
if (GetFieldOffset("nt!_DRIVER_OBJECT", "DriverName", &ulNameOffset))
{
dprintf("Cannot get DriverName offset!\n");
return E_FAIL;
}
return GetUNICODE_STRING(ul64Driver + ulNameOffset, pszString, ulSize);
}
VOID OutputData(ULONG ulBytesPerCluster,
ULONG64 ul64TotalClusters,
ULONG64 ul64FreeClusters)
{
ULONG64 ul64TotalBytes = ul64TotalClusters * ulBytesPerCluster;
ULONG64 ul64FreeBytes = ul64FreeClusters * ulBytesPerCluster;
dprintf(" Cluster Size %u KB\n", ulBytesPerCluster / 1024);
dprintf(" Total Clusters %I64u KB\n", ul64TotalClusters);
dprintf(" Free Clusters %I64u KB\n", ul64FreeClusters);
dprintf(" Total Space %I64u GB (%I64u KB)\n",
(ul64TotalBytes) / (0x40000000),
(ul64TotalBytes) / (0x400));
if (ul64FreeBytes > 0x40000000)
{
dprintf(" Free Space %I64f GB (%.2I64u MB)\n",
(float)(ul64FreeBytes) / (0x40000000),
(ul64FreeBytes) / (0x100000));
}
else if (ul64FreeBytes > 0x100000)
{
dprintf(" Free Space %I64f MB (%.2I64u KB)\n",
(float)(ul64FreeBytes) / (0x100000),
(ul64FreeBytes) / (0x400));
}
else
{
dprintf(" Free Space %I64u Bytes\n", ul64FreeBytes);
}
}
ULONG GetAndOutputNTFSData(CHAR cDriveletter, ULONG64 ul64DevObj)
{
ULONG ulVCBOffset = 0;
ULONG ulBytesPerCluster = 0;
ULONG64 ul64TotalClusters = 0;
ULONG64 ul64FreeClusters = 0;
if (GetFieldOffset("ntfs!_VOLUME_DEVICE_OBJECT", "Vcb", &ulVCBOffset))
{
dprintf("Cannot get Vcb offset for NTFS Device!\n");
return E_FAIL;
}
if (GetFieldValue(ul64DevObj + ulVCBOffset, "ntfs!_VCB", "BytesPerCluster", ulBytesPerCluster))
{
dprintf("Failed to get BytesPerCluster from VCB at 0x%I64x!\n", ul64DevObj + ulVCBOffset);
return E_FAIL;
}
if (GetFieldValue(ul64DevObj + ulVCBOffset, "ntfs!_VCB", "TotalClusters", ul64TotalClusters))
{
dprintf("Failed to get TotalClusters from VCB at 0x%I64x!\n", ul64DevObj + ulVCBOffset);
return E_FAIL;
}
if (GetFieldValue(ul64DevObj + ulVCBOffset, "ntfs!_VCB", "FreeClusters", ul64FreeClusters))
{
dprintf("Failed to get FreeClusters from VCB at 0x%I64x!\n", ul64DevObj + ulVCBOffset);
return E_FAIL;
}
OutputData(ulBytesPerCluster, ul64TotalClusters, ul64FreeClusters);
return S_OK;
}
ULONG GetAndOutputFatData(CHAR cDriveletter, ULONG64 ul64DevObj)
{
ULONG ulVCBOffset = 0;
ULONG ulBytesPerSector = 0;
ULONG ulSectorsPerCluster = 0;
ULONG64 ul64TotalClusters = 0;
ULONG64 ul64FreeClusters = 0;
if (GetFieldOffset("fastfat!_VOLUME_DEVICE_OBJECT", "Vcb", &ulVCBOffset))
{
dprintf("Cannot get Vcb offset for FastFat Device!\n");
return E_FAIL;
}
if (GetFieldValue(ul64DevObj + ulVCBOffset, "fastfat!_VCB", "Bpb.BytesPerSector", ulBytesPerSector))
{
dprintf("Failed to get BytesPerSector from VCB at 0x%I64x!\n", ul64DevObj + ulVCBOffset);
return E_FAIL;
}
if (GetFieldValue(ul64DevObj + ulVCBOffset, "fastfat!_VCB", "Bpb.SectorsPerCluster", ulSectorsPerCluster))
{
dprintf("Failed to get SectorsPerCluster from VCB at 0x%I64x!\n", ul64DevObj + ulVCBOffset);
return E_FAIL;
}
if (GetFieldValue(ul64DevObj + ulVCBOffset, "fastfat!_VCB", "AllocationSupport.NumberOfClusters", ul64TotalClusters))
{
dprintf("Failed to get TotalClusters from VCB at 0x%I64x!\n", ul64DevObj + ulVCBOffset);
return E_FAIL;
}
if (GetFieldValue(ul64DevObj + ulVCBOffset, "fastfat!_VCB", "AllocationSupport.NumberOfFreeClusters", ul64FreeClusters))
{
dprintf("Failed to get FreeClusters from VCB at 0x%I64x!\n", ul64DevObj + ulVCBOffset);
return E_FAIL;
}
OutputData(ulBytesPerSector * ulSectorsPerCluster, ul64TotalClusters, ul64FreeClusters);
return S_OK;
}
DECLARE_API( diskspace )
/*++
Routine Description:
Dumps free disk space for the specified volume
Arguments:
args - The volume letter of the drive on which you want the info
Return Value:
None
--*/
{
ULONG ulReturn = S_OK;
CHAR cVolume = args[0];
CHAR szRootPath[MAX_PATH + 1] = {0};
ULONG64 ul64Drive = 0;
ULONG64 ul64Vpb = 0;
INIT_API();
// Make sure we have a valid drive letter as the first character.
if (((cVolume < 'A') || (cVolume > 'z')) ||
((cVolume > 'Z') && (cVolume < 'a')))
{
dprintf("'%s' is not a valid drive specification!\n", args);
ulReturn = E_FAIL;
goto exit;
}
// Make sure this is likely to be a valid param in that it is
// followed by a space of a colon.
if ((args[1] != ' ') && (args[1] != ':') && (args[1] != '\0'))
{
dprintf("'%s' is not a valid drive specification!\n", args);
ulReturn = E_FAIL;
goto exit;
}
sprintf(szRootPath, "\\GLOBAL??\\%c:", cVolume);
dprintf("Checking Free Space for %c: ", cVolume);
ul64Drive = FindObjectByName(szRootPath, 0);
if (!ul64Drive)
{
dprintf("\nFailed to find volume %c:!\n", cVolume);
ulReturn = E_FAIL;
goto exit;
}
GetRealDeviceForSymbolicLink(ul64Drive, szRootPath, sizeof(szRootPath));
if (strstr(_strlwr(szRootPath), "cdrom"))
{
dprintf("\n%c: is a CDROM drive. This function is not supported!\n", cVolume);
ulReturn = E_FAIL;
goto exit;
}
dprintf("..");
ul64Drive = FindObjectByName(szRootPath, 0);
dprintf("..");
if (GetFieldValue(ul64Drive, "nt!_DEVICE_OBJECT", "Vpb", ul64Vpb))
{
dprintf("Failed to get Vbp pointer from DeviceObject at 0x%I64x!\n", ul64Drive);
ulReturn = E_FAIL;
goto exit;
}
dprintf("..");
if (GetFieldValue(ul64Vpb, "nt!_VPB", "DeviceObject", ul64Drive))
{
dprintf("Failed to get DeviceObject from VBP pointer at 0x%I64x!\n", ul64Vpb);
ulReturn = E_FAIL;
goto exit;
}
dprintf("..");
if (GetDeviceDriverString(ul64Drive, szRootPath, sizeof(szRootPath)))
{
dprintf("Failed to Get Driver String From Device at 0x%I64x!\n", ul64Drive);
ulReturn = E_FAIL;
goto exit;
}
dprintf("..\n");
if (strstr(_strlwr(szRootPath), "ntfs"))
{
GetAndOutputNTFSData(cVolume, ul64Drive);
}
else if (strstr(_strlwr(szRootPath), "fastfat"))
{
GetAndOutputFatData(cVolume, ul64Drive);
}
else if (strstr(_strlwr(szRootPath), "cdfs"))
{
dprintf("This extension does not support the cdfs filesystem!\n");
}
else
{
dprintf("Unable to determine Volume Type for %s!\n", szRootPath);
}
exit:
EXIT_API();
return ulReturn;
}