Code:
#pragma comment( lib, "advapi32.lib" ) // Search for advapi32.lib while linking
#include <windows.h>
#include <stdio.h>
typedef enum _FILE_INFORMATION_CLASS {
FileDirectoryInformation = 1,
FileFullDirectoryInformation,
FileBothDirectoryInformation,
FileBasicInformation,
FileStandardInformation,
FileInternalInformation,
FileEaInformation,
FileAccessInformation,
FileNameInformation,
FileRenameInformation,
FileLinkInformation,
FileNamesInformation,
FileDispositionInformation,
FilePositionInformation,
FileModeInformation = 16, // 16
FileAlignmentInformation,
FileAllInformation,
FileAllocationInformation,
FileEndOfFileInformation,
FileAlternateNameInformation,
FileStreamInformation,
FilePipeInformation,
FilePipeLocalInformation,
FilePipeRemoteInformation,
FileMailslotQueryInformation,
FileMailslotSetInformation,
FileCompressionInformation,
FileObjectIdInformation,
FileCompletionInformation,
FileMoveClusterInformation,
FileQuotaInformation,
FileReparsePointInformation,
FileNetworkOpenInformation,
FileAttributeTagInformation,
FileTrackingInformation
} FILE_INFORMATION_CLASS, *PFILE_INFORMATION_CLASS;
typedef INT NTSTATUS;
#define BUFFER_OVERFLOW ((NTSTATUS)0x80000005L)
typedef struct _IO_STATUS_BLOCK {
NTSTATUS Status;
ULONG Information;
} IO_STATUS_BLOCK, *PIO_STATUS_BLOCK;
#pragma pack(push, 4)
typedef struct _FILE_STREAM_INFORMATION { // Information Class 22
ULONG NextEntryOffset;
ULONG StreamNameLength;
LARGE_INTEGER EndOfStream;
LARGE_INTEGER AllocationSize;
WCHAR StreamName[1];
} FILE_STREAM_INFORMATION, *PFILE_STREAM_INFORMATION;
#pragma pack(pop)
typedef NTSTATUS (NTAPI *NTQUERYINFORMATIONFILE)(
IN HANDLE FileHandle,
OUT PIO_STATUS_BLOCK IoStatusBlock,
OUT PVOID FileInformation,
IN ULONG Length,
IN FILE_INFORMATION_CLASS FileInformationClass);
int main(int argc, char *argv[])
{
NTQUERYINFORMATIONFILE NtQueryInformationFile;
LPBYTE pInfoBlock = NULL;
ULONG uInfoBlockSize = 0;
IO_STATUS_BLOCK ioStatus;
NTSTATUS status;
HANDLE hFile;
(FARPROC&)NtQueryInformationFile = GetProcAddress(GetModuleHandle("ntdll.dll"), "NtQueryInformationFile");
if (NtQueryInformationFile == NULL)
{
printf("NtQueryInformationFile failed\n");
return -1;
}
hFile = CreateFile(argv[1], 0, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
if (hFile == INVALID_HANDLE_VALUE)
{
printf("Invalid file handle\n");
return -1;
}
do
{
uInfoBlockSize += 16384;
delete [] pInfoBlock;
pInfoBlock = new BYTE [uInfoBlockSize];
((PFILE_STREAM_INFORMATION)pInfoBlock)->StreamNameLength = 0;
status = NtQueryInformationFile(hFile, &ioStatus, (LPVOID)pInfoBlock, uInfoBlockSize, FileStreamInformation);
} while (status == BUFFER_OVERFLOW);
CloseHandle(hFile);
PFILE_STREAM_INFORMATION pStreamInfo = (PFILE_STREAM_INFORMATION)(LPVOID)pInfoBlock;
LARGE_INTEGER liFileSize;
WCHAR wszStreamName[MAX_PATH];
char szStreamName[MAX_PATH], szFilePath[MAX_PATH];
LPSTR pszName;
int iLength;
if (!GetFullPathName(argv[1], MAX_PATH, szFilePath, &pszName))
{
printf("GetFullPathName failed\n");
return -1;
}
printf("%s\n", szFilePath);
for (;;)
{
// Check if stream info block is empty
if (pStreamInfo->StreamNameLength == 0)
break;
// Get stream name
memcpy(wszStreamName, pStreamInfo->StreamName, pStreamInfo->StreamNameLength);
wszStreamName[pStreamInfo->StreamNameLength / sizeof(WCHAR)] = L'\0';
// Remove attribute tag and convert to char
LPWSTR pTag = wcsstr(wszStreamName, L":$DATA");
if (pTag) *pTag = L'\0';
iLength = WideCharToMultiByte(CP_ACP, 0, wszStreamName, -1, szStreamName, MAX_PATH, NULL, NULL);
// Full path including stream name
strcpy(szFilePath, argv[1]);
if (strcmp(szStreamName, ":"))
{
strcat(szFilePath, szStreamName); // Named stream - attach stream name
}
// Get stream size
hFile = CreateFile(szFilePath, 0, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
if (hFile == INVALID_HANDLE_VALUE)
{
printf("CreateFilePath failed\n");
return -1;
}
if (!GetFileSizeEx(hFile, &liFileSize))
{
printf("GetFileSizeEx failed\n");
return -1;
}
CloseHandle(hFile);
if (iLength < 40)
{
strcat(szStreamName, " ");
szStreamName[40] = '\0';
}
else
strcat(szStreamName, " ");
printf(" %s%I64u\n", szStreamName, liFileSize.QuadPart);
if (pStreamInfo->NextEntryOffset == 0) break; // No more stream info records
pStreamInfo = (PFILE_STREAM_INFORMATION)((LPBYTE)pStreamInfo + pStreamInfo->NextEntryOffset); // Next stream record
}
return 0;
}