mirror of https://github.com/lianthony/NT4.0
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.
733 lines
17 KiB
733 lines
17 KiB
/*
|
|
* XLST.C
|
|
*
|
|
* This is a test tool. No attempt is made to be 'propah'. If you find no
|
|
* comments, you are in the right place.
|
|
*
|
|
* This is essentially a tool similar to LS, except that
|
|
*
|
|
* 1. It does not support sorting yet.
|
|
* 2. It does not handle wild cards yet.
|
|
* 3. It supports NTFS details on a NTFS partition.
|
|
*/
|
|
|
|
#include <ntos.h>
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <wchar.h>
|
|
|
|
typedef ULONG DWORD;
|
|
|
|
WCHAR CDBuffer[8192];
|
|
WCHAR * PathBuffer;
|
|
LONG ColumnPos = 0;
|
|
VOID xxGetCurrentDirectory(ULONG, LPWSTR);
|
|
VOID xxPrintTimes(LARGE_INTEGER tCreat, LARGE_INTEGER tMod,
|
|
LARGE_INTEGER tChg, LARGE_INTEGER tAcc);
|
|
|
|
#define xxInitUnicodeString(u, s, l) \
|
|
(u)->Buffer = s; \
|
|
(u)->MaximumLength = (USHORT)l; \
|
|
(u)->Length = (USHORT)l;
|
|
|
|
UNICODE_STRING Dot, DotDot, Ntfs, DataStream;
|
|
CHAR * ThisName = NULL;
|
|
DWORD Options = 0;
|
|
UNICODE_STRING DirName, FsName;
|
|
BOOLEAN IsVolNtfs = TRUE;
|
|
|
|
#define True (BOOLEAN)TRUE
|
|
#define False (BOOLEAN)FALSE
|
|
#define COLUMN_SPACING 14
|
|
#define MAX_COLUMN 72
|
|
|
|
#define ATTR 0x01
|
|
#define SHORT_NAME 0x02
|
|
#define TIMES 0x04
|
|
#define INDEX 0x08
|
|
#define SIZE 0x10
|
|
#define STREAMS 0x20
|
|
#define RECURSIVE 0x40
|
|
|
|
int
|
|
GetOptions(
|
|
int argc,
|
|
char ** argv
|
|
)
|
|
{
|
|
int i, j;
|
|
char c;
|
|
|
|
for (i = 1; i < argc; i++)
|
|
{
|
|
c = argv[i][0];
|
|
if (c == '-' || c == '/')
|
|
{
|
|
for (j = 1; c = argv[i][j]; j++)
|
|
switch (c)
|
|
{
|
|
case 'A':
|
|
Options = ATTR | SHORT_NAME | TIMES | INDEX | SIZE | STREAMS;
|
|
break;
|
|
case 'a':
|
|
Options |= ATTR;
|
|
break;
|
|
case 's':
|
|
Options |= SIZE;
|
|
break;
|
|
case 'i':
|
|
Options |= INDEX;
|
|
break;
|
|
case 't':
|
|
Options |= STREAMS;
|
|
break;
|
|
case 'R':
|
|
Options |= RECURSIVE;
|
|
break;
|
|
case 'S':
|
|
Options |= SHORT_NAME;
|
|
break;
|
|
case 'T':
|
|
Options |= TIMES;
|
|
break;
|
|
case '?':
|
|
default:
|
|
printf("xlst -<options> [File]\n");
|
|
printf("\t-?\tThis information\n");
|
|
printf("\t-A\tAll\n");
|
|
printf("\t-a\tAttributes\n");
|
|
printf("\t-i\tIndex\n");
|
|
printf("\t-s\tSize\n");
|
|
printf("\t-t\tStreams\n");
|
|
printf("\t-R\tRecursive\n");
|
|
printf("\t-S\tShort Name\n");
|
|
printf("\t-T\tTimes\n");
|
|
return (0);
|
|
break;
|
|
}
|
|
}
|
|
else if (ThisName == NULL)
|
|
ThisName = argv[i];
|
|
}
|
|
|
|
PathBuffer = CDBuffer + (sizeof(L"\\DOSDEVICES\\") - sizeof(UNICODE_NULL))/sizeof(WCHAR);
|
|
RtlCopyMemory(CDBuffer, L"\\DOSDEVICES\\", sizeof(L"\\DOSDEVICES\\") - sizeof(UNICODE_NULL));
|
|
|
|
if ((ThisName == NULL) ||
|
|
(ThisName[1] != ':'))
|
|
xxGetCurrentDirectory(sizeof(CDBuffer)/sizeof(WCHAR) -
|
|
sizeof(L"\\DOSDEVICES\\"), PathBuffer);
|
|
RtlInitUnicodeString(&DirName, CDBuffer);
|
|
DirName.MaximumLength = sizeof(CDBuffer);
|
|
|
|
if ((ThisName != NULL) &&
|
|
(ThisName[0] == '\\'))
|
|
DirName.Length = sizeof(L"\\DOSDEVICES\\") + sizeof(L"C:") - 2*sizeof(WCHAR);
|
|
|
|
|
|
if (ThisName != NULL)
|
|
{
|
|
ANSI_STRING ADir;
|
|
UNICODE_STRING UDir, Slash;
|
|
|
|
RtlInitAnsiString(&ADir, ThisName);
|
|
RtlInitUnicodeString(&Slash, L"\\");
|
|
RtlAnsiStringToUnicodeString(&UDir, &ADir, True);
|
|
if (!RtlEqualUnicodeString(&UDir, &Slash, FALSE) &&
|
|
!(ThisName[1] == ':'))
|
|
RtlAppendUnicodeStringToString(&DirName, &Slash);
|
|
RtlAppendUnicodeStringToString(&DirName, &UDir);
|
|
}
|
|
|
|
return (1);
|
|
}
|
|
|
|
|
|
VOID
|
|
PrintAttr(
|
|
IN DWORD Attr
|
|
)
|
|
{
|
|
printf("%c%c%c%c%c ",
|
|
(Attr & FILE_ATTRIBUTE_DIRECTORY) ? 'd' : '-',
|
|
(Attr & FILE_ATTRIBUTE_READONLY) ? 'r' : '-',
|
|
(Attr & FILE_ATTRIBUTE_ARCHIVE) ? 'a' : '-',
|
|
(Attr & FILE_ATTRIBUTE_SYSTEM) ? 's' : '-',
|
|
(Attr & FILE_ATTRIBUTE_HIDDEN) ? 'h' : '-');
|
|
}
|
|
|
|
|
|
VOID
|
|
PrintNames(
|
|
IN DWORD Attr,
|
|
IN WCHAR * LongName,
|
|
IN WCHAR * ShortName,
|
|
IN CHAR * Trailer OPTIONAL
|
|
)
|
|
{
|
|
LONG ColumnAdd, NumSpaces;
|
|
CHAR * SpaceTrailers[COLUMN_SPACING-1] =
|
|
{
|
|
" ",
|
|
" ",
|
|
" ",
|
|
" ",
|
|
" ",
|
|
" ",
|
|
" ",
|
|
" ",
|
|
" ",
|
|
" ",
|
|
" ",
|
|
" ",
|
|
" "
|
|
};
|
|
|
|
if (Trailer == NULL)
|
|
{
|
|
Trailer = "\n";
|
|
if ((Options & ~RECURSIVE) == 0)
|
|
{
|
|
ColumnAdd = wcslen(LongName);
|
|
if (Attr & (FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_READONLY | FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN))
|
|
ColumnAdd ++; // for * appended to name
|
|
if (Attr & FILE_ATTRIBUTE_DIRECTORY)
|
|
ColumnAdd += 2; // for [] surround name
|
|
NumSpaces = COLUMN_SPACING - 1 - (ColumnAdd % COLUMN_SPACING);
|
|
if ((ColumnAdd+ColumnPos) < MAX_COLUMN)
|
|
{
|
|
Trailer = SpaceTrailers[NumSpaces];
|
|
ColumnAdd += NumSpaces;
|
|
}
|
|
else ColumnPos = 0;
|
|
|
|
ColumnPos += ColumnAdd;
|
|
if (ColumnPos > MAX_COLUMN)
|
|
{
|
|
Trailer = "\n";
|
|
ColumnPos = 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (Attr & FILE_ATTRIBUTE_DIRECTORY)
|
|
printf("[%ws]", LongName);
|
|
else printf("%ws", LongName);
|
|
if (Attr & (FILE_ATTRIBUTE_READONLY | FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN))
|
|
printf("*");
|
|
if (Options & SHORT_NAME)
|
|
{
|
|
if (ShortName[0] != UNICODE_NULL)
|
|
printf(" < %ws >", ShortName);
|
|
}
|
|
printf("%s", Trailer);
|
|
}
|
|
|
|
VOID
|
|
PrintFileDetails(
|
|
IN DWORD Attr,
|
|
IN WCHAR * LongName,
|
|
IN WCHAR * ShortName,
|
|
IN LARGE_INTEGER FileSize,
|
|
IN LARGE_INTEGER FileIndex,
|
|
IN LARGE_INTEGER tCreat,
|
|
IN LARGE_INTEGER tMod,
|
|
IN LARGE_INTEGER tChg,
|
|
IN LARGE_INTEGER tAcc
|
|
)
|
|
{
|
|
if (Options & ATTR)
|
|
PrintAttr(Attr);
|
|
|
|
if (Options & SIZE)
|
|
{
|
|
if (FileSize.HighPart != 0)
|
|
printf("%4ld%08ld ", FileSize.HighPart, FileSize.LowPart);
|
|
else printf(" %8ld ", FileSize.LowPart);
|
|
}
|
|
|
|
if (IsVolNtfs && (Options & INDEX))
|
|
{
|
|
if (FileIndex.HighPart != 0)
|
|
printf(" %8lx%08lx ", FileIndex.HighPart, FileIndex.LowPart);
|
|
else printf(" %8lx ", FileIndex.LowPart);
|
|
}
|
|
|
|
if (IsVolNtfs && (Options & TIMES))
|
|
{
|
|
PrintNames(Attr, LongName, ShortName, "\n");
|
|
}
|
|
|
|
if (Options & TIMES)
|
|
xxPrintTimes(tCreat, tMod, tChg, tAcc);
|
|
|
|
if (!(IsVolNtfs && (Options & TIMES)))
|
|
{
|
|
PrintNames( Attr,
|
|
LongName,
|
|
ShortName,
|
|
NULL);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
VOID
|
|
PrintStreamDetails(
|
|
IN WCHAR * LongName,
|
|
IN WCHAR * StreamName,
|
|
IN LARGE_INTEGER FileSize
|
|
)
|
|
{
|
|
if (Options & ATTR)
|
|
printf(" ");
|
|
|
|
if (Options & SIZE)
|
|
{
|
|
if (FileSize.HighPart != 0)
|
|
printf("%4ld%08ld ", FileSize.HighPart, FileSize.LowPart);
|
|
else printf(" %8ld ", FileSize.LowPart);
|
|
}
|
|
|
|
if (Options & INDEX)
|
|
printf(" ");
|
|
|
|
printf(" %ws\n", StreamName);
|
|
}
|
|
|
|
|
|
VOID
|
|
DoFile(
|
|
HANDLE FileHandle
|
|
)
|
|
{
|
|
NTSTATUS Status;
|
|
HANDLE ParentHandle;
|
|
UNICODE_STRING FileName, Parent;
|
|
OBJECT_ATTRIBUTES ObjAttr;
|
|
FILE_BOTH_DIR_INFORMATION * pNames;
|
|
FILE_BASIC_INFORMATION BasInfo;
|
|
FILE_STANDARD_INFORMATION StdInfo;
|
|
FILE_INTERNAL_INFORMATION IntInfo;
|
|
FILE_STREAM_INFORMATION * pStream;
|
|
IO_STATUS_BLOCK IoStsBlk;
|
|
LONG i, len, TotSize = 0;
|
|
WCHAR ShortName[12+1];
|
|
WCHAR LongName[256+1];
|
|
WCHAR StreamName[256+1];
|
|
CHAR NamesInfoBuf[1024];
|
|
CHAR StreamsInfoBuf[4096];
|
|
|
|
ShortName[0] = 0;
|
|
pStream = (FILE_STREAM_INFORMATION *)StreamsInfoBuf;
|
|
pNames = (FILE_BOTH_DIR_INFORMATION *)NamesInfoBuf;
|
|
|
|
printf("\n %ws\n", PathBuffer);
|
|
len = wcslen(CDBuffer);
|
|
// Walk back from the Path buffer to get the name
|
|
for (i = len; i > 0; i--)
|
|
{
|
|
if (CDBuffer[i-1] == L'\\')
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
// Copy the supplied name in the long-name buffer for now.
|
|
RtlCopyMemory(LongName, CDBuffer + i, (len - i) * sizeof(WCHAR));
|
|
LongName[len - i] = UNICODE_NULL;
|
|
RtlInitUnicodeString(&FileName, LongName);
|
|
|
|
// Open the parent directory to get the file names - stupid !!!
|
|
Parent.Buffer = CDBuffer;
|
|
Parent.Length = (sizeof(WCHAR) * len) - (FileName.Length + sizeof(WCHAR));
|
|
Parent.MaximumLength = Parent.Length + sizeof(WCHAR);
|
|
InitializeObjectAttributes( &ObjAttr,
|
|
&Parent,
|
|
OBJ_CASE_INSENSITIVE,
|
|
NULL,
|
|
NULL);
|
|
|
|
Status = NtOpenFile(&ParentHandle,
|
|
FILE_GENERIC_READ,
|
|
&ObjAttr,
|
|
&IoStsBlk,
|
|
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
|
|
FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT);
|
|
|
|
if (!NT_SUCCESS(Status) || !NT_SUCCESS(IoStsBlk.Status))
|
|
{
|
|
fprintf(stderr, "\n***Failed to open directory %ws, Status %lx***\n",
|
|
PathBuffer, Status);
|
|
}
|
|
|
|
NtQueryDirectoryFile(ParentHandle,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
&IoStsBlk,
|
|
NamesInfoBuf,
|
|
sizeof(NamesInfoBuf),
|
|
FileBothDirectoryInformation,
|
|
True,
|
|
&FileName,
|
|
False);
|
|
NtClose(ParentHandle);
|
|
|
|
// Copy longname
|
|
RtlCopyMemory(LongName, pNames->FileName, pNames->FileNameLength);
|
|
LongName[pNames->FileNameLength/sizeof(WCHAR)] = UNICODE_NULL;
|
|
|
|
if (IsVolNtfs && (Options & SHORT_NAME) && (pNames->ShortNameLength != 0))
|
|
{
|
|
// Copy short name
|
|
RtlCopyMemory(ShortName, pNames->ShortName, pNames->ShortNameLength);
|
|
ShortName[pNames->ShortNameLength/sizeof(WCHAR)] = UNICODE_NULL;
|
|
}
|
|
|
|
// Get file size
|
|
NtQueryInformationFile( FileHandle,
|
|
&IoStsBlk,
|
|
&StdInfo,
|
|
sizeof(StdInfo),
|
|
FileStandardInformation);
|
|
|
|
// Get the FILE_ID
|
|
if (IsVolNtfs && (Options & INDEX))
|
|
NtQueryInformationFile( FileHandle,
|
|
&IoStsBlk,
|
|
&IntInfo,
|
|
sizeof(IntInfo),
|
|
FileInternalInformation);
|
|
|
|
// Get the other stuff
|
|
if (Options & (TIMES | ATTR))
|
|
NtQueryInformationFile( FileHandle,
|
|
&IoStsBlk,
|
|
&BasInfo,
|
|
sizeof(BasInfo),
|
|
FileBasicInformation);
|
|
|
|
TotSize += StdInfo.EndOfFile.LowPart;
|
|
PrintFileDetails(BasInfo.FileAttributes,
|
|
LongName,
|
|
ShortName,
|
|
StdInfo.EndOfFile,
|
|
IntInfo.IndexNumber,
|
|
BasInfo.CreationTime,
|
|
BasInfo.LastWriteTime,
|
|
BasInfo.ChangeTime,
|
|
BasInfo.LastAccessTime);
|
|
|
|
if (IsVolNtfs)
|
|
{
|
|
// And all the streams
|
|
NtQueryInformationFile(FileHandle,
|
|
&IoStsBlk,
|
|
StreamsInfoBuf,
|
|
sizeof(StreamsInfoBuf),
|
|
FileStreamInformation);
|
|
|
|
if (IoStsBlk.Information != 0)
|
|
{
|
|
PFILE_STREAM_INFORMATION tmppsinf;
|
|
|
|
do
|
|
{
|
|
UNICODE_STRING Temp;
|
|
|
|
xxInitUnicodeString(&Temp, pStream->StreamName, pStream->StreamNameLength);
|
|
if (!RtlEqualUnicodeString(&Temp, &DataStream, True))
|
|
{
|
|
TotSize += pStream->StreamSize.LowPart;
|
|
RtlMoveMemory(StreamName, pStream->StreamName, pStream->StreamNameLength);
|
|
StreamName[pStream->StreamNameLength/sizeof(WCHAR)] = UNICODE_NULL;
|
|
if (Options & STREAMS)
|
|
PrintStreamDetails(LongName, StreamName, pStream->StreamSize);
|
|
}
|
|
tmppsinf = pStream;
|
|
pStream = (FILE_STREAM_INFORMATION *)((CHAR *)pStream + pStream->NextEntryOffset);
|
|
} while (tmppsinf->NextEntryOffset != 0);
|
|
|
|
}
|
|
}
|
|
printf("%s %ld bytes in 1 file\n", (ColumnPos != 0) ? "\n" : "", TotSize);
|
|
}
|
|
|
|
|
|
VOID
|
|
DoEnum(
|
|
HANDLE ParentHandle
|
|
)
|
|
{
|
|
NTSTATUS Status;
|
|
UNICODE_STRING Name;
|
|
HANDLE EntityHandle;
|
|
OBJECT_ATTRIBUTES ObjAttr;
|
|
IO_STATUS_BLOCK IoStsBlk;
|
|
FILE_BOTH_DIR_INFORMATION * pName;
|
|
FILE_STREAM_INFORMATION * pStream;
|
|
FILE_INTERNAL_INFORMATION IntInfo;
|
|
BOOLEAN ReScan = False, SecondScan = False;
|
|
WCHAR LongName[256+1];
|
|
WCHAR ShortName[12+1];
|
|
WCHAR StreamName[256+1];
|
|
LONGLONG DirListBuffer[4096/sizeof(LONGLONG)];
|
|
LONGLONG StreamBuffer[4096/sizeof(LONGLONG)];
|
|
LONG TotSize = 0, Count = 0, ParentLen = wcslen(PathBuffer);
|
|
|
|
pName = (FILE_BOTH_DIR_INFORMATION *)DirListBuffer;
|
|
pStream = (FILE_STREAM_INFORMATION *)StreamBuffer;
|
|
ColumnPos = 0;
|
|
printf("\n %ws\n", PathBuffer);
|
|
|
|
while (True)
|
|
{
|
|
// Read the directory contents
|
|
Status = NtQueryDirectoryFile(ParentHandle,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
&IoStsBlk,
|
|
DirListBuffer,
|
|
sizeof(DirListBuffer),
|
|
FileBothDirectoryInformation,
|
|
True,
|
|
NULL,
|
|
ReScan);
|
|
|
|
if (Status == STATUS_NO_MORE_FILES)
|
|
{
|
|
if (!SecondScan)
|
|
printf("%s %ld bytes in %ld file(s)\n",
|
|
(ColumnPos != 0) ? "\n" : "", TotSize, Count);
|
|
|
|
SecondScan ^= True;
|
|
if (!SecondScan || !(Options & RECURSIVE))
|
|
{
|
|
break;
|
|
}
|
|
ReScan = True;
|
|
continue;
|
|
}
|
|
|
|
if (!NT_SUCCESS(Status) || !NT_SUCCESS(IoStsBlk.Status))
|
|
{
|
|
fprintf(stderr, "Could not query directory. Status %lx\n", Status);
|
|
return;
|
|
}
|
|
|
|
ReScan = False;
|
|
xxInitUnicodeString(&Name, pName->FileName, pName->FileNameLength);
|
|
|
|
if ((pName->FileAttributes & FILE_ATTRIBUTE_SYSTEM) ||
|
|
RtlEqualUnicodeString(&Dot, &Name, True) ||
|
|
RtlEqualUnicodeString(&DotDot, &Name, True))
|
|
continue;
|
|
|
|
Count ++;
|
|
RtlCopyMemory(LongName, pName->FileName, pName->FileNameLength);
|
|
LongName[pName->FileNameLength/sizeof(WCHAR)] = UNICODE_NULL;
|
|
RtlInitUnicodeString(&Name, LongName);
|
|
|
|
RtlCopyMemory(ShortName, pName->ShortName, pName->ShortNameLength);
|
|
ShortName[pName->ShortNameLength/sizeof(WCHAR)] = UNICODE_NULL;
|
|
|
|
if (SecondScan)
|
|
{
|
|
if (pName->FileAttributes & FILE_ATTRIBUTE_DIRECTORY)
|
|
{
|
|
HANDLE ChildHandle;
|
|
|
|
PathBuffer[ParentLen] = L'\\';
|
|
RtlCopyMemory(&PathBuffer[ParentLen + 1],
|
|
pName->FileName,
|
|
pName->FileNameLength);
|
|
PathBuffer[ParentLen + 1 + pName->FileNameLength/sizeof(WCHAR)] = UNICODE_NULL;
|
|
|
|
// Open the directory and recurse
|
|
InitializeObjectAttributes( &ObjAttr,
|
|
&Name,
|
|
OBJ_CASE_INSENSITIVE,
|
|
ParentHandle,
|
|
NULL);
|
|
|
|
Status = NtOpenFile(&ChildHandle,
|
|
FILE_GENERIC_READ,
|
|
&ObjAttr,
|
|
&IoStsBlk,
|
|
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
|
|
FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT);
|
|
|
|
if (!NT_SUCCESS(Status) || !NT_SUCCESS(IoStsBlk.Status))
|
|
{
|
|
fprintf(stderr, "\n***Failed to open directory%ws. Status %lx***\n",
|
|
PathBuffer, Status);
|
|
}
|
|
else DoEnum(ChildHandle);
|
|
|
|
PathBuffer[ParentLen] = UNICODE_NULL;
|
|
continue;
|
|
}
|
|
else continue;
|
|
}
|
|
|
|
if (IsVolNtfs)
|
|
{
|
|
InitializeObjectAttributes(&ObjAttr,
|
|
&Name,
|
|
OBJ_CASE_INSENSITIVE,
|
|
ParentHandle,
|
|
NULL);
|
|
|
|
Status = NtOpenFile(&EntityHandle,
|
|
FILE_GENERIC_READ,
|
|
&ObjAttr,
|
|
&IoStsBlk,
|
|
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
|
|
(pName->FileAttributes & FILE_ATTRIBUTE_DIRECTORY) ?
|
|
(FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT) :
|
|
(FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT));
|
|
|
|
if (!NT_SUCCESS(Status) || !NT_SUCCESS(IoStsBlk.Status))
|
|
{
|
|
fprintf(stderr, "\n***Failed to open %ws. Status %lx***\n",
|
|
LongName, Status);
|
|
ColumnPos = 0;
|
|
continue;
|
|
}
|
|
}
|
|
|
|
if (IsVolNtfs && (Options & INDEX))
|
|
// Get the FILE_ID
|
|
NtQueryInformationFile(EntityHandle,
|
|
&IoStsBlk,
|
|
&IntInfo,
|
|
sizeof(IntInfo),
|
|
FileInternalInformation);
|
|
|
|
TotSize += pName->EndOfFile.LowPart;
|
|
PrintFileDetails(pName->FileAttributes,
|
|
LongName,
|
|
ShortName,
|
|
pName->EndOfFile,
|
|
IntInfo.IndexNumber,
|
|
pName->CreationTime,
|
|
pName->LastWriteTime,
|
|
pName->ChangeTime,
|
|
pName->LastAccessTime);
|
|
|
|
if (IsVolNtfs)
|
|
{
|
|
// And all the streams
|
|
NtQueryInformationFile(EntityHandle,
|
|
&IoStsBlk,
|
|
StreamBuffer,
|
|
sizeof(StreamBuffer),
|
|
FileStreamInformation);
|
|
|
|
if (IoStsBlk.Information != 0)
|
|
{
|
|
PFILE_STREAM_INFORMATION tmppsinf;
|
|
|
|
do
|
|
{
|
|
UNICODE_STRING Temp;
|
|
|
|
xxInitUnicodeString(&Temp, pStream->StreamName, pStream->StreamNameLength);
|
|
if (!RtlEqualUnicodeString(&Temp, &DataStream, True))
|
|
{
|
|
TotSize += pStream->StreamSize.LowPart;
|
|
RtlCopyMemory(StreamName, pStream->StreamName, pStream->StreamNameLength);
|
|
StreamName[pStream->StreamNameLength/sizeof(WCHAR)] = UNICODE_NULL;
|
|
if (Options & STREAMS)
|
|
PrintStreamDetails(LongName, StreamName, pStream->StreamSize);
|
|
}
|
|
tmppsinf = pStream;
|
|
pStream = (FILE_STREAM_INFORMATION *)((CHAR *)pStream + pStream->NextEntryOffset);
|
|
} while (tmppsinf->NextEntryOffset != 0);
|
|
|
|
} // if iostatus.info not zero
|
|
}
|
|
|
|
NtClose(EntityHandle);
|
|
pStream = (FILE_STREAM_INFORMATION *)StreamBuffer;
|
|
}
|
|
}
|
|
|
|
|
|
VOID _cdecl
|
|
main(
|
|
int argc,
|
|
char ** argv
|
|
)
|
|
{
|
|
NTSTATUS Status;
|
|
HANDLE DirectoryHandle;
|
|
OBJECT_ATTRIBUTES ObjAttr;
|
|
IO_STATUS_BLOCK IoStsBlk;
|
|
FILE_FS_ATTRIBUTE_INFORMATION * pVolInfo;
|
|
BOOLEAN IsAFile = False;
|
|
WCHAR VolumeBuffer[64];
|
|
|
|
RtlInitUnicodeString(&Dot, L".");
|
|
RtlInitUnicodeString(&DotDot, L"..");
|
|
RtlInitUnicodeString(&Ntfs, L"NTFS");
|
|
RtlInitUnicodeString(&DataStream, L"::$DATA");
|
|
|
|
if (!GetOptions(argc, argv))
|
|
return;
|
|
|
|
InitializeObjectAttributes( &ObjAttr,
|
|
&DirName,
|
|
OBJ_CASE_INSENSITIVE,
|
|
NULL,
|
|
NULL);
|
|
|
|
Status = NtOpenFile(&DirectoryHandle,
|
|
FILE_GENERIC_READ,
|
|
&ObjAttr,
|
|
&IoStsBlk,
|
|
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
|
|
FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT);
|
|
|
|
if (Status == STATUS_NOT_A_DIRECTORY)
|
|
{
|
|
Status = NtOpenFile(&DirectoryHandle,
|
|
FILE_GENERIC_READ,
|
|
&ObjAttr,
|
|
&IoStsBlk,
|
|
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
|
|
FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT);
|
|
IsAFile = True;
|
|
}
|
|
if (!NT_SUCCESS(Status) || !NT_SUCCESS(IoStsBlk.Status))
|
|
{
|
|
fprintf(stderr, "NtOpenFile Failed (%ws) %lx\n", CDBuffer, Status);
|
|
return;
|
|
}
|
|
|
|
// First get the volume type and set IsVolNtfs if so
|
|
pVolInfo = (FILE_FS_ATTRIBUTE_INFORMATION *)VolumeBuffer;
|
|
Status = NtQueryVolumeInformationFile(
|
|
DirectoryHandle,
|
|
&IoStsBlk,
|
|
VolumeBuffer,
|
|
sizeof(VolumeBuffer),
|
|
FileFsAttributeInformation);
|
|
|
|
xxInitUnicodeString(&FsName,
|
|
pVolInfo->FileSystemName,
|
|
pVolInfo->FileSystemNameLength);
|
|
|
|
if (!RtlEqualUnicodeString(&FsName, &Ntfs, True))
|
|
{
|
|
IsVolNtfs = FALSE;
|
|
}
|
|
|
|
if (IsAFile)
|
|
DoFile(DirectoryHandle); // Actually the file handle here
|
|
else DoEnum(DirectoryHandle);
|
|
|
|
NtClose(DirectoryHandle);
|
|
}
|
|
|