I've got a Windows program that scans the contents of a hard disk. I'd like to display a meaningful progress bar while it does so. Is there a quick way to get the total number of files on the disk? The number doesn't have to be exact -- an approximation within 10% or so should do.
Asked
Active
Viewed 162 times
-1
-
Do you have administrator privilege? [Reading the content of the MFT](http://stackoverflow.com/a/7459109/886887) provides a much faster way of scanning the contents of the disk, and if you did that, you could implement a progress bar by keeping track of [what percentage of the MFT](http://stackoverflow.com/a/11337898/886887) you have processed. – Harry Johnston Feb 23 '17 at 00:50
-
No luck on that -- this program needs to be able to run under as wide a range of circumstances as possible. – Mark Feb 23 '17 at 00:51
1 Answers
1
this is possible for NTFS volume. one way as Harry Johnston write. also possible some another way, also fast enough by iterating file records:
struct NTFS_RECORD_HEADER
{
enum {
FILE = 'ELIF',
INDX = 'XDNI',
BAAD = 'DAAB',
HOLE = 'ELOH',
CHKD = 'DKHC'
} Type;
USHORT UsaOffset;
USHORT UsaCount;
USN Usn;
};
struct NTFS_FILE_RECORD_HEADER : public NTFS_RECORD_HEADER
{
USHORT SequenceNumber;
USHORT LinkCount;
USHORT AttributesOffset;
USHORT Flags;
ULONG BytesInUse;
ULONG BytesAllocated;
ULONGLONG BaseFileRecord;
USHORT NextAttributeNumber;
enum{
flgInUse = 1, flgDirectory = 2
};
};
ULONG GetFileCount(HANDLE hVolume, PULONG FileCount)
{
NTFS_VOLUME_DATA_BUFFER nvdb;
ULONG cb, BytesReturned;
if (!DeviceIoControl(hVolume, FSCTL_GET_NTFS_VOLUME_DATA, NULL, 0, &nvdb, sizeof(nvdb), &BytesReturned, NULL))
{
return GetLastError();
}
NTFS_FILE_RECORD_INPUT_BUFFER nfrib;
cb = FIELD_OFFSET(NTFS_FILE_RECORD_OUTPUT_BUFFER, FileRecordBuffer[nvdb.BytesPerFileRecordSegment]);
PNTFS_FILE_RECORD_OUTPUT_BUFFER pnfrob = (PNTFS_FILE_RECORD_OUTPUT_BUFFER)alloca(cb);
union {
PVOID FileRecordBuffer;
NTFS_RECORD_HEADER* pnrh;
NTFS_FILE_RECORD_HEADER* pnfrh;
};
FileRecordBuffer = pnfrob->FileRecordBuffer;
// get maximum valid FileReferenceNumber
ULONG a = 0, b = MAXLONG, N;
do
{
nfrib.FileReferenceNumber.QuadPart = N = (a + b) >> 1;
DeviceIoControl(hVolume, FSCTL_GET_NTFS_FILE_RECORD,
&nfrib, sizeof nfrib, pnfrob, cb, &BytesReturned, 0) ? a = N + 1 : b = N;
} while(a < b);
if (!b)
{
return ERROR_GEN_FAILURE;
}
N = 0;
nfrib.FileReferenceNumber.QuadPart = b - 1;
// itterate [0, nfrib.FileReferenceNumber.QuadPart)
do
{
if (DeviceIoControl(hVolume, FSCTL_GET_NTFS_FILE_RECORD,
&nfrib, sizeof nfrib, pnfrob, cb, &BytesReturned, 0))
{
// are really file
if (
pnrh->Type == NTFS_RECORD_HEADER::FILE &&
pnfrh->Flags & NTFS_FILE_RECORD_HEADER::flgInUse &&
!pnfrh->BaseFileRecord
)
{
N++;
}
}
else
{
pnfrob->FileReferenceNumber.QuadPart = nfrib.FileReferenceNumber.QuadPart;
}
} while (0 <= (nfrib.FileReferenceNumber.QuadPart = pnfrob->FileReferenceNumber.QuadPart - 1));
*FileCount = N;
return NOERROR;
}