mirror of
https://github.com/ladislav-zezula/FileTest
synced 2026-06-08 15:24:12 +00:00
3786 lines
148 KiB
C++
3786 lines
148 KiB
C++
/*****************************************************************************/
|
|
/* Page06NtFileInfo.cpp Copyright (c) Ladislav Zezula 2005 */
|
|
/*---------------------------------------------------------------------------*/
|
|
/* Description : */
|
|
/*---------------------------------------------------------------------------*/
|
|
/* Date Ver Who Comment */
|
|
/* -------- ---- --- ------- */
|
|
/* 01.11.05 1.00 Lad The first version of Page06NtFileInfo.cpp */
|
|
/*****************************************************************************/
|
|
|
|
#include "FileTest.h"
|
|
#include "resource.h"
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Local defines
|
|
|
|
#define WM_RELOADITEMS (WM_USER + 0x1000)
|
|
#define WM_SHOW_DATE_FORMATS (WM_USER + 0x1001)
|
|
|
|
#define INITIAL_FILEINFO_BUFFER_SIZE 0x10000
|
|
|
|
static UNICODE_STRING NullString = RTL_CONSTANT_STRING(L"NULL");
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Description of data structures for file info classes
|
|
|
|
// Values for FILE_CASE_SENSITIVE_INFORMATION::Flags
|
|
static TFlagInfo CaseSensitiveFlags[] =
|
|
{
|
|
FLAGINFO_BITV(FILE_CS_FLAG_CASE_SENSITIVE_DIR),
|
|
FLAGINFO_END()
|
|
};
|
|
|
|
TStructMember FileStatBasicInformationMembers[] =
|
|
{
|
|
{_T("FileId"), TYPE_FILEID64, sizeof(LARGE_INTEGER)},
|
|
{_T("CreationTime"), TYPE_FILETIME, sizeof(LARGE_INTEGER)},
|
|
{_T("LastAccessTime"), TYPE_FILETIME, sizeof(LARGE_INTEGER)},
|
|
{_T("LastWriteTime"), TYPE_FILETIME, sizeof(LARGE_INTEGER)},
|
|
{_T("ChangeTime"), TYPE_FILETIME, sizeof(LARGE_INTEGER)},
|
|
{_T("AllocationSize"), TYPE_UINT64, sizeof(LARGE_INTEGER)},
|
|
{_T("EndOfFile"), TYPE_UINT64, sizeof(LARGE_INTEGER)},
|
|
{_T("FileAttributes"), TYPE_FLAG32, sizeof(ULONG), NULL, {(TStructMember*)FileAttributesValues}},
|
|
{_T("ReparseTag"), TYPE_UINT32, sizeof(ULONG)},
|
|
{_T("NumberOfLinks"), TYPE_UINT32, sizeof(ULONG)},
|
|
{_T("DeviceType"), TYPE_UINT32, sizeof(ULONG)},
|
|
{_T("DeviceCharacteristics"), TYPE_UINT32, sizeof(ULONG)},
|
|
{_T("Reserved"), TYPE_UINT32, sizeof(ULONG)},
|
|
{_T("VolumeSerialNumber"), TYPE_UINT64, sizeof(LARGE_INTEGER)},
|
|
{_T("FileId"), TYPE_FILEID128, sizeof(FILE_ID_128)},
|
|
{NULL}
|
|
};
|
|
|
|
TStructMember FileId64ExtdDirectoryInformationMembers[] =
|
|
{
|
|
{_T("NextEntryOffset"), TYPE_UINT32, sizeof(ULONG)},
|
|
{_T("FileIndex"), TYPE_UINT32, sizeof(ULONG)},
|
|
{_T("CreationTime"), TYPE_FILETIME, sizeof(LARGE_INTEGER)},
|
|
{_T("LastAccessTime"), TYPE_FILETIME, sizeof(LARGE_INTEGER)},
|
|
{_T("LastWriteTime"), TYPE_FILETIME, sizeof(LARGE_INTEGER)},
|
|
{_T("ChangeTime"), TYPE_FILETIME, sizeof(LARGE_INTEGER)},
|
|
{_T("EndOfFile"), TYPE_UINT64, sizeof(LARGE_INTEGER)},
|
|
{_T("AllocationSize"), TYPE_UINT64, sizeof(LARGE_INTEGER)},
|
|
{_T("FileAttributes"), TYPE_FLAG32, sizeof(ULONG), NULL, {(TStructMember*)FileAttributesValues}},
|
|
{_T("FileNameLength"), TYPE_UINT32, sizeof(ULONG)},
|
|
{_T("EaSize"), TYPE_UINT32, sizeof(ULONG)},
|
|
{_T("ReparsePointTag"), TYPE_UINT32, sizeof(ULONG)},
|
|
{_T("FileId"), TYPE_FILEID64, sizeof(LARGE_INTEGER)},
|
|
{_T("FileName"), TYPE_WNAME_L32B, FIELD_OFFSET(FILE_ID_EXTD_DIR_INFORMATION, FileNameLength)},
|
|
{NULL}
|
|
};
|
|
|
|
TStructMember FileId64ExtdBothDirectoryInformationMembers[] =
|
|
{
|
|
{_T("NextEntryOffset"), TYPE_UINT32, sizeof(ULONG)},
|
|
{_T("FileIndex"), TYPE_UINT32, sizeof(ULONG)},
|
|
{_T("CreationTime"), TYPE_FILETIME, sizeof(LARGE_INTEGER)},
|
|
{_T("LastAccessTime"), TYPE_FILETIME, sizeof(LARGE_INTEGER)},
|
|
{_T("LastWriteTime"), TYPE_FILETIME, sizeof(LARGE_INTEGER)},
|
|
{_T("ChangeTime"), TYPE_FILETIME, sizeof(LARGE_INTEGER)},
|
|
{_T("EndOfFile"), TYPE_UINT64, sizeof(LARGE_INTEGER)},
|
|
{_T("AllocationSize"), TYPE_UINT64, sizeof(LARGE_INTEGER)},
|
|
{_T("FileAttributes"), TYPE_FLAG32, sizeof(ULONG), NULL, {(TStructMember*)FileAttributesValues}},
|
|
{_T("FileNameLength"), TYPE_UINT32, sizeof(ULONG)},
|
|
{_T("EaSize"), TYPE_UINT32, sizeof(ULONG)},
|
|
{_T("ReparsePointTag"), TYPE_UINT32, sizeof(ULONG)},
|
|
{_T("FileId"), TYPE_FILEID64, sizeof(LARGE_INTEGER)},
|
|
{_T("ShortNameLength"), TYPE_UINT8, sizeof(CCHAR)},
|
|
{_T("<padding>"), TYPE_PADDING, sizeof(WCHAR)},
|
|
{_T("ShortName"), TYPE_VNAME_FIEBD, sizeof(WCHAR[12])},
|
|
{_T("FileName"), TYPE_WNAME_L32B, FIELD_OFFSET(FILE_ID_EXTD_DIR_INFORMATION, FileNameLength)},
|
|
{NULL}
|
|
};
|
|
|
|
TStructMember FileIdAllExtdDirectoryInformationMembers[] =
|
|
{
|
|
{_T("NextEntryOffset"), TYPE_UINT32, sizeof(ULONG)},
|
|
{_T("FileIndex"), TYPE_UINT32, sizeof(ULONG)},
|
|
{_T("CreationTime"), TYPE_FILETIME, sizeof(LARGE_INTEGER)},
|
|
{_T("LastAccessTime"), TYPE_FILETIME, sizeof(LARGE_INTEGER)},
|
|
{_T("LastWriteTime"), TYPE_FILETIME, sizeof(LARGE_INTEGER)},
|
|
{_T("ChangeTime"), TYPE_FILETIME, sizeof(LARGE_INTEGER)},
|
|
{_T("EndOfFile"), TYPE_UINT64, sizeof(LARGE_INTEGER)},
|
|
{_T("AllocationSize"), TYPE_UINT64, sizeof(LARGE_INTEGER)},
|
|
{_T("FileAttributes"), TYPE_FLAG32, sizeof(ULONG), NULL, {(TStructMember*)FileAttributesValues}},
|
|
{_T("FileNameLength"), TYPE_UINT32, sizeof(ULONG)},
|
|
{_T("EaSize"), TYPE_UINT32, sizeof(ULONG)},
|
|
{_T("ReparsePointTag"), TYPE_UINT32, sizeof(ULONG)},
|
|
{_T("FileId"), TYPE_FILEID64, sizeof(LARGE_INTEGER)},
|
|
{_T("FileId128"), TYPE_FILEID128, sizeof(FILE_ID_128)},
|
|
{_T("FileName"), TYPE_WNAME_L32B, FIELD_OFFSET(FILE_ID_EXTD_DIR_INFORMATION, FileNameLength)},
|
|
{NULL}
|
|
};
|
|
|
|
TStructMember FileIdAllExtdBothDirectoryInformationMembers[] =
|
|
{
|
|
{_T("NextEntryOffset"), TYPE_UINT32, sizeof(ULONG)},
|
|
{_T("FileIndex"), TYPE_UINT32, sizeof(ULONG)},
|
|
{_T("CreationTime"), TYPE_FILETIME, sizeof(LARGE_INTEGER)},
|
|
{_T("LastAccessTime"), TYPE_FILETIME, sizeof(LARGE_INTEGER)},
|
|
{_T("LastWriteTime"), TYPE_FILETIME, sizeof(LARGE_INTEGER)},
|
|
{_T("ChangeTime"), TYPE_FILETIME, sizeof(LARGE_INTEGER)},
|
|
{_T("EndOfFile"), TYPE_UINT64, sizeof(LARGE_INTEGER)},
|
|
{_T("AllocationSize"), TYPE_UINT64, sizeof(LARGE_INTEGER)},
|
|
{_T("FileAttributes"), TYPE_FLAG32, sizeof(ULONG), NULL, {(TStructMember*)FileAttributesValues}},
|
|
{_T("FileNameLength"), TYPE_UINT32, sizeof(ULONG)},
|
|
{_T("EaSize"), TYPE_UINT32, sizeof(ULONG)},
|
|
{_T("ReparsePointTag"), TYPE_UINT32, sizeof(ULONG)},
|
|
{_T("FileId"), TYPE_FILEID64, sizeof(LARGE_INTEGER)},
|
|
{_T("FileId128"), TYPE_FILEID128, sizeof(FILE_ID_128)},
|
|
{_T("ShortNameLength"), TYPE_UINT8, sizeof(CCHAR)},
|
|
{_T("<padding>"), TYPE_PADDING, sizeof(WCHAR)},
|
|
{_T("ShortName"), TYPE_VNAME_FIEBD, sizeof(WCHAR[12])},
|
|
{_T("FileName"), TYPE_WNAME_L32B, FIELD_OFFSET(FILE_ID_EXTD_DIR_INFORMATION, FileNameLength)},
|
|
{NULL}
|
|
};
|
|
|
|
// Values for FILE_FS_ATTRIBUTE_INFORMATION::FileSystemAttributes
|
|
TFlagInfo FileSystemAttributesValues[] =
|
|
{
|
|
FLAGINFO_BITV(FILE_CASE_SENSITIVE_SEARCH),
|
|
FLAGINFO_BITV(FILE_CASE_PRESERVED_NAMES),
|
|
FLAGINFO_BITV(FILE_UNICODE_ON_DISK),
|
|
FLAGINFO_BITV(FILE_PERSISTENT_ACLS),
|
|
FLAGINFO_BITV(FILE_FILE_COMPRESSION),
|
|
FLAGINFO_BITV(FILE_VOLUME_QUOTAS),
|
|
FLAGINFO_BITV(FILE_SUPPORTS_SPARSE_FILES),
|
|
FLAGINFO_BITV(FILE_SUPPORTS_REPARSE_POINTS),
|
|
FLAGINFO_BITV(FILE_SUPPORTS_REMOTE_STORAGE),
|
|
FLAGINFO_BITV(FILE_RETURNS_CLEANUP_RESULT_INFO),
|
|
FLAGINFO_BITV(FILE_SUPPORTS_POSIX_UNLINK_RENAME),
|
|
FLAGINFO_BITV(FILE_SUPPORTS_BYPASS_IO),
|
|
FLAGINFO_BITV(FILE_SUPPORTS_STREAM_SNAPSHOTS),
|
|
FLAGINFO_BITV(FILE_SUPPORTS_CASE_SENSITIVE_DIRS),
|
|
FLAGINFO_BITV(FILE_VOLUME_IS_COMPRESSED),
|
|
FLAGINFO_BITV(FILE_SUPPORTS_OBJECT_IDS),
|
|
FLAGINFO_BITV(FILE_SUPPORTS_ENCRYPTION),
|
|
FLAGINFO_BITV(FILE_NAMED_STREAMS),
|
|
FLAGINFO_BITV(FILE_READ_ONLY_VOLUME),
|
|
FLAGINFO_BITV(FILE_SEQUENTIAL_WRITE_ONCE),
|
|
FLAGINFO_BITV(FILE_SUPPORTS_TRANSACTIONS),
|
|
FLAGINFO_BITV(FILE_SUPPORTS_HARD_LINKS),
|
|
FLAGINFO_BITV(FILE_SUPPORTS_EXTENDED_ATTRIBUTES),
|
|
FLAGINFO_BITV(FILE_SUPPORTS_OPEN_BY_FILE_ID),
|
|
FLAGINFO_BITV(FILE_SUPPORTS_USN_JOURNAL),
|
|
FLAGINFO_BITV(FILE_SUPPORTS_INTEGRITY_STREAMS),
|
|
FLAGINFO_BITV(FILE_SUPPORTS_BLOCK_REFCOUNTING),
|
|
FLAGINFO_BITV(FILE_SUPPORTS_SPARSE_VDL),
|
|
FLAGINFO_BITV(FILE_DAX_VOLUME),
|
|
FLAGINFO_BITV(FILE_SUPPORTS_GHOSTING),
|
|
FLAGINFO_END()
|
|
};
|
|
|
|
TStructMember FileUnknownInformationMembers[] =
|
|
{
|
|
{_T("BinaryData"), TYPE_ARRAY8_VARIABLE, 0},
|
|
{NULL, TYPE_NONE, 0}
|
|
};
|
|
|
|
TStructMember FileDirectoryInformationMembers[] =
|
|
{
|
|
{_T("NextEntryOffset"), TYPE_UINT32, sizeof(ULONG)},
|
|
{_T("FileIndex"), TYPE_UINT32, sizeof(ULONG)},
|
|
{_T("CreationTime"), TYPE_FILETIME, sizeof(LARGE_INTEGER)},
|
|
{_T("LastAccessTime"), TYPE_FILETIME, sizeof(LARGE_INTEGER)},
|
|
{_T("LastWriteTime"), TYPE_FILETIME, sizeof(LARGE_INTEGER)},
|
|
{_T("ChangeTime"), TYPE_FILETIME, sizeof(LARGE_INTEGER)},
|
|
{_T("EndOfFile"), TYPE_UINT64, sizeof(LARGE_INTEGER)},
|
|
{_T("AllocationSize"), TYPE_UINT64, sizeof(LARGE_INTEGER)},
|
|
{_T("FileAttributes"), TYPE_FLAG32, sizeof(ULONG), NULL, {(TStructMember *)FileAttributesValues}},
|
|
{_T("FileNameLength"), TYPE_UINT32, sizeof(ULONG)},
|
|
{_T("FileName"), TYPE_WNAME_L32B, FIELD_OFFSET(FILE_DIRECTORY_INFORMATION, FileNameLength)},
|
|
{NULL}
|
|
};
|
|
|
|
TStructMember FileFullDirectoryInformationMembers[] =
|
|
{
|
|
{_T("NextEntryOffset"), TYPE_UINT32, sizeof(ULONG)},
|
|
{_T("FileIndex"), TYPE_UINT32, sizeof(ULONG)},
|
|
{_T("CreationTime"), TYPE_FILETIME, sizeof(LARGE_INTEGER)},
|
|
{_T("LastAccessTime"), TYPE_FILETIME, sizeof(LARGE_INTEGER)},
|
|
{_T("LastWriteTime"), TYPE_FILETIME, sizeof(LARGE_INTEGER)},
|
|
{_T("ChangeTime"), TYPE_FILETIME, sizeof(LARGE_INTEGER)},
|
|
{_T("EndOfFile"), TYPE_UINT64, sizeof(LARGE_INTEGER)},
|
|
{_T("AllocationSize"), TYPE_UINT64, sizeof(LARGE_INTEGER)},
|
|
{_T("FileAttributes"), TYPE_FLAG32, sizeof(ULONG), NULL, {(TStructMember *)FileAttributesValues}},
|
|
{_T("FileNameLength"), TYPE_UINT32, sizeof(ULONG)},
|
|
{_T("EaSize"), TYPE_UINT32, sizeof(ULONG)},
|
|
{_T("FileName"), TYPE_WNAME_L32B, FIELD_OFFSET(FILE_FULL_DIR_INFORMATION, FileNameLength)},
|
|
{NULL}
|
|
};
|
|
|
|
TStructMember FileBothDirectoryInformationMembers[] =
|
|
{
|
|
{_T("NextEntryOffset"), TYPE_UINT32, sizeof(ULONG)},
|
|
{_T("FileIndex"), TYPE_UINT32, sizeof(ULONG)},
|
|
{_T("CreationTime"), TYPE_FILETIME, sizeof(LARGE_INTEGER)},
|
|
{_T("LastAccessTime"), TYPE_FILETIME, sizeof(LARGE_INTEGER)},
|
|
{_T("LastWriteTime"), TYPE_FILETIME, sizeof(LARGE_INTEGER)},
|
|
{_T("ChangeTime"), TYPE_FILETIME, sizeof(LARGE_INTEGER)},
|
|
{_T("EndOfFile"), TYPE_UINT64, sizeof(LARGE_INTEGER)},
|
|
{_T("AllocationSize"), TYPE_UINT64, sizeof(LARGE_INTEGER)},
|
|
{_T("FileAttributes"), TYPE_FLAG32, sizeof(ULONG), NULL, {(TStructMember *)FileAttributesValues}},
|
|
{_T("FileNameLength"), TYPE_UINT32, sizeof(ULONG)},
|
|
{_T("EaSize"), TYPE_UINT32, sizeof(ULONG)},
|
|
{_T("ShortNameLength"), TYPE_UINT8, sizeof(BYTE)}, // Although CCHAR, it has 2 bytes because of alignment
|
|
{_T("<padding>"), TYPE_PADDING, sizeof(WCHAR)},
|
|
{_T("ShortName"), TYPE_VNAME_FBDI, sizeof(WCHAR[12])},
|
|
{_T("FileName"), TYPE_WNAME_L32B, FIELD_OFFSET(FILE_BOTH_DIR_INFORMATION, FileNameLength)},
|
|
{NULL}
|
|
};
|
|
|
|
TStructMember FileBasicInformationMembers[] =
|
|
{
|
|
{_T("CreationTime"), TYPE_FILETIME, sizeof(LARGE_INTEGER)},
|
|
{_T("LastAccessTime"), TYPE_FILETIME, sizeof(LARGE_INTEGER)},
|
|
{_T("LastWriteTime"), TYPE_FILETIME, sizeof(LARGE_INTEGER)},
|
|
{_T("ChangeTime"), TYPE_FILETIME, sizeof(LARGE_INTEGER)},
|
|
{_T("FileAttributes"), TYPE_FLAG32, sizeof(ULONG), NULL, {(TStructMember *)FileAttributesValues}},
|
|
{NULL, TYPE_NONE, 0}
|
|
};
|
|
|
|
TStructMember FileStandardInformationMembers[] =
|
|
{
|
|
{_T("AllocationSize"), TYPE_UINT64, sizeof(LARGE_INTEGER)},
|
|
{_T("EndOfFile"), TYPE_UINT64, sizeof(LARGE_INTEGER)},
|
|
{_T("NumberOfLinks"), TYPE_UINT32, sizeof(ULONG)},
|
|
{_T("DeletePending"), TYPE_BOOLEAN, sizeof(BOOLEAN)},
|
|
{_T("Directory"), TYPE_BOOLEAN, sizeof(BOOLEAN)},
|
|
{NULL, TYPE_NONE, 0}
|
|
};
|
|
|
|
TStructMember FileStandardInformationMembersEx[] =
|
|
{
|
|
{ _T("AllocationSize"), TYPE_UINT64, sizeof(LARGE_INTEGER) },
|
|
{ _T("EndOfFile"), TYPE_UINT64, sizeof(LARGE_INTEGER) },
|
|
{ _T("NumberOfLinks"), TYPE_UINT32, sizeof(ULONG) },
|
|
{ _T("DeletePending"), TYPE_BOOLEAN, sizeof(BOOLEAN) },
|
|
{ _T("Directory"), TYPE_BOOLEAN, sizeof(BOOLEAN) },
|
|
{ _T("AlternateStream"), TYPE_BOOLEAN, sizeof(BOOLEAN) },
|
|
{ _T("MetadataAttribute"), TYPE_BOOLEAN, sizeof(BOOLEAN) },
|
|
{ NULL, TYPE_NONE, 0 }
|
|
};
|
|
|
|
TStructMember FileInternalInformationMembers[] =
|
|
{
|
|
{_T("IndexNumber"), TYPE_FILEID64, sizeof(LARGE_INTEGER)},
|
|
{NULL, TYPE_NONE, 0}
|
|
};
|
|
|
|
TStructMember FileEaInformationMembers[] =
|
|
{
|
|
{_T("EaSize"), TYPE_UINT32, sizeof(ULONG)},
|
|
{NULL, TYPE_NONE, 0}
|
|
};
|
|
|
|
TStructMember FileAccessInformationMembers[] =
|
|
{
|
|
{_T("AccessFlags"), TYPE_FLAG32, sizeof(ACCESS_MASK), NULL, {(TStructMember *)AccessMaskValues}},
|
|
{NULL, TYPE_NONE, 0}
|
|
};
|
|
|
|
TStructMember FileNameInformationMembers[] =
|
|
{
|
|
{_T("FileNameLength"), TYPE_UINT32, sizeof(ULONG)},
|
|
{_T("FileName"), TYPE_WNAME_L32B, FIELD_OFFSET(FILE_NAME_INFORMATION, FileNameLength)},
|
|
{NULL, TYPE_NONE, 0}
|
|
};
|
|
|
|
TStructMember FileRenameInformationMembers[] =
|
|
{
|
|
{_T("ReplaceIfExists"), TYPE_BOOLEAN, sizeof(BOOLEAN)},
|
|
{_T("<padding>"), TYPE_PADDING, sizeof(HANDLE)},
|
|
{_T("RootDirectory"), TYPE_DIR_HANDLE, sizeof(HANDLE)},
|
|
{_T("FileNameLength"), TYPE_UINT32, sizeof(ULONG)},
|
|
{_T("FileName"), TYPE_WNAME_L32B, FIELD_OFFSET(FILE_RENAME_INFORMATION, FileNameLength)},
|
|
{NULL, TYPE_NONE, 0}
|
|
};
|
|
|
|
TStructMember FileLinkInformationMembers[] =
|
|
{
|
|
{_T("ReplaceIfExists"), TYPE_BOOLEAN, sizeof(ULONG)},
|
|
{_T("<padding>"), TYPE_PADDING, sizeof(HANDLE)},
|
|
{_T("RootDirectory"), TYPE_DIR_HANDLE, sizeof(HANDLE)},
|
|
{_T("FileNameLength"), TYPE_UINT32, sizeof(ULONG)},
|
|
{_T("FileName"), TYPE_WNAME_L32B, FIELD_OFFSET(FILE_LINK_INFORMATION, FileNameLength)},
|
|
{NULL, TYPE_NONE, 0}
|
|
};
|
|
|
|
TStructMember FileLinkEntryMembers[] =
|
|
{
|
|
{_T("NextEntryOffset"), TYPE_UINT32, sizeof(LARGE_INTEGER)}, // alignment
|
|
{_T("ParentFileId"), TYPE_FILEID64,sizeof(LARGE_INTEGER)},
|
|
{_T("FileNameLength"), TYPE_UINT32, sizeof(ULONG)},
|
|
{_T("FileName"), TYPE_WNAME_L32W, FIELD_OFFSET(FILE_LINK_ENTRY_INFORMATION, FileNameLength)},
|
|
{NULL, TYPE_NONE, 0}
|
|
};
|
|
|
|
TStructMember FileNamesInformationMembers[] =
|
|
{
|
|
{_T("NextEntryOffset"), TYPE_UINT32, sizeof(ULONG)},
|
|
{_T("FileIndex"), TYPE_UINT32, sizeof(ULONG)},
|
|
{_T("FileNameLength"), TYPE_UINT32, sizeof(ULONG)},
|
|
{_T("FileName"), TYPE_WNAME_L32B, FIELD_OFFSET(FILE_NAMES_INFORMATION, FileNameLength)},
|
|
{NULL, TYPE_NONE, 0}
|
|
};
|
|
|
|
TStructMember FileDispositionInformationMembers[] =
|
|
{
|
|
{_T("DeleteFile"), TYPE_BOOLEAN, sizeof(BOOLEAN)},
|
|
{NULL, TYPE_NONE, 0}
|
|
};
|
|
|
|
TStructMember FilePositionInformationMembers[] =
|
|
{
|
|
{_T("CurrentByteOffset"), TYPE_UINT64, sizeof(LARGE_INTEGER)},
|
|
{NULL, TYPE_NONE, 0}
|
|
};
|
|
|
|
TStructMember FileFullEaInformationMembers[] =
|
|
{
|
|
{_T("NextEntryOffset"), TYPE_UINT32, sizeof(ULONG)},
|
|
{_T("Flags"), TYPE_UINT8, sizeof(UCHAR)},
|
|
{_T("EaNameLength"), TYPE_UINT8, sizeof(UCHAR)},
|
|
{_T("EaValueLength"), TYPE_UINT16, sizeof(USHORT)},
|
|
{_T("EaName"), TYPE_CNAME_L8B, FIELD_OFFSET(FILE_FULL_EA_INFORMATION, EaNameLength)},
|
|
// {_T("EaValue"), TYPE_ARRAY, FIELD_OFFSET(FILE_FULL_EA_INFORMATION, EaValueLength)},
|
|
{NULL, TYPE_NONE, 0}
|
|
};
|
|
|
|
TStructMember FileModeInformationMembers[] =
|
|
{
|
|
{_T("Mode"), TYPE_FLAG32, sizeof(ULONG), NULL, {(TStructMember *)CreateOptionsValues}},
|
|
{NULL, TYPE_NONE, 0}
|
|
};
|
|
|
|
static TFlagInfo FileAlignmentValues[] =
|
|
{
|
|
FLAGINFO_NUMV(FILE_BYTE_ALIGNMENT),
|
|
FLAGINFO_NUMV(FILE_WORD_ALIGNMENT),
|
|
FLAGINFO_NUMV(FILE_LONG_ALIGNMENT),
|
|
FLAGINFO_NUMV(FILE_QUAD_ALIGNMENT),
|
|
FLAGINFO_NUMV(FILE_OCTA_ALIGNMENT),
|
|
FLAGINFO_NUMV(FILE_32_BYTE_ALIGNMENT),
|
|
FLAGINFO_NUMV(FILE_64_BYTE_ALIGNMENT),
|
|
FLAGINFO_NUMV(FILE_128_BYTE_ALIGNMENT),
|
|
FLAGINFO_NUMV(FILE_256_BYTE_ALIGNMENT),
|
|
FLAGINFO_NUMV(FILE_512_BYTE_ALIGNMENT),
|
|
FLAGINFO_END()
|
|
};
|
|
|
|
TStructMember FileAlignmentInformationMembers[] =
|
|
{
|
|
{_T("AlignmentRequirement"), TYPE_FLAG32, sizeof(ULONG), NULL, {(TStructMember *)FileAlignmentValues}},
|
|
{NULL, TYPE_NONE, 0}
|
|
};
|
|
|
|
TStructMember FileAllInformationMembers[] =
|
|
{
|
|
{_T("FILE_BASIC_INFORMATION"), TYPE_STRUCT, sizeof(FILE_BASIC_INFORMATION), NULL, {FileBasicInformationMembers}},
|
|
{_T("FILE_STANDARD_INFORMATION"), TYPE_STRUCT, sizeof(FILE_STANDARD_INFORMATION), NULL, {FileStandardInformationMembers}},
|
|
{_T("FILE_INTERNAL_INFORMATION"), TYPE_STRUCT, sizeof(FILE_INTERNAL_INFORMATION), NULL, {FileInternalInformationMembers}},
|
|
{_T("FILE_EA_INFORMATION"), TYPE_STRUCT, sizeof(FILE_EA_INFORMATION), NULL, {FileEaInformationMembers}},
|
|
{_T("FILE_ACCESS_INFORMATION"), TYPE_STRUCT, sizeof(FILE_ACCESS_INFORMATION), NULL, {FileAccessInformationMembers}},
|
|
{_T("FILE_POSITION_INFORMATION"), TYPE_STRUCT, sizeof(FILE_POSITION_INFORMATION), NULL, {FilePositionInformationMembers}},
|
|
{_T("FILE_MODE_INFORMATION"), TYPE_STRUCT, sizeof(FILE_MODE_INFORMATION), NULL, {FileModeInformationMembers}},
|
|
{_T("FILE_ALIGNMENT_INFORMATION"),TYPE_STRUCT, sizeof(FILE_ALIGNMENT_INFORMATION), NULL, {FileAlignmentInformationMembers}},
|
|
{_T("FILE_NAME_INFORMATION"), TYPE_STRUCT, sizeof(FILE_NAME_INFORMATION), NULL, {FileNameInformationMembers}},
|
|
{NULL, TYPE_NONE, 0}
|
|
};
|
|
|
|
TStructMember FileAllocationInformationMembers[] =
|
|
{
|
|
{_T("AllocationSize"), TYPE_UINT64, sizeof(LARGE_INTEGER)},
|
|
{NULL, TYPE_NONE, 0}
|
|
};
|
|
|
|
TStructMember FileEndOfFileInformationMembers[] =
|
|
{
|
|
{_T("EndOfFile"), TYPE_UINT64, sizeof(LARGE_INTEGER)},
|
|
{NULL, TYPE_NONE, 0}
|
|
};
|
|
|
|
#define FileAlternateNameInformationMembers FileNameInformationMembers
|
|
|
|
TStructMember FileStreamInformationMembers[] =
|
|
{
|
|
{_T("NextEntryOffset"), TYPE_UINT32, sizeof(ULONG)},
|
|
{_T("StreamNameLength"), TYPE_UINT32, sizeof(ULONG)},
|
|
{_T("StreamSize"), TYPE_UINT64, sizeof(LARGE_INTEGER)},
|
|
{_T("StreamAllocationSize"), TYPE_UINT64, sizeof(LARGE_INTEGER)},
|
|
{_T("StreamName"), TYPE_WNAME_L32B, FIELD_OFFSET(FILE_STREAM_INFORMATION, StreamNameLength)},
|
|
{NULL, TYPE_NONE, 0}
|
|
};
|
|
|
|
static TFlagInfo FilePipeReadModeValues[] =
|
|
{
|
|
FLAGINFO_NUMV(FILE_PIPE_BYTE_STREAM_MODE),
|
|
FLAGINFO_NUMV(FILE_PIPE_MESSAGE_MODE),
|
|
FLAGINFO_END()
|
|
};
|
|
|
|
static TFlagInfo FilePipeCompletionModeValues[] =
|
|
{
|
|
FLAGINFO_NUMV(FILE_PIPE_QUEUE_OPERATION),
|
|
FLAGINFO_NUMV(FILE_PIPE_COMPLETE_OPERATION),
|
|
FLAGINFO_END()
|
|
};
|
|
|
|
TStructMember FilePipeInformationMembers[] =
|
|
{
|
|
{_T("ReadMode"), TYPE_FLAG32, sizeof(ULONG), NULL, {(TStructMember *)FilePipeReadModeValues}},
|
|
{_T("CompletionMode"), TYPE_FLAG32, sizeof(ULONG), NULL, {(TStructMember *)FilePipeCompletionModeValues}},
|
|
{NULL, TYPE_NONE, 0}
|
|
};
|
|
|
|
static TFlagInfo FilePipeTypeValues[] =
|
|
{
|
|
FLAGINFO_MASK(FILE_PIPE_BYTE_STREAM_TYPE | FILE_PIPE_MESSAGE_TYPE, FILE_PIPE_BYTE_STREAM_MODE),
|
|
FLAGINFO_MASK(FILE_PIPE_BYTE_STREAM_TYPE | FILE_PIPE_MESSAGE_TYPE, FILE_PIPE_MESSAGE_TYPE),
|
|
FLAGINFO_BITV(FILE_PIPE_REJECT_REMOTE_CLIENTS),
|
|
FLAGINFO_END()
|
|
};
|
|
|
|
static TFlagInfo FilePipeConfigurationValues[] =
|
|
{
|
|
FLAGINFO_NUMV(FILE_PIPE_INBOUND),
|
|
FLAGINFO_NUMV(FILE_PIPE_OUTBOUND),
|
|
FLAGINFO_NUMV(FILE_PIPE_FULL_DUPLEX),
|
|
FLAGINFO_END()
|
|
};
|
|
|
|
static TFlagInfo FilePipeStateValues[] =
|
|
{
|
|
FLAGINFO_NUMV(FILE_PIPE_DISCONNECTED_STATE),
|
|
FLAGINFO_NUMV(FILE_PIPE_LISTENING_STATE),
|
|
FLAGINFO_NUMV(FILE_PIPE_CONNECTED_STATE),
|
|
FLAGINFO_NUMV(FILE_PIPE_CLOSING_STATE),
|
|
FLAGINFO_END()
|
|
};
|
|
|
|
static TFlagInfo FilePipeEndValues[] =
|
|
{
|
|
FLAGINFO_NUMV(FILE_PIPE_CLIENT_END),
|
|
FLAGINFO_NUMV(FILE_PIPE_SERVER_END),
|
|
FLAGINFO_END()
|
|
};
|
|
|
|
TStructMember FilePipeLocalInformationMembers[] =
|
|
{
|
|
{_T("NamedPipeType"), TYPE_FLAG32, sizeof(ULONG), NULL, {(TStructMember *)FilePipeTypeValues}},
|
|
{_T("NamedPipeConfiguration"), TYPE_FLAG32, sizeof(ULONG), NULL, {(TStructMember *)FilePipeConfigurationValues}},
|
|
{_T("MaximumInstances"), TYPE_UINT32, sizeof(ULONG)},
|
|
{_T("CurrentInstances"), TYPE_UINT32, sizeof(ULONG)},
|
|
{_T("InboundQuota"), TYPE_UINT32, sizeof(ULONG)},
|
|
{_T("ReadDataAvailable"), TYPE_UINT32, sizeof(ULONG)},
|
|
{_T("OutboundQuota"), TYPE_UINT32, sizeof(ULONG)},
|
|
{_T("WriteQuotaAvailable"), TYPE_UINT32, sizeof(ULONG)},
|
|
{_T("NamedPipeState"), TYPE_FLAG32, sizeof(ULONG), NULL, {(TStructMember *)FilePipeStateValues}},
|
|
{_T("NamedPipeEnd"), TYPE_FLAG32, sizeof(ULONG), NULL, {(TStructMember *)FilePipeEndValues}},
|
|
{NULL, TYPE_NONE, 0}
|
|
};
|
|
|
|
TStructMember FilePipeRemoteInformationMembers[] =
|
|
{
|
|
{_T("CollectDataTime"), TYPE_UINT64, sizeof(LARGE_INTEGER)},
|
|
{_T("MaximumCollectionCount"), TYPE_UINT32, sizeof(ULONG)},
|
|
{NULL, TYPE_NONE, 0}
|
|
};
|
|
|
|
TStructMember FileMailslotQueryInformationMembers[] =
|
|
{
|
|
{_T("MaximumMessageSize"), TYPE_UINT32, sizeof(ULONG)},
|
|
{_T("MailslotQuota"), TYPE_UINT32, sizeof(ULONG)},
|
|
{_T("NextMessageSize"), TYPE_UINT32, sizeof(ULONG)},
|
|
{_T("MessagesAvailable"), TYPE_UINT32, sizeof(ULONG)},
|
|
{_T("ReadTimeout"), TYPE_UINT64, sizeof(LARGE_INTEGER)},
|
|
{NULL, TYPE_NONE, 0}
|
|
};
|
|
|
|
TStructMember FileMailslotSetInformationMembers[] =
|
|
{
|
|
{_T("ReadTimeout"), TYPE_UINT64, sizeof(LARGE_INTEGER)},
|
|
{NULL, TYPE_NONE, 0}
|
|
};
|
|
|
|
static TFlagInfo FileCompressionFormatValues[] =
|
|
{
|
|
FLAGINFO_NUMV(COMPRESSION_FORMAT_NONE),
|
|
FLAGINFO_NUMV(COMPRESSION_FORMAT_DEFAULT),
|
|
FLAGINFO_NUMV(COMPRESSION_FORMAT_LZNT1),
|
|
FLAGINFO_END()
|
|
};
|
|
|
|
TStructMember FileCompressionInformationMembers[] =
|
|
{
|
|
{_T("CompressedFileSize"), TYPE_UINT64, sizeof(LARGE_INTEGER)},
|
|
{_T("CompressionFormat"), TYPE_FLAG16, sizeof(USHORT), NULL, {(TStructMember *)FileCompressionFormatValues}},
|
|
{_T("CompressionUnitShift"), TYPE_UINT8, sizeof(UCHAR)},
|
|
{_T("ChunkShift"), TYPE_UINT8, sizeof(UCHAR)},
|
|
{_T("ClusterShift"), TYPE_UINT8, sizeof(UCHAR)},
|
|
{_T("Reserved[0]"), TYPE_UINT8, sizeof(UCHAR)},
|
|
{_T("Reserved[1]"), TYPE_UINT8, sizeof(UCHAR)},
|
|
{_T("Reserved[2]"), TYPE_UINT8, sizeof(UCHAR)},
|
|
{NULL, TYPE_NONE, 0}
|
|
};
|
|
|
|
TStructMember FileObjectIdInformationMembers[] =
|
|
{
|
|
{_T("FileReference"), TYPE_FILEID64, sizeof(LONGLONG)},
|
|
{_T("ObjectId"), TYPE_FILEID128, sizeof(UCHAR[16])},
|
|
{_T("BirthVolumeId"), TYPE_GUID, sizeof(UCHAR[16])},
|
|
{_T("BirthObjectId"), TYPE_FILEID128, sizeof(UCHAR[16])},
|
|
{_T("DomainId"), TYPE_GUID, sizeof(UCHAR[16])},
|
|
{NULL, TYPE_NONE, 0}
|
|
};
|
|
|
|
TStructMember FileCompletionInformationMembers[] =
|
|
{
|
|
{_T("Port"), TYPE_HANDLE, sizeof(HANDLE)},
|
|
{_T("Key"), TYPE_POINTER, sizeof(PVOID)},
|
|
{NULL, TYPE_NONE, 0}
|
|
};
|
|
|
|
TStructMember FileMoveClusterInformationMembers[] =
|
|
{
|
|
{_T("ClusterCount"), TYPE_UINT32, sizeof(ULONG)},
|
|
{_T("<padding>"), TYPE_PADDING, sizeof(HANDLE)},
|
|
{_T("RootDirectory"), TYPE_DIR_HANDLE, sizeof(HANDLE)},
|
|
{_T("FileNameLength"), TYPE_FILETIME, sizeof(ULONG)},
|
|
{_T("FileName"), TYPE_WNAME_L32B, FIELD_OFFSET(FILE_MOVE_CLUSTER_INFORMATION, FileNameLength)},
|
|
{NULL, TYPE_NONE, 0}
|
|
};
|
|
|
|
TStructMember FileQuotaInformationMembers[] =
|
|
{
|
|
{_T("NextEntryOffset"), TYPE_UINT32, sizeof(ULONG)},
|
|
{_T("SidLength"), TYPE_UINT32, sizeof(ULONG)},
|
|
{_T("ChangeTime"), TYPE_FILETIME, sizeof(LARGE_INTEGER)},
|
|
{_T("QuotaUsed"), TYPE_UINT64, sizeof(LARGE_INTEGER)},
|
|
{_T("QuotaThreshold"), TYPE_UINT64, sizeof(LARGE_INTEGER)},
|
|
{_T("QuotaLimit"), TYPE_UINT64, sizeof(LARGE_INTEGER)},
|
|
{_T("Sid"), TYPE_SID, sizeof(SID)},
|
|
{NULL, TYPE_NONE, 0}
|
|
};
|
|
|
|
TStructMember FileReparsePointInformationMembers[] =
|
|
{
|
|
{_T("FileReference"), TYPE_FILEID64, sizeof(LONGLONG)},
|
|
{_T("Tag"), TYPE_UINT32, sizeof(ULONG)},
|
|
{NULL, TYPE_NONE, 0}
|
|
};
|
|
|
|
TStructMember FileNetworkOpenInformationMembers[] =
|
|
{
|
|
{_T("CreationTime"), TYPE_FILETIME, sizeof(LARGE_INTEGER)},
|
|
{_T("LastAccessTime"), TYPE_FILETIME, sizeof(LARGE_INTEGER)},
|
|
{_T("LastWriteTime"), TYPE_FILETIME, sizeof(LARGE_INTEGER)},
|
|
{_T("ChangeTime"), TYPE_FILETIME, sizeof(LARGE_INTEGER)},
|
|
{_T("AllocationSize"), TYPE_UINT64, sizeof(LARGE_INTEGER)},
|
|
{_T("EndOfFile"), TYPE_UINT64, sizeof(LARGE_INTEGER)},
|
|
{_T("FileAttributes"), TYPE_FLAG32, sizeof(ULONG), NULL, {(TStructMember *)FileAttributesValues}},
|
|
{NULL, TYPE_NONE, 0}
|
|
};
|
|
|
|
TStructMember FileAttributeTagInformationMembers[] =
|
|
{
|
|
{_T("FileAttributes"), TYPE_FLAG32, sizeof(ULONG), NULL, {(TStructMember *)FileAttributesValues}},
|
|
{_T("ReparseTag"), TYPE_UINT32, sizeof(ULONG)},
|
|
{NULL, TYPE_NONE, 0}
|
|
};
|
|
|
|
TStructMember FileTrackingInformationMembers[] =
|
|
{
|
|
{_T("DestinationFile"), TYPE_HANDLE, sizeof(HANDLE)},
|
|
{_T("ObjectInformationLength"), TYPE_UINT32, sizeof(ULONG)},
|
|
{_T("ObjectInformation"), TYPE_UINT8, sizeof(CHAR)}, // TODO: TYPE_FTI_NAME
|
|
{NULL, TYPE_NONE, 0}
|
|
};
|
|
|
|
TStructMember FileIdBothDirectoryInformationMembers[] =
|
|
{
|
|
{_T("NextEntryOffset"), TYPE_UINT32, sizeof(ULONG)},
|
|
{_T("FileIndex"), TYPE_UINT32, sizeof(ULONG)},
|
|
{_T("CreationTime"), TYPE_FILETIME, sizeof(LARGE_INTEGER)},
|
|
{_T("LastAccessTime"), TYPE_FILETIME, sizeof(LARGE_INTEGER)},
|
|
{_T("LastWriteTime"), TYPE_FILETIME, sizeof(LARGE_INTEGER)},
|
|
{_T("ChangeTime"), TYPE_FILETIME, sizeof(LARGE_INTEGER)},
|
|
{_T("EndOfFile"), TYPE_UINT64, sizeof(LARGE_INTEGER)},
|
|
{_T("AllocationSize"), TYPE_UINT64, sizeof(LARGE_INTEGER)},
|
|
{_T("FileAttributes"), TYPE_FLAG32, sizeof(ULONG), NULL, {(TStructMember *)FileAttributesValues}},
|
|
{_T("FileNameLength"), TYPE_UINT32, sizeof(ULONG)},
|
|
{_T("EaSize"), TYPE_UINT32, sizeof(ULONG)},
|
|
{_T("ShortNameLength"), TYPE_UINT8, sizeof(BYTE)}, // Although CCHAR, it has 2 bytes because of alignment
|
|
{_T("<padding>"), TYPE_PADDING, sizeof(WCHAR)},
|
|
{_T("ShortName"), TYPE_VNAME_FIBD, sizeof(WCHAR[13])}, // One more WCHAR due to alignment
|
|
{_T("FileId"), TYPE_FILEID64, sizeof(LARGE_INTEGER)},
|
|
{_T("FileName"), TYPE_WNAME_L32B, FIELD_OFFSET(FILE_ID_BOTH_DIR_INFORMATION, FileNameLength)},
|
|
{NULL}
|
|
};
|
|
|
|
TStructMember FileIdFullDirectoryInformationMembers[] =
|
|
{
|
|
{_T("NextEntryOffset"), TYPE_UINT32, sizeof(ULONG)},
|
|
{_T("FileIndex"), TYPE_UINT32, sizeof(ULONG)},
|
|
{_T("CreationTime"), TYPE_FILETIME, sizeof(LARGE_INTEGER)},
|
|
{_T("LastAccessTime"), TYPE_FILETIME, sizeof(LARGE_INTEGER)},
|
|
{_T("LastWriteTime"), TYPE_FILETIME, sizeof(LARGE_INTEGER)},
|
|
{_T("ChangeTime"), TYPE_FILETIME, sizeof(LARGE_INTEGER)},
|
|
{_T("EndOfFile"), TYPE_UINT64, sizeof(LARGE_INTEGER)},
|
|
{_T("AllocationSize"), TYPE_UINT64, sizeof(LARGE_INTEGER)},
|
|
{_T("FileAttributes"), TYPE_FLAG32, sizeof(ULONG), NULL, {(TStructMember *)FileAttributesValues}},
|
|
{_T("FileNameLength"), TYPE_UINT32, sizeof(ULONG)},
|
|
{_T("EaSize"), TYPE_UINT32, sizeof(LARGE_INTEGER)}, // Size is larger due to alignment
|
|
{_T("FileId"), TYPE_FILEID64, sizeof(LARGE_INTEGER)},
|
|
{_T("FileName"), TYPE_WNAME_L32B, FIELD_OFFSET(FILE_ID_FULL_DIR_INFORMATION, FileNameLength)},
|
|
{NULL}
|
|
};
|
|
|
|
TStructMember FileValidDataLengthInformationMembers[] =
|
|
{
|
|
{_T("ValidDataLength"), TYPE_UINT64, sizeof(LARGE_INTEGER)},
|
|
{NULL, TYPE_NONE, 0}
|
|
};
|
|
|
|
#define FileShortNameInformationMembers FileNameInformationMembers
|
|
|
|
TStructMember FileIoCompletionNotificationInformationMembers[] =
|
|
{
|
|
{_T("Flags"), TYPE_UINT32, sizeof(ULONG)},
|
|
{NULL, TYPE_NONE, 0}
|
|
};
|
|
|
|
TStructMember FileIoStatusBlockRangeInformationMembers[] =
|
|
{
|
|
{_T("IoStatusBlockRange"), TYPE_POINTER, sizeof(void *)},
|
|
{_T("Length"), TYPE_UINT32, sizeof(ULONG)},
|
|
{NULL, TYPE_NONE, 0}
|
|
};
|
|
|
|
static TFlagInfo IoPriorityHintValues[] =
|
|
{
|
|
FLAGINFO_NUMV(IoPriorityVeryLow),
|
|
FLAGINFO_NUMV(IoPriorityLow),
|
|
FLAGINFO_NUMV(IoPriorityNormal),
|
|
FLAGINFO_NUMV(IoPriorityHigh),
|
|
FLAGINFO_NUMV(IoPriorityCritical),
|
|
FLAGINFO_END()
|
|
};
|
|
|
|
TStructMember FileIoPriorityHintInformationMembers[] =
|
|
{
|
|
{_T("PriorityHint"), TYPE_FLAG32, sizeof(IO_PRIORITY_HINT), NULL, {(TStructMember *)IoPriorityHintValues}},
|
|
{NULL, TYPE_NONE, 0}
|
|
};
|
|
|
|
TStructMember FileSfioReserveInformationMembers[] =
|
|
{
|
|
{_T("RequestsPerPeriod"), TYPE_UINT32, sizeof(ULONG)},
|
|
{_T("Period"), TYPE_UINT32, sizeof(ULONG)},
|
|
{_T("RetryFailures"), TYPE_BOOLEAN, sizeof(BOOLEAN)},
|
|
{_T("Discardable"), TYPE_BOOLEAN, sizeof(BOOLEAN)},
|
|
{_T("<padding>"), TYPE_PADDING, sizeof(ULONG)},
|
|
{_T("RequestSize"), TYPE_UINT32, sizeof(ULONG)},
|
|
{_T("NumOutstandingRequests"), TYPE_UINT32, sizeof(ULONG)},
|
|
{NULL, TYPE_NONE, 0}
|
|
};
|
|
|
|
TStructMember FileSfioVolumeInformationMembers[] =
|
|
{
|
|
{_T("MaximumRequestsPerPeriod"), TYPE_UINT32, sizeof(ULONG)},
|
|
{_T("MinimumPeriod"), TYPE_UINT32, sizeof(ULONG)},
|
|
{_T("MinimumTransferSize"),TYPE_UINT32, sizeof(ULONG)},
|
|
{NULL, TYPE_NONE, 0}
|
|
};
|
|
|
|
TStructMember FileHardLinkInformationMembers[] =
|
|
{
|
|
{_T("BytesNeeded"), TYPE_UINT32, sizeof(ULONG)},
|
|
{_T("EntriesReturned"), TYPE_UINT32, sizeof(ULONG)},
|
|
{_T("Entry"), TYPE_CHAINED_STRUCT, 0, NULL, FileLinkEntryMembers},
|
|
{NULL, TYPE_NONE, 0}
|
|
};
|
|
|
|
TStructMember FileProcessIdsUsingFileInformationMembers[] =
|
|
{
|
|
{_T("NumberOfProcessIdsInList"), TYPE_UINT32, sizeof(ULONG)},
|
|
{_T("<padding>"), TYPE_PADDING, sizeof(HANDLE)},
|
|
{_T("ProcessIdList"), TYPE_ARRAY_PROCESS, FIELD_OFFSET(FILE_PROCESS_IDS_USING_FILE_INFORMATION, NumberOfProcessIdsInList)},
|
|
{NULL, TYPE_NONE, 0}
|
|
};
|
|
|
|
TStructMember FileNetworkPhysicalNameInformationMembers[] =
|
|
{
|
|
{_T("FileNameLength"), TYPE_UINT32, sizeof(ULONG)},
|
|
{_T("FileName"), TYPE_WNAME_L32B, FIELD_OFFSET(FILE_NAME_INFORMATION, FileNameLength)},
|
|
{NULL, TYPE_NONE, 0}
|
|
};
|
|
|
|
TStructMember FileNormalizedNameInformationMembers[] =
|
|
{
|
|
{_T("FileNameLength"), TYPE_UINT32, sizeof(ULONG)},
|
|
{_T("FileName"), TYPE_WNAME_L32B, FIELD_OFFSET(FILE_NAME_INFORMATION, FileNameLength)},
|
|
{NULL, TYPE_NONE, 0}
|
|
};
|
|
|
|
TFlagInfo FileTxFlagsValues[] =
|
|
{
|
|
FLAGINFO_BITV(FILE_ID_GLOBAL_TX_DIR_INFO_FLAG_WRITELOCKED),
|
|
FLAGINFO_BITV(FILE_ID_GLOBAL_TX_DIR_INFO_FLAG_VISIBLE_TO_TX),
|
|
FLAGINFO_BITV(FILE_ID_GLOBAL_TX_DIR_INFO_FLAG_VISIBLE_OUTSIDE_TX),
|
|
FLAGINFO_END()
|
|
};
|
|
|
|
TStructMember FileIdGlobalTxDirectoryInformationMembers[] =
|
|
{
|
|
{_T("NextEntryOffset"), TYPE_UINT32, sizeof(ULONG)},
|
|
{_T("FileIndex"), TYPE_UINT32, sizeof(ULONG)},
|
|
{_T("CreationTime"), TYPE_FILETIME, sizeof(LARGE_INTEGER)},
|
|
{_T("LastAccessTime"), TYPE_FILETIME, sizeof(LARGE_INTEGER)},
|
|
{_T("LastWriteTime"), TYPE_FILETIME, sizeof(LARGE_INTEGER)},
|
|
{_T("ChangeTime"), TYPE_FILETIME, sizeof(LARGE_INTEGER)},
|
|
{_T("EndOfFile"), TYPE_UINT64, sizeof(LARGE_INTEGER)},
|
|
{_T("AllocationSize"), TYPE_UINT64, sizeof(LARGE_INTEGER)},
|
|
{_T("FileAttributes"), TYPE_FLAG32, sizeof(ULONG), NULL, {(TStructMember *)FileAttributesValues}},
|
|
{_T("FileNameLength"), TYPE_UINT32, sizeof(ULONG)},
|
|
{_T("FileId"), TYPE_FILEID64, sizeof(LARGE_INTEGER)},
|
|
{_T("LockingTransactionId"), TYPE_GUID, sizeof(GUID)},
|
|
{_T("TxInfoFlags"), TYPE_FLAG32, sizeof(ULONG), NULL, {(TStructMember *)FileTxFlagsValues}},
|
|
{_T("FileName"), TYPE_WNAME_L32B, FIELD_OFFSET(FILE_ID_GLOBAL_TX_DIR_INFORMATION, FileNameLength)},
|
|
{NULL, TYPE_NONE, 0}
|
|
};
|
|
|
|
TStructMember FileIsRemoteDeviceInformationMembers[] =
|
|
{
|
|
{_T("IsRemote"), TYPE_BOOLEAN, sizeof(BOOLEAN)},
|
|
{NULL, TYPE_NONE, 0}
|
|
};
|
|
|
|
TStructMember FileNumaNodeInformationMembers[] =
|
|
{
|
|
{_T("NodeNumber"), TYPE_UINT32, sizeof(ULONG)},
|
|
{NULL, TYPE_NONE, 0}
|
|
};
|
|
|
|
TStructMember FileStandardLinkInformationMembers[] =
|
|
{
|
|
{_T("NumberOfAccessibleLinks"), TYPE_UINT32, sizeof(ULONG)},
|
|
{_T("TotalNumberOfLinks"), TYPE_UINT32, sizeof(ULONG)},
|
|
{_T("DeletePending"), TYPE_BOOLEAN, sizeof(BOOLEAN)},
|
|
{_T("Directory"), TYPE_BOOLEAN, sizeof(BOOLEAN)},
|
|
{NULL, TYPE_NONE, 0}
|
|
};
|
|
|
|
TStructMember FileRemoteProtocolInformationMembers[] =
|
|
{
|
|
{_T("StructureVersion"), TYPE_UINT16, sizeof(USHORT)},
|
|
{_T("StructureSize"), TYPE_UINT16, sizeof(USHORT)},
|
|
{_T("Protocol"), TYPE_UINT32, sizeof(ULONG)},
|
|
{_T("ProtocolMajorVersion"), TYPE_UINT16, sizeof(USHORT)},
|
|
{_T("ProtocolMinorVersion"), TYPE_UINT16, sizeof(USHORT)},
|
|
{_T("ProtocolRevision"), TYPE_UINT16, sizeof(USHORT)},
|
|
{_T("Reserved"), TYPE_UINT16, sizeof(USHORT)},
|
|
{_T("GenericReserved.Reserved[0x0]"), TYPE_UINT32, sizeof(ULONG)},
|
|
{_T("GenericReserved.Reserved[0x1]"), TYPE_UINT32, sizeof(ULONG)},
|
|
{_T("GenericReserved.Reserved[0x2]"), TYPE_UINT32, sizeof(ULONG)},
|
|
{_T("GenericReserved.Reserved[0x3]"), TYPE_UINT32, sizeof(ULONG)},
|
|
{_T("GenericReserved.Reserved[0x4]"), TYPE_UINT32, sizeof(ULONG)},
|
|
{_T("GenericReserved.Reserved[0x5]"), TYPE_UINT32, sizeof(ULONG)},
|
|
{_T("GenericReserved.Reserved[0x6]"), TYPE_UINT32, sizeof(ULONG)},
|
|
{_T("GenericReserved.Reserved[0x7]"), TYPE_UINT32, sizeof(ULONG)},
|
|
{_T("ProtocolReserved.Reserved[0x0]"), TYPE_UINT32, sizeof(ULONG)},
|
|
{_T("ProtocolReserved.Reserved[0x1]"), TYPE_UINT32, sizeof(ULONG)},
|
|
{_T("ProtocolReserved.Reserved[0x2]"), TYPE_UINT32, sizeof(ULONG)},
|
|
{_T("ProtocolReserved.Reserved[0x3]"), TYPE_UINT32, sizeof(ULONG)},
|
|
{_T("ProtocolReserved.Reserved[0x4]"), TYPE_UINT32, sizeof(ULONG)},
|
|
{_T("ProtocolReserved.Reserved[0x5]"), TYPE_UINT32, sizeof(ULONG)},
|
|
{_T("ProtocolReserved.Reserved[0x6]"), TYPE_UINT32, sizeof(ULONG)},
|
|
{_T("ProtocolReserved.Reserved[0x7]"), TYPE_UINT32, sizeof(ULONG)},
|
|
{_T("ProtocolReserved.Reserved[0x8]"), TYPE_UINT32, sizeof(ULONG)},
|
|
{_T("ProtocolReserved.Reserved[0x9]"), TYPE_UINT32, sizeof(ULONG)},
|
|
{_T("ProtocolReserved.Reserved[0xA]"), TYPE_UINT32, sizeof(ULONG)},
|
|
{_T("ProtocolReserved.Reserved[0xB]"), TYPE_UINT32, sizeof(ULONG)},
|
|
{_T("ProtocolReserved.Reserved[0xC]"), TYPE_UINT32, sizeof(ULONG)},
|
|
{_T("ProtocolReserved.Reserved[0xD]"), TYPE_UINT32, sizeof(ULONG)},
|
|
{_T("ProtocolReserved.Reserved[0xE]"), TYPE_UINT32, sizeof(ULONG)},
|
|
{_T("ProtocolReserved.Reserved[0xF]"), TYPE_UINT32, sizeof(ULONG)},
|
|
{NULL, TYPE_NONE, 0}
|
|
};
|
|
|
|
TStructMember FileVolumeNameInformationMembers[] =
|
|
{
|
|
{_T("DeviceNameLength"), TYPE_UINT32, sizeof(ULONG)},
|
|
{_T("DeviceName"), TYPE_WNAME_L32B, FIELD_OFFSET(FILE_VOLUME_NAME_INFORMATION, DeviceNameLength)},
|
|
{NULL, TYPE_NONE, 0}
|
|
};
|
|
|
|
TStructMember FileIdInformationMembers[] =
|
|
{
|
|
{_T("VolumeSerialNumber"), TYPE_UINT64, sizeof(LARGE_INTEGER)},
|
|
{_T("FileId"), TYPE_FILEID128, sizeof(FILE_ID_128)},
|
|
{NULL, TYPE_NONE, 0}
|
|
};
|
|
|
|
TStructMember FileIdExtdDirectoryInformationMembers[] =
|
|
{
|
|
{_T("NextEntryOffset"), TYPE_UINT32, sizeof(ULONG)},
|
|
{_T("FileIndex"), TYPE_UINT32, sizeof(ULONG)},
|
|
{_T("CreationTime"), TYPE_FILETIME, sizeof(LARGE_INTEGER)},
|
|
{_T("LastAccessTime"), TYPE_FILETIME, sizeof(LARGE_INTEGER)},
|
|
{_T("LastWriteTime"), TYPE_FILETIME, sizeof(LARGE_INTEGER)},
|
|
{_T("ChangeTime"), TYPE_FILETIME, sizeof(LARGE_INTEGER)},
|
|
{_T("EndOfFile"), TYPE_UINT64, sizeof(LARGE_INTEGER)},
|
|
{_T("AllocationSize"), TYPE_UINT64, sizeof(LARGE_INTEGER)},
|
|
{_T("FileAttributes"), TYPE_FLAG32, sizeof(ULONG), NULL, {(TStructMember *)FileAttributesValues}},
|
|
{_T("FileNameLength"), TYPE_UINT32, sizeof(ULONG)},
|
|
{_T("EaSize"), TYPE_UINT32, sizeof(ULONG)},
|
|
{_T("ReparsePointTag"), TYPE_UINT32, sizeof(ULONG)},
|
|
{_T("FileId"), TYPE_FILEID128, sizeof(FILE_ID_128)},
|
|
{_T("FileName"), TYPE_WNAME_L32B, FIELD_OFFSET(FILE_ID_EXTD_DIR_INFORMATION, FileNameLength)},
|
|
{NULL}
|
|
};
|
|
|
|
TStructMember FileHardLinkFullIdInformationMembers[] =
|
|
{
|
|
{_T("NextEntryOffset"), TYPE_UINT32, sizeof(ULONG)},
|
|
{_T("<alignment>"), TYPE_UINT32, sizeof(ULONG)},
|
|
{_T("ParentFileId"), TYPE_FILEID128, sizeof(FILE_ID_128)},
|
|
{_T("FileName"), TYPE_WNAME_L32B, FIELD_OFFSET(FILE_LINK_ENTRY_FULL_ID_INFORMATION, FileNameLength)},
|
|
{NULL}
|
|
};
|
|
|
|
TStructMember FileIdExtdBothDirectoryInformationMembers[] =
|
|
{
|
|
{_T("NextEntryOffset"), TYPE_UINT32, sizeof(ULONG)},
|
|
{_T("FileIndex"), TYPE_UINT32, sizeof(ULONG)},
|
|
{_T("CreationTime"), TYPE_FILETIME, sizeof(LARGE_INTEGER)},
|
|
{_T("LastAccessTime"), TYPE_FILETIME, sizeof(LARGE_INTEGER)},
|
|
{_T("LastWriteTime"), TYPE_FILETIME, sizeof(LARGE_INTEGER)},
|
|
{_T("ChangeTime"), TYPE_FILETIME, sizeof(LARGE_INTEGER)},
|
|
{_T("EndOfFile"), TYPE_UINT64, sizeof(LARGE_INTEGER)},
|
|
{_T("AllocationSize"), TYPE_UINT64, sizeof(LARGE_INTEGER)},
|
|
{_T("FileAttributes"), TYPE_FLAG32, sizeof(ULONG), NULL, {(TStructMember *)FileAttributesValues}},
|
|
{_T("FileNameLength"), TYPE_UINT32, sizeof(ULONG)},
|
|
{_T("EaSize"), TYPE_UINT32, sizeof(ULONG)},
|
|
{_T("ReparsePointTag"), TYPE_UINT32, sizeof(ULONG)},
|
|
{_T("FileId"), TYPE_FILEID128, sizeof(FILE_ID_128)},
|
|
{_T("ShortNameLength"), TYPE_UINT8, sizeof(BYTE)}, // Although CCHAR, it has 2 bytes because of alignment
|
|
{_T("<padding>"), TYPE_PADDING, sizeof(WCHAR)},
|
|
{_T("ShortName"), TYPE_VNAME_FIEBD, sizeof(WCHAR[12])},
|
|
{_T("FileName"), TYPE_WNAME_L32B, FIELD_OFFSET(FILE_BOTH_DIR_INFORMATION, FileNameLength)},
|
|
{NULL}
|
|
};
|
|
|
|
TFlagInfo FileDispositionInformationExValues[] =
|
|
{
|
|
// FLAGINFO_BITV(FILE_DISPOSITION_DO_NOT_DELETE), // Zero; not an actual flag
|
|
FLAGINFO_BITV(FILE_DISPOSITION_DELETE),
|
|
FLAGINFO_BITV(FILE_DISPOSITION_POSIX_SEMANTICS),
|
|
FLAGINFO_BITV(FILE_DISPOSITION_FORCE_IMAGE_SECTION_CHECK),
|
|
FLAGINFO_BITV(FILE_DISPOSITION_ON_CLOSE),
|
|
FLAGINFO_BITV(FILE_DISPOSITION_IGNORE_READONLY_ATTRIBUTE),
|
|
FLAGINFO_END()
|
|
};
|
|
|
|
TStructMember FileDispositionInformationExMembers[] =
|
|
{
|
|
{ _T("DispositionFlags"), TYPE_FLAG32, sizeof(ULONG), NULL, {(TStructMember *)FileDispositionInformationExValues}},
|
|
{ NULL, TYPE_NONE, 0 }
|
|
};
|
|
|
|
TFlagInfo FileRenameInformationExValues[] =
|
|
{
|
|
FLAGINFO_BITV(FILE_RENAME_REPLACE_IF_EXISTS),
|
|
FLAGINFO_BITV(FILE_RENAME_POSIX_SEMANTICS),
|
|
FLAGINFO_BITV(FILE_RENAME_SUPPRESS_PIN_STATE_INHERITANCE),
|
|
FLAGINFO_BITV(FILE_RENAME_SUPPRESS_STORAGE_RESERVE_INHERITANCE),
|
|
FLAGINFO_BITV(FILE_RENAME_NO_INCREASE_AVAILABLE_SPACE),
|
|
FLAGINFO_BITV(FILE_RENAME_NO_DECREASE_AVAILABLE_SPACE),
|
|
FLAGINFO_BITV(FILE_RENAME_IGNORE_READONLY_ATTRIBUTE),
|
|
FLAGINFO_BITV(FILE_RENAME_FORCE_RESIZE_TARGET_SR),
|
|
FLAGINFO_BITV(FILE_RENAME_FORCE_RESIZE_SOURCE_SR),
|
|
FLAGINFO_END()
|
|
};
|
|
|
|
TStructMember FileRenameInformationExMembers[] =
|
|
{
|
|
{ _T("Flags"), TYPE_FLAG32, sizeof(ULONG), NULL, {(TStructMember *)FileRenameInformationExValues}},
|
|
{ _T("<padding>"), TYPE_PADDING, sizeof(HANDLE) },
|
|
{ _T("RootDirectory"), TYPE_DIR_HANDLE, sizeof(HANDLE) },
|
|
{ _T("FileNameLength"), TYPE_UINT32, sizeof(ULONG) },
|
|
{ _T("FileName"), TYPE_WNAME_L32B, FIELD_OFFSET(FILE_RENAME_INFORMATION_EX, FileNameLength) },
|
|
{ NULL, TYPE_NONE, 0 }
|
|
};
|
|
|
|
TFlagInfo FileStorageClassValues[] =
|
|
{
|
|
FLAGINFO_NUMV(FileStorageTierClassUnspecified),
|
|
FLAGINFO_NUMV(FileStorageTierClassCapacity),
|
|
FLAGINFO_NUMV(FileStorageTierClassPerformance),
|
|
FLAGINFO_END()
|
|
};
|
|
|
|
TFlagInfo FileStorageFlagsValues[] =
|
|
{
|
|
FLAGINFO_BITV(QUERY_STORAGE_CLASSES_FLAGS_MEASURE_WRITE),
|
|
FLAGINFO_BITV(QUERY_STORAGE_CLASSES_FLAGS_MEASURE_READ),
|
|
FLAGINFO_END()
|
|
};
|
|
|
|
TStructMember FileDesiredStorageClassInformationMembers[] =
|
|
{
|
|
{_T("Class"), TYPE_FLAG32, sizeof(ULONG), NULL, {(TStructMember *)FileStorageClassValues}},
|
|
{_T("Flags"), TYPE_FLAG32, sizeof(ULONG), NULL, {(TStructMember *)FileStorageFlagsValues}},
|
|
{ NULL }
|
|
};
|
|
|
|
TStructMember FileStatInformationMembers[] =
|
|
{
|
|
{_T("FileId"), TYPE_FILEID64, sizeof(LARGE_INTEGER)},
|
|
{_T("CreationTime"), TYPE_FILETIME, sizeof(LARGE_INTEGER)},
|
|
{_T("LastAccessTime"), TYPE_FILETIME, sizeof(LARGE_INTEGER)},
|
|
{_T("LastWriteTime"), TYPE_FILETIME, sizeof(LARGE_INTEGER)},
|
|
{_T("ChangeTime"), TYPE_FILETIME, sizeof(LARGE_INTEGER)},
|
|
{_T("AllocationSize"), TYPE_UINT64, sizeof(LARGE_INTEGER)},
|
|
{_T("EndOfFile"), TYPE_UINT64, sizeof(LARGE_INTEGER)},
|
|
{_T("FileAttributes"), TYPE_FLAG32, sizeof(ULONG), NULL, {(TStructMember *)FileAttributesValues}},
|
|
{_T("ReparseTag"), TYPE_UINT32, sizeof(ULONG)},
|
|
{_T("NumberOfLinks"), TYPE_UINT32, sizeof(ULONG)},
|
|
{_T("EffectiveAccess"), TYPE_FLAG32, sizeof(ACCESS_MASK), NULL, {(TStructMember *)AccessMaskValues}},
|
|
{ NULL, TYPE_NONE, 0 }
|
|
};
|
|
|
|
TStructMember FileMemoryPartitionInformationMembers[] =
|
|
{
|
|
{_T("OwnerPartitionHandle"), TYPE_HANDLE, sizeof(TYPE_HANDLE)},
|
|
{_T("AllFlags"), TYPE_UINT32, sizeof(UINT32)},
|
|
{ NULL, TYPE_NONE, 0 }
|
|
};
|
|
|
|
TFlagInfo FileLxFlagsValues[] =
|
|
{
|
|
FLAGINFO_BITV(LX_FILE_METADATA_HAS_UID),
|
|
FLAGINFO_BITV(LX_FILE_METADATA_HAS_GID),
|
|
FLAGINFO_BITV(LX_FILE_METADATA_HAS_MODE),
|
|
FLAGINFO_BITV(LX_FILE_METADATA_HAS_DEVICE_ID),
|
|
FLAGINFO_BITV(LX_FILE_CASE_SENSITIVE_DIR),
|
|
FLAGINFO_END()
|
|
};
|
|
|
|
TStructMember FileStatLxInformationMembers[] =
|
|
{
|
|
{_T("FileId"), TYPE_UINT64, sizeof(LARGE_INTEGER)},
|
|
{_T("CreationTime"), TYPE_FILETIME, sizeof(LARGE_INTEGER)},
|
|
{_T("LastAccessTime"), TYPE_FILETIME, sizeof(LARGE_INTEGER)},
|
|
{_T("LastWriteTime"), TYPE_FILETIME, sizeof(LARGE_INTEGER)},
|
|
{_T("ChangeTime"), TYPE_FILETIME, sizeof(LARGE_INTEGER)},
|
|
{_T("AllocationSize"), TYPE_UINT64, sizeof(LARGE_INTEGER)},
|
|
{_T("EndOfFile"), TYPE_UINT64, sizeof(LARGE_INTEGER)},
|
|
{_T("FileAttributes"), TYPE_FLAG32, sizeof(ULONG), NULL, {(TStructMember *)FileAttributesValues}},
|
|
{_T("ReparseTag"), TYPE_UINT32, sizeof(ULONG)},
|
|
{_T("NumberOfLinks"), TYPE_UINT32, sizeof(ULONG)},
|
|
{_T("AccessMask"), TYPE_FLAG32, sizeof(ULONG), NULL, {(TStructMember *)AccessMaskValues}},
|
|
{_T("EffectiveAccess"), TYPE_FLAG32, sizeof(ULONG), NULL, {(TStructMember *)AccessMaskValues}},
|
|
{_T("LxFlags"), TYPE_FLAG32, sizeof(ULONG), NULL, {(TStructMember *)FileLxFlagsValues}},
|
|
{_T("LxUid"), TYPE_UINT32, sizeof(ULONG)},
|
|
{_T("LxGid"), TYPE_UINT32, sizeof(ULONG)},
|
|
{_T("LxMode"), TYPE_UINT32, sizeof(ULONG)},
|
|
{_T("LxDeviceIdMajor"), TYPE_UINT32, sizeof(ULONG)},
|
|
{_T("LxDeviceIdMinor"), TYPE_UINT32, sizeof(ULONG)},
|
|
{ NULL, TYPE_NONE, 0 }
|
|
};
|
|
|
|
TStructMember FileCaseSensitiveInformationMembers[] =
|
|
{
|
|
{_T("Flags"), TYPE_FLAG32, sizeof(ULONG), NULL, {(TStructMember *)CaseSensitiveFlags}},
|
|
{ NULL, TYPE_NONE, 0 }
|
|
};
|
|
|
|
TFlagInfo FileLinkInformationExValues[] =
|
|
{
|
|
FLAGINFO_BITV(FILE_LINK_REPLACE_IF_EXISTS),
|
|
FLAGINFO_BITV(FILE_LINK_POSIX_SEMANTICS),
|
|
FLAGINFO_BITV(FILE_LINK_SUPPRESS_STORAGE_RESERVE_INHERITANCE),
|
|
FLAGINFO_BITV(FILE_LINK_NO_INCREASE_AVAILABLE_SPACE),
|
|
FLAGINFO_BITV(FILE_LINK_NO_DECREASE_AVAILABLE_SPACE),
|
|
FLAGINFO_BITV(FILE_LINK_IGNORE_READONLY_ATTRIBUTE),
|
|
FLAGINFO_BITV(FILE_LINK_FORCE_RESIZE_TARGET_SR),
|
|
FLAGINFO_BITV(FILE_LINK_FORCE_RESIZE_SOURCE_SR),
|
|
FLAGINFO_END()
|
|
};
|
|
|
|
TStructMember FileLinkInformationExMembers[] =
|
|
{
|
|
{_T("Flags"), TYPE_FLAG32, sizeof(ULONG), NULL, {(TStructMember *)FileLinkInformationExValues}},
|
|
{_T("<padding>"), TYPE_PADDING, sizeof(HANDLE) },
|
|
{_T("RootDirectory"), TYPE_DIR_HANDLE, sizeof(HANDLE)},
|
|
{_T("FileNameLength"), TYPE_UINT32, sizeof(ULONG)},
|
|
{_T("FileName"), TYPE_WNAME_L32B, FIELD_OFFSET(FILE_LINK_INFORMATION, FileNameLength)},
|
|
{NULL, TYPE_NONE, 0}
|
|
};
|
|
|
|
TStructMember FileStorageReserveIdInformationMembers[] =
|
|
{
|
|
{_T("StorageReserveId"), TYPE_UINT32, sizeof(ULONG)},
|
|
{NULL, TYPE_NONE, 0}
|
|
};
|
|
|
|
TFlagInfo FileKnownFolderValues[] =
|
|
{
|
|
FLAGINFO_NUMV(KnownFolderNone),
|
|
FLAGINFO_NUMV(KnownFolderDesktop),
|
|
FLAGINFO_NUMV(KnownFolderDocuments),
|
|
FLAGINFO_NUMV(KnownFolderDownloads),
|
|
FLAGINFO_NUMV(KnownFolderMusic),
|
|
FLAGINFO_NUMV(KnownFolderPictures),
|
|
FLAGINFO_NUMV(KnownFolderVideos),
|
|
FLAGINFO_END()
|
|
};
|
|
|
|
TStructMember FileKnownFolderInformationMembers[] =
|
|
{
|
|
{_T("Type"), TYPE_FLAG32, sizeof(ULONG), NULL, {(TStructMember *)FileKnownFolderValues}},
|
|
{NULL, TYPE_NONE, 0}
|
|
};
|
|
|
|
#define FileAttributeCacheInformationMembers FileUnknownInformationMembers
|
|
#define FileRenameInformationBypassAccessCheckMembers FileRenameInformationMembers
|
|
#define FileLinkInformationBypassAccessCheckMembers FileLinkInformationMembers
|
|
#define FileReplaceCompletionInformationMembers FileCompletionInformationMembers
|
|
#define FileRenameInformationExBypassAccessCheckMembers FileRenameInformationExMembers
|
|
#define FileCaseSensitiveInformationBypassAccessCheckMembers FileCaseSensitiveInformationMembers
|
|
#define FileLinkInformationExBypassAccessCheckMembers FileLinkInformationExMembers
|
|
#define FileCaseSensitiveInformationForceAccessCheckMembers FileCaseSensitiveInformationMembers
|
|
|
|
TInfoData FileInfoData[] =
|
|
{
|
|
FILE_INFO_READONLY(FileDirectoryInformation, FILE_DIRECTORY_INFORMATION, TRUE),
|
|
FILE_INFO_READONLY(FileFullDirectoryInformation, FILE_FULL_DIR_INFORMATION, TRUE),
|
|
FILE_INFO_READONLY(FileBothDirectoryInformation, FILE_BOTH_DIR_INFORMATION, TRUE),
|
|
FILE_INFO_EDITABLE(FileBasicInformation, FILE_BASIC_INFORMATION, FALSE),
|
|
FILE_INFO_EDITABLE(FileStandardInformation, FILE_STANDARD_INFORMATION, FALSE),
|
|
FILE_INFO_EDITABLE(FileInternalInformation, FILE_INTERNAL_INFORMATION, FALSE),
|
|
FILE_INFO_EDITABLE(FileEaInformation, FILE_EA_INFORMATION, FALSE),
|
|
FILE_INFO_EDITABLE(FileAccessInformation, FILE_ACCESS_INFORMATION, FALSE),
|
|
FILE_INFO_READONLY(FileNameInformation, FILE_NAME_INFORMATION, FALSE),
|
|
FILE_INFO_EDITABLE(FileRenameInformation, FILE_RENAME_INFORMATION, FALSE),
|
|
FILE_INFO_EDITABLE(FileLinkInformation, FILE_LINK_INFORMATION, FALSE),
|
|
FILE_INFO_READONLY(FileNamesInformation, FILE_NAMES_INFORMATION, TRUE),
|
|
FILE_INFO_EDITABLE(FileDispositionInformation, FILE_DISPOSITION_INFORMATION, FALSE),
|
|
FILE_INFO_EDITABLE(FilePositionInformation, FILE_POSITION_INFORMATION, FALSE),
|
|
FILE_INFO_READONLY(FileFullEaInformation, FILE_FULL_EA_INFORMATION, TRUE),
|
|
FILE_INFO_EDITABLE(FileModeInformation, FILE_MODE_INFORMATION, FALSE),
|
|
FILE_INFO_EDITABLE(FileAlignmentInformation, FILE_ALIGNMENT_INFORMATION, FALSE),
|
|
FILE_INFO_READONLY(FileAllInformation, FILE_ALL_INFORMATION, FALSE),
|
|
FILE_INFO_EDITABLE(FileAllocationInformation, FILE_ALLOCATION_INFORMATION, FALSE),
|
|
FILE_INFO_EDITABLE(FileEndOfFileInformation, FILE_END_OF_FILE_INFORMATION, FALSE),
|
|
FILE_INFO_READONLY(FileAlternateNameInformation, FILE_NAME_INFORMATION, FALSE),
|
|
FILE_INFO_READONLY(FileStreamInformation, FILE_STREAM_INFORMATION, TRUE),
|
|
FILE_INFO_EDITABLE(FilePipeInformation, FILE_PIPE_INFORMATION, FALSE),
|
|
FILE_INFO_EDITABLE(FilePipeLocalInformation, FILE_PIPE_LOCAL_INFORMATION, FALSE),
|
|
FILE_INFO_EDITABLE(FilePipeRemoteInformation, FILE_PIPE_REMOTE_INFORMATION, FALSE),
|
|
FILE_INFO_EDITABLE(FileMailslotQueryInformation, FILE_MAILSLOT_QUERY_INFORMATION, FALSE),
|
|
FILE_INFO_EDITABLE(FileMailslotSetInformation, FILE_MAILSLOT_SET_INFORMATION, FALSE),
|
|
FILE_INFO_EDITABLE(FileCompressionInformation, FILE_COMPRESSION_INFORMATION, FALSE),
|
|
FILE_INFO_READONLY(FileObjectIdInformation, FILE_OBJECTID_INFORMATION, FALSE),
|
|
FILE_INFO_EDITABLE(FileCompletionInformation, FILE_COMPLETION_INFORMATION, FALSE),
|
|
FILE_INFO_EDITABLE(FileMoveClusterInformation, FILE_MOVE_CLUSTER_INFORMATION, FALSE),
|
|
FILE_INFO_READONLY(FileQuotaInformation, FILE_QUOTA_INFORMATION, TRUE),
|
|
FILE_INFO_EDITABLE(FileReparsePointInformation, FILE_REPARSE_POINT_INFORMATION, FALSE),
|
|
FILE_INFO_EDITABLE(FileNetworkOpenInformation, FILE_NETWORK_OPEN_INFORMATION, FALSE),
|
|
FILE_INFO_EDITABLE(FileAttributeTagInformation, FILE_ATTRIBUTE_TAG_INFORMATION, FALSE),
|
|
FILE_INFO_EDITABLE(FileTrackingInformation, FILE_TRACKING_INFORMATION, FALSE),
|
|
FILE_INFO_READONLY(FileIdBothDirectoryInformation, FILE_ID_BOTH_DIR_INFORMATION, TRUE),
|
|
FILE_INFO_READONLY(FileIdFullDirectoryInformation, FILE_ID_FULL_DIR_INFORMATION, TRUE),
|
|
FILE_INFO_EDITABLE(FileValidDataLengthInformation, FILE_VALID_DATA_LENGTH_INFORMATION, FALSE),
|
|
FILE_INFO_EDITABLE(FileShortNameInformation, FILE_NAME_INFORMATION, FALSE),
|
|
FILE_INFO_EDITABLE(FileIoCompletionNotificationInformation, FILE_IO_COMPLETION_NOTIFICATION_INFORMATION, FALSE),
|
|
FILE_INFO_EDITABLE(FileIoStatusBlockRangeInformation, FILE_IOSTATUSBLOCK_RANGE_INFORMATION, FALSE),
|
|
FILE_INFO_EDITABLE(FileIoPriorityHintInformation, FILE_IO_PRIORITY_HINT_INFORMATION, FALSE),
|
|
FILE_INFO_EDITABLE(FileSfioReserveInformation, FILE_SFIO_RESERVE_INFORMATION, FALSE),
|
|
FILE_INFO_READONLY(FileSfioVolumeInformation, FILE_SFIO_VOLUME_INFORMATION, FALSE),
|
|
FILE_INFO_READONLY(FileHardLinkInformation, FILE_LINKS_INFORMATION, FALSE),
|
|
FILE_INFO_READONLY(FileProcessIdsUsingFileInformation, FILE_PROCESS_IDS_USING_FILE_INFORMATION, FALSE),
|
|
FILE_INFO_READONLY(FileNormalizedNameInformation, FILE_NORMALIZED_NAME_INFORMATION, FALSE),
|
|
FILE_INFO_READONLY(FileNetworkPhysicalNameInformation, FILE_NETWORK_PHYSICAL_NAME_INFORMATION, FALSE),
|
|
FILE_INFO_READONLY(FileIdGlobalTxDirectoryInformation, FILE_ID_GLOBAL_TX_DIRECTORY_INFORMATION, TRUE),
|
|
FILE_INFO_READONLY(FileIsRemoteDeviceInformation, FILE_IS_REMOTE_DEVICE_INFORMATION, FALSE),
|
|
FILE_INFO_READONLY(FileAttributeCacheInformation, FILE_ATTRIBUTE_CACHE_INFORMATION, FALSE),
|
|
FILE_INFO_READONLY(FileNumaNodeInformation, FILE_NUMA_NODE_INFORMATION, FALSE),
|
|
FILE_INFO_READONLY(FileStandardLinkInformation, FILE_STANDARD_LINK_INFORMATION, FALSE),
|
|
FILE_INFO_READONLY(FileRemoteProtocolInformation, FILE_REMOTE_PROTOCOL_INFORMATION, FALSE),
|
|
FILE_INFO_EDITABLE(FileRenameInformationBypassAccessCheck, FILE_RENAME_INFORMATION, FALSE),
|
|
FILE_INFO_EDITABLE(FileLinkInformationBypassAccessCheck, FILE_LINK_INFORMATION, FALSE),
|
|
FILE_INFO_READONLY(FileVolumeNameInformation, FILE_VOLUME_NAME_INFORMATION, FALSE),
|
|
FILE_INFO_READONLY(FileIdInformation, FILE_ID_INFORMATION, FALSE),
|
|
FILE_INFO_READONLY(FileIdExtdDirectoryInformation, FILE_ID_EXTD_DIR_INFORMATION, TRUE),
|
|
FILE_INFO_EDITABLE(FileReplaceCompletionInformation, FILE_COMPLETION_INFORMATION, FALSE),
|
|
FILE_INFO_READONLY(FileHardLinkFullIdInformation, FILE_LINK_ENTRY_FULL_ID_INFORMATION, TRUE),
|
|
FILE_INFO_READONLY(FileIdExtdBothDirectoryInformation, FILE_ID_EXTD_BOTH_DIR_INFORMATION, TRUE),
|
|
FILE_INFO_EDITABLE(FileDispositionInformationEx, FILE_DISPOSITION_INFORMATION_EX, FALSE),
|
|
FILE_INFO_EDITABLE(FileRenameInformationEx, FILE_RENAME_INFORMATION_EX, FALSE),
|
|
FILE_INFO_EDITABLE(FileRenameInformationExBypassAccessCheck,FILE_RENAME_INFORMATION_EX, FALSE),
|
|
FILE_INFO_EDITABLE(FileDesiredStorageClassInformation, FILE_DESIRED_STORAGE_CLASS_INFORMATION, FALSE),
|
|
FILE_INFO_READONLY(FileStatInformation, FILE_STAT_INFORMATION, FALSE),
|
|
FILE_INFO_EDITABLE(FileMemoryPartitionInformation, FILE_MEMORY_PARTITION_INFORMATION, FALSE),
|
|
FILE_INFO_READONLY(FileStatLxInformation, FILE_STAT_LX_INFORMATION, FALSE),
|
|
FILE_INFO_EDITABLE(FileCaseSensitiveInformation, FILE_CASE_SENSITIVE_INFORMATION, FALSE),
|
|
FILE_INFO_EDITABLE(FileLinkInformationEx, FILE_LINK_INFORMATION_EX, FALSE),
|
|
FILE_INFO_EDITABLE(FileLinkInformationExBypassAccessCheck, FILE_LINK_INFORMATION_EX, FALSE),
|
|
FILE_INFO_EDITABLE(FileStorageReserveIdInformation, FILE_SET_STORAGE_RESERVE_ID_INFORMATION, FALSE),
|
|
FILE_INFO_EDITABLE(FileCaseSensitiveInformationForceAccessCheck, FILE_CASE_SENSITIVE_INFORMATION, FALSE),
|
|
FILE_INFO_EDITABLE(FileKnownFolderInformation, FILE_KNOWN_FOLDER_INFORMATION, FALSE),
|
|
FILE_INFO_EDITABLE(FileStatBasicInformation, FILE_STAT_BASIC_INFORMATION, FALSE),
|
|
|
|
FILE_INFO_READONLY(FileId64ExtdDirectoryInformation, FILE_ID_64_EXTD_DIR_INFORMATION, TRUE),
|
|
FILE_INFO_READONLY(FileId64ExtdBothDirectoryInformation, FILE_ID_64_EXTD_BOTH_DIR_INFORMATION, TRUE),
|
|
FILE_INFO_READONLY(FileIdAllExtdDirectoryInformation, FILE_ID_ALL_EXTD_DIR_INFORMATION, TRUE),
|
|
FILE_INFO_READONLY(FileIdAllExtdBothDirectoryInformation, FILE_ID_ALL_EXTD_BOTH_DIR_INFORMATION, TRUE),
|
|
|
|
{FileMaximumInformation}
|
|
};
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Description of data structures for FS info classes
|
|
|
|
TStructMember FileFsVolumeInformationMembers[] =
|
|
{
|
|
{_T("VolumeCreationTime"), TYPE_FILETIME, sizeof(LARGE_INTEGER)},
|
|
{_T("VolumeSerialNumber"), TYPE_UINT32, sizeof(ULONG)},
|
|
{_T("VolumeLabelLength"), TYPE_UINT32, sizeof(ULONG)},
|
|
{_T("SupportsObjects"), TYPE_BOOLEAN, sizeof(WCHAR)}, // Aligned to 2
|
|
{_T("VolumeLabel"), TYPE_WNAME_L32B, FIELD_OFFSET(FILE_FS_VOLUME_INFORMATION, VolumeLabelLength)},
|
|
{NULL, TYPE_NONE, 0}
|
|
};
|
|
|
|
TStructMember FileFsLabelInformationMembers[] =
|
|
{
|
|
{_T("VolumeLabelLength"), TYPE_UINT32, sizeof(ULONG)},
|
|
{_T("VolumeLabel"), TYPE_WNAME_L32B, FIELD_OFFSET(FILE_FS_LABEL_INFORMATION, VolumeLabelLength)},
|
|
{NULL, TYPE_NONE, 0}
|
|
};
|
|
|
|
|
|
TStructMember FileFsSizeInformationMembers[] =
|
|
{
|
|
{_T("TotalAllocationUnits"), TYPE_UINT64, sizeof(LARGE_INTEGER)},
|
|
{_T("AvailableAllocationUnits"), TYPE_UINT64, sizeof(LARGE_INTEGER)},
|
|
{_T("SectorsPerAllocationUnit"), TYPE_UINT32, sizeof(ULONG)},
|
|
{_T("BytesPerSector"), TYPE_UINT32, sizeof(ULONG)},
|
|
{NULL, TYPE_NONE, 0}
|
|
};
|
|
|
|
TFlagInfo FileDeviceCharacteristicsValues[] =
|
|
{
|
|
FLAGINFO_BITV(FILE_REMOVABLE_MEDIA),
|
|
FLAGINFO_BITV(FILE_READ_ONLY_DEVICE),
|
|
FLAGINFO_BITV(FILE_FLOPPY_DISKETTE),
|
|
FLAGINFO_BITV(FILE_WRITE_ONCE_MEDIA),
|
|
FLAGINFO_BITV(FILE_REMOTE_DEVICE),
|
|
FLAGINFO_BITV(FILE_DEVICE_IS_MOUNTED),
|
|
FLAGINFO_BITV(FILE_VIRTUAL_VOLUME),
|
|
FLAGINFO_BITV(FILE_AUTOGENERATED_DEVICE_NAME),
|
|
FLAGINFO_BITV(FILE_DEVICE_SECURE_OPEN),
|
|
FLAGINFO_BITV(FILE_CHARACTERISTIC_PNP_DEVICE),
|
|
FLAGINFO_BITV(FILE_CHARACTERISTIC_TS_DEVICE),
|
|
FLAGINFO_BITV(FILE_CHARACTERISTIC_WEBDAV_DEVICE),
|
|
FLAGINFO_BITV(FILE_CHARACTERISTIC_CSV),
|
|
FLAGINFO_BITV(FILE_DEVICE_ALLOW_APPCONTAINER_TRAVERSAL),
|
|
FLAGINFO_BITV(FILE_PORTABLE_DEVICE),
|
|
FLAGINFO_BITV(FILE_REMOTE_DEVICE_VSMB),
|
|
FLAGINFO_BITV(FILE_DEVICE_REQUIRE_SECURITY_CHECK),
|
|
FLAGINFO_END()
|
|
};
|
|
|
|
TStructMember FileFsDeviceInformationMembers[] =
|
|
{
|
|
{_T("DeviceType"), TYPE_UINT32, sizeof(ULONG)},
|
|
{_T("Characteristics"), TYPE_FLAG32, sizeof(ULONG), NULL, {(TStructMember *)FileDeviceCharacteristicsValues}},
|
|
{NULL, TYPE_NONE, 0}
|
|
};
|
|
|
|
TStructMember FileFsAttributeInformationMembers[] =
|
|
{
|
|
{_T("FileSystemAttributes"), TYPE_FLAG32, sizeof(ULONG), NULL, {(TStructMember *)FileSystemAttributesValues}},
|
|
{_T("MaximumComponentNameLength"), TYPE_UINT32, sizeof(ULONG)},
|
|
{_T("FileSystemNameLength"), TYPE_UINT32, sizeof(ULONG)},
|
|
{_T("FileSystemName"), TYPE_WNAME_L32B, FIELD_OFFSET(FILE_FS_ATTRIBUTE_INFORMATION, FileSystemNameLength)},
|
|
{NULL, TYPE_NONE, 0}
|
|
};
|
|
|
|
TFlagInfo FileSystemControlFlagValues[] =
|
|
{
|
|
FLAGINFO_BITV(FILE_VC_QUOTA_TRACK),
|
|
FLAGINFO_BITV(FILE_VC_QUOTA_ENFORCE),
|
|
FLAGINFO_BITV(FILE_VC_CONTENT_INDEX_DISABLED),
|
|
FLAGINFO_BITV(FILE_VC_LOG_QUOTA_THRESHOLD),
|
|
FLAGINFO_BITV(FILE_VC_LOG_QUOTA_LIMIT),
|
|
FLAGINFO_BITV(FILE_VC_LOG_VOLUME_THRESHOLD),
|
|
FLAGINFO_BITV(FILE_VC_LOG_VOLUME_LIMIT),
|
|
FLAGINFO_BITV(FILE_VC_QUOTAS_INCOMPLETE),
|
|
FLAGINFO_BITV(FILE_VC_QUOTAS_REBUILDING),
|
|
FLAGINFO_END()
|
|
};
|
|
|
|
TStructMember FileFsControlInformationMembers[] =
|
|
{
|
|
{_T("FreeSpaceStartFiltering"), TYPE_UINT64, sizeof(LARGE_INTEGER)},
|
|
{_T("FreeSpaceThreshold"), TYPE_UINT64, sizeof(LARGE_INTEGER)},
|
|
{_T("FreeSpaceStopFiltering"), TYPE_UINT64, sizeof(LARGE_INTEGER)},
|
|
{_T("DefaultQuotaThreshold"), TYPE_UINT64, sizeof(LARGE_INTEGER)},
|
|
{_T("DefaultQuotaLimit"), TYPE_UINT64, sizeof(LARGE_INTEGER)},
|
|
{_T("FileSystemControlFlags"), TYPE_FLAG32, sizeof(ULONG), NULL, {(TStructMember *)FileSystemControlFlagValues}},
|
|
{NULL, TYPE_NONE, 0}
|
|
};
|
|
|
|
|
|
TStructMember FileFsFullSizeInformationMembers[] =
|
|
{
|
|
{_T("TotalAllocationUnits"), TYPE_UINT64, sizeof(LARGE_INTEGER)},
|
|
{_T("CallerAvailableAllocationUnits"), TYPE_UINT64, sizeof(LARGE_INTEGER)},
|
|
{_T("ActualAvailableAllocationUnits"), TYPE_UINT64, sizeof(LARGE_INTEGER)},
|
|
{_T("SectorsPerAllocationUnit"), TYPE_UINT32, sizeof(ULONG)},
|
|
{_T("BytesPerSector"), TYPE_UINT32, sizeof(ULONG)},
|
|
{NULL, TYPE_NONE, 0}
|
|
};
|
|
|
|
|
|
TStructMember FileFsObjectIdInformationMembers[] =
|
|
{
|
|
{_T("ObjectId"), TYPE_GUID, sizeof(UCHAR[16])},
|
|
{_T("ExtendedInfo"), TYPE_ARRAY8_FIXED, sizeof(UCHAR[48])},
|
|
{NULL, TYPE_NONE, 0}
|
|
};
|
|
|
|
|
|
TStructMember FileFsDriverPathInformationMembers[] =
|
|
{
|
|
{_T("DriverInPath"), TYPE_BOOLEAN, sizeof(ULONG)},
|
|
{_T("DriverNameLength"), TYPE_UINT32, sizeof(ULONG)},
|
|
{_T("DriverName"), TYPE_WNAME_L32B, FIELD_OFFSET(FILE_FS_DRIVER_PATH_INFORMATION, DriverNameLength)},
|
|
{NULL, TYPE_NONE, 0}
|
|
};
|
|
|
|
|
|
TStructMember FileFsVolumeFlagsInformationMembers[] =
|
|
{
|
|
{_T("Flags"), TYPE_UINT32, sizeof(ULONG)},
|
|
{NULL, TYPE_NONE, 0}
|
|
};
|
|
|
|
TFlagInfo FileSystemSectorFlagValues[] =
|
|
{
|
|
FLAGINFO_BITV(SSINFO_FLAGS_ALIGNED_DEVICE),
|
|
FLAGINFO_BITV(SSINFO_FLAGS_PARTITION_ALIGNED_ON_DEVICE),
|
|
FLAGINFO_BITV(SSINFO_FLAGS_NO_SEEK_PENALTY),
|
|
FLAGINFO_BITV(SSINFO_FLAGS_TRIM_ENABLED),
|
|
FLAGINFO_BITV(SSINFO_FLAGS_BYTE_ADDRESSABLE),
|
|
FLAGINFO_END()
|
|
};
|
|
|
|
TStructMember FileFsSectorSizeInformationMembers[] =
|
|
{
|
|
{_T("LogicalBytesPerSector"), TYPE_UINT32, sizeof(ULONG)},
|
|
{_T("PhysicalBytesPerSectorForAtomicity"), TYPE_UINT32, sizeof(ULONG)},
|
|
{_T("PhysicalBytesPerSectorForPerformance"), TYPE_UINT32, sizeof(ULONG)},
|
|
{_T("FileSystemEffectivePhysicalBytesPerSectorForAtomicity"), TYPE_UINT32, sizeof(ULONG)},
|
|
{_T("Flags"), TYPE_FLAG32, sizeof(ULONG), NULL, {(TStructMember *)FileSystemSectorFlagValues}},
|
|
{_T("ByteOffsetForSectorAlignment"), TYPE_UINT32, sizeof(ULONG)},
|
|
{_T("ByteOffsetForPartitionAlignment"), TYPE_UINT32, sizeof(ULONG)},
|
|
{NULL, TYPE_NONE, 0}
|
|
};
|
|
|
|
TStructMember FileFsDataCopyInformationMembers[] =
|
|
{
|
|
{_T("NumberOfCopies"), TYPE_UINT32, sizeof(ULONG)},
|
|
{NULL, TYPE_NONE, 0}
|
|
};
|
|
|
|
TStructMember FileFsMetadataSizeInformationMembers[] =
|
|
{
|
|
{_T("TotalMetadataAllocationUnits"), TYPE_UINT64, sizeof(LARGE_INTEGER)},
|
|
{_T("SectorsPerAllocationUnit"), TYPE_UINT32, sizeof(ULONG)},
|
|
{_T("BytesPerSector"), TYPE_UINT32, sizeof(ULONG)},
|
|
{NULL, TYPE_NONE, 0}
|
|
};
|
|
|
|
TStructMember FileFsFullSizeInformationExMembers[] =
|
|
{
|
|
{_T("ActualTotalAllocationUnits"), TYPE_UINT64, sizeof(LARGE_INTEGER)},
|
|
{_T("ActualAvailableAllocationUnits"), TYPE_UINT64, sizeof(LARGE_INTEGER)},
|
|
{_T("ActualPoolUnavailableAllocationUnits"), TYPE_UINT64, sizeof(LARGE_INTEGER)},
|
|
{_T("CallerTotalAllocationUnits"), TYPE_UINT64, sizeof(LARGE_INTEGER)},
|
|
{_T("CallerAvailableAllocationUnits"), TYPE_UINT64, sizeof(LARGE_INTEGER)},
|
|
{_T("CallerPoolUnavailableAllocationUnits"), TYPE_UINT64, sizeof(LARGE_INTEGER)},
|
|
{_T("UsedAllocationUnits"), TYPE_UINT64, sizeof(LARGE_INTEGER)},
|
|
{_T("TotalReservedAllocationUnits"), TYPE_UINT64, sizeof(LARGE_INTEGER)},
|
|
{_T("VolumeStorageReserveAllocationUnits"), TYPE_UINT64, sizeof(LARGE_INTEGER)},
|
|
{_T("AvailableCommittedAllocationUnits"), TYPE_UINT64, sizeof(LARGE_INTEGER)},
|
|
{_T("PoolAvailableAllocationUnits"), TYPE_UINT64, sizeof(LARGE_INTEGER)},
|
|
{_T("SectorsPerAllocationUnit"), TYPE_UINT32, sizeof(ULONG)},
|
|
{_T("BytesPerSector"), TYPE_UINT32, sizeof(ULONG)},
|
|
{NULL, TYPE_NONE, 0}
|
|
};
|
|
|
|
TInfoData FsInfoData[] =
|
|
{
|
|
FILE_INFO_EDITABLE(FileFsVolumeInformation, FILE_FS_VOLUME_INFORMATION, FALSE),
|
|
FILE_INFO_EDITABLE(FileFsLabelInformation, FILE_FS_LABEL_INFORMATION, FALSE),
|
|
FILE_INFO_EDITABLE(FileFsSizeInformation, FILE_FS_SIZE_INFORMATION, FALSE),
|
|
FILE_INFO_EDITABLE(FileFsDeviceInformation, FILE_FS_DEVICE_INFORMATION, FALSE),
|
|
FILE_INFO_EDITABLE(FileFsAttributeInformation, FILE_FS_ATTRIBUTE_INFORMATION, FALSE),
|
|
FILE_INFO_EDITABLE(FileFsControlInformation, FILE_FS_CONTROL_INFORMATION, FALSE),
|
|
FILE_INFO_EDITABLE(FileFsFullSizeInformation, FILE_FS_FULL_SIZE_INFORMATION, FALSE),
|
|
FILE_INFO_EDITABLE(FileFsObjectIdInformation, FILE_FS_OBJECTID_INFORMATION, FALSE),
|
|
FILE_INFO_EDITABLE(FileFsDriverPathInformation, FILE_FS_DRIVER_PATH_INFORMATION, FALSE),
|
|
FILE_INFO_EDITABLE(FileFsVolumeFlagsInformation, FILE_FS_VOLUME_FLAGS_INFORMATION, FALSE),
|
|
FILE_INFO_EDITABLE(FileFsSectorSizeInformation, FILE_FS_SECTOR_SIZE_INFORMATION, FALSE),
|
|
FILE_INFO_EDITABLE(FileFsDataCopyInformation, FILE_FS_DATA_COPY_INFORMATION, FALSE),
|
|
FILE_INFO_EDITABLE(FileFsMetadataSizeInformation, FILE_FS_METADATA_SIZE_INFORMATION, FALSE),
|
|
FILE_INFO_EDITABLE(FileFsFullSizeInformationEx, FILE_FS_FULL_SIZE_INFORMATION_EX, FALSE),
|
|
{FileFsMaximumInformation}
|
|
};
|
|
|
|
#define InitialFileInfo FileBasicInformation
|
|
#define InitialFsInfo FileFsVolumeInformation
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Tooltip variables
|
|
|
|
static UINT_PTR nTimerTooltip = 0;
|
|
static HANDLE hDirTarget = NULL;
|
|
static HWND hToolTip = NULL;
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Forward definitions
|
|
|
|
static int FillStructMembersChained(
|
|
HWND hTreeView,
|
|
HTREEITEM hParentItem,
|
|
TStructMember * pMembers,
|
|
LPBYTE pbData,
|
|
LPBYTE pbDataEnd
|
|
);
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Conversion functions
|
|
|
|
#define NEXT_ENTRY_OFFSET_ATRIFICIAL 0x80000000
|
|
|
|
typedef struct _CHAINED_ENTRY
|
|
{
|
|
ULONG NextEntryOffset;
|
|
} CHAINED_ENTRY, *PCHAINED_ENTRY;
|
|
|
|
static PCHAINED_ENTRY DirEntry_Find(LPBYTE PtrEntry, ULONG_PTR DataLength)
|
|
{
|
|
PCHAINED_ENTRY DirEntry = (PCHAINED_ENTRY)PtrEntry;
|
|
LPBYTE EndEntry = PtrEntry + DataLength;
|
|
|
|
while(DirEntry->NextEntryOffset != 0 && PtrEntry < EndEntry)
|
|
{
|
|
PtrEntry = PtrEntry + DirEntry->NextEntryOffset;
|
|
DirEntry = (PCHAINED_ENTRY)PtrEntry;
|
|
}
|
|
return DirEntry;
|
|
}
|
|
|
|
static void DirEntry_Mark(PCHAINED_ENTRY LastEntry, LPBYTE pbDataPtr)
|
|
{
|
|
LPBYTE pbLastEntry = (LPBYTE)LastEntry;
|
|
|
|
// At this point, the last entry's "next" offset should be zero
|
|
assert(LastEntry->NextEntryOffset == 0);
|
|
assert(pbDataPtr > pbLastEntry);
|
|
|
|
// Set the last entry's offset to the next item.
|
|
LastEntry->NextEntryOffset = NEXT_ENTRY_OFFSET_ATRIFICIAL | (ULONG)(pbDataPtr - pbLastEntry);
|
|
}
|
|
|
|
static int GetAlignedDataLength(LPBYTE pbStructPtr, LPBYTE pbData, int nTypeSize, int nAlignmentSize)
|
|
{
|
|
int nCurrentOffset = (int)(pbData - pbStructPtr);
|
|
int nAlignMask = nAlignmentSize - 1;
|
|
int nAlignedSize = (nTypeSize + nAlignMask) & ~nAlignMask;
|
|
|
|
return nAlignedSize - (nCurrentOffset & nAlignMask);
|
|
}
|
|
|
|
static LPTSTR AStringToItemText(
|
|
LPTSTR szBuffer,
|
|
LPTSTR szEndChar,
|
|
LPSTR VarString,
|
|
ULONG LengthInBytes,
|
|
BOOL bTextForEdit)
|
|
{
|
|
size_t nNameLength = LengthInBytes / sizeof(CHAR);
|
|
|
|
// Include the preceding quotas, if necessary
|
|
if(!bTextForEdit && szEndChar > szBuffer)
|
|
*szBuffer++ = _T('\"');
|
|
|
|
// Copy the string itself
|
|
for(ULONG i = 0; i < nNameLength; i++)
|
|
{
|
|
if(szEndChar > szBuffer)
|
|
*szBuffer++ = *VarString++;
|
|
}
|
|
|
|
// Close the string with quotas, if needed
|
|
if(!bTextForEdit && szEndChar > szBuffer)
|
|
*szBuffer++ = _T('\"');
|
|
|
|
*szBuffer = 0;
|
|
return szBuffer;
|
|
}
|
|
|
|
static LPTSTR WStringToItemText(
|
|
LPTSTR szBuffer,
|
|
LPTSTR szEndChar,
|
|
LPWSTR VarString,
|
|
ULONG LengthInBytes,
|
|
BOOL bTextForEdit)
|
|
{
|
|
size_t nNameLength;
|
|
|
|
// The file name can't be longer than MAX_USHORT
|
|
if(LengthInBytes > 0xFFFE)
|
|
LengthInBytes = 0xFFFE;
|
|
nNameLength = LengthInBytes / sizeof(WCHAR);
|
|
|
|
// Include the preceding quotas, if necessary
|
|
if(!bTextForEdit && szEndChar > szBuffer)
|
|
*szBuffer++ = _T('\"');
|
|
|
|
// Copy the string itself
|
|
for(size_t i = 0; i < nNameLength; i++)
|
|
{
|
|
if(szEndChar > szBuffer)
|
|
*szBuffer++ = *VarString++;
|
|
}
|
|
|
|
// Include the terminating quotation mark, if necessary
|
|
// and terminate the string with zero
|
|
if(!bTextForEdit && szEndChar > szBuffer)
|
|
*szBuffer++ = _T('\"');
|
|
*szBuffer = 0;
|
|
|
|
return szBuffer;
|
|
}
|
|
|
|
static LPTSTR CreateFullName(LPCTSTR szDirectory, LPCWSTR szPlainName, ULONG cbPlainName)
|
|
{
|
|
LPTSTR szFileName;
|
|
LPTSTR szFilePtr;
|
|
size_t cchDirectory = _tcslen(szDirectory);
|
|
size_t cchLength;
|
|
|
|
// Allocate buffer
|
|
cchLength = cchDirectory + 1 + (cbPlainName / sizeof(WCHAR)) + 1;
|
|
szFileName = szFilePtr = new TCHAR[cchLength];
|
|
if(szFileName != NULL)
|
|
{
|
|
// Do we need a backslash?
|
|
if(cchDirectory > 0)
|
|
{
|
|
// Copy the directory name
|
|
memcpy(szFilePtr, szDirectory, cchDirectory * sizeof(TCHAR));
|
|
szFilePtr += cchDirectory;
|
|
|
|
// Add backslash if needed
|
|
if(szFilePtr[-1] != _T('\\'))
|
|
*szFilePtr++ = _T('\\');
|
|
}
|
|
|
|
// Copy the plain name
|
|
memcpy(szFilePtr, szPlainName, cbPlainName);
|
|
szFilePtr[cbPlainName / sizeof(TCHAR)] = 0;
|
|
}
|
|
|
|
return szFileName;
|
|
}
|
|
|
|
static void FillComboBoxFiltered(HWND hWndCombo, TInfoData * pInfoList, LPCTSTR szFilterText)
|
|
{
|
|
TCHAR szItemText[256];
|
|
|
|
// Disable redrawing and remove all items
|
|
EnableRedraw(hWndCombo, FALSE);
|
|
|
|
// Delete all items
|
|
while(ComboBox_DeleteString(hWndCombo, 0) > 0);
|
|
|
|
// Fill the combo box
|
|
while(pInfoList->szInfoClass != NULL)
|
|
{
|
|
// Convert the string to uppercase
|
|
StringCchCopy(szItemText, _countof(szItemText), pInfoList->szInfoClass);
|
|
CharUpper(szItemText);
|
|
|
|
// If the item contains the substring, include it in the list
|
|
if(_tcsstr(szItemText, szFilterText))
|
|
ComboBox_AddString(hWndCombo, pInfoList->szInfoClass);
|
|
|
|
// Move to the next item
|
|
pInfoList++;
|
|
}
|
|
|
|
// Enable redrawing and redraw
|
|
EnableRedraw(hWndCombo);
|
|
}
|
|
/*
|
|
static int SearchItemList(TInfoData * pInfoList, LPCTSTR szEditText, int nTextLength, int * piSelStart)
|
|
{
|
|
TInfoData * pInfoItem;
|
|
|
|
// Search the list, try to find the text from the beginning of the item
|
|
for(pInfoItem = pInfoList; pInfoItem->szInfoClass != NULL; pInfoItem++)
|
|
{
|
|
// Does the begin of the item match?
|
|
if(!_tcsnicmp(pInfoItem->szInfoClass, szEditText, nTextLength))
|
|
{
|
|
*piSelStart = nTextLength;
|
|
return (int)(pInfoItem - pInfoList);
|
|
}
|
|
}
|
|
|
|
// Search the list, try to find the text with "File" prefix
|
|
for(pInfoItem = pInfoList; pInfoItem->szInfoClass != NULL; pInfoItem++)
|
|
{
|
|
LPCTSTR szItemText = pInfoItem->szInfoClass;
|
|
|
|
// Compare all words in the item text
|
|
while(szItemText[0] != 0)
|
|
{
|
|
// Skip the word
|
|
szItemText++;
|
|
while(szItemText[0] != 0 && IsCharUpper(szItemText[0]) == FALSE)
|
|
szItemText++;
|
|
|
|
// Does the begin of the word match?
|
|
if(szItemText[0] != 0 && _tcsnicmp(szItemText, szEditText, nTextLength) == 0)
|
|
{
|
|
*piSelStart = (int)(szItemText - pInfoItem->szInfoClass) + nTextLength;
|
|
return (int)(pInfoItem - pInfoList);
|
|
}
|
|
}
|
|
}
|
|
|
|
return -1;
|
|
}
|
|
*/
|
|
|
|
static NTSTATUS TextToDirHandle(LPCTSTR szText, PHANDLE phHandle)
|
|
{
|
|
OBJECT_ATTRIBUTES ObjAttr;
|
|
UNICODE_STRING FileName = {0, 0, NULL};
|
|
IO_STATUS_BLOCK IoStatus;
|
|
NTSTATUS Status;
|
|
HANDLE FileHandle = NULL;
|
|
|
|
// If we already have a directory handle, close it
|
|
if(IsHandleValid(hDirTarget))
|
|
NtClose(hDirTarget);
|
|
hDirTarget = NULL;
|
|
|
|
// Convert the file name to NT name
|
|
InitializeObjectAttributes(&ObjAttr, &FileName, OBJ_CASE_INSENSITIVE, NULL, NULL);
|
|
Status = FileNameToUnicodeString(&FileName, szText);
|
|
|
|
// Open the file/directory
|
|
if(NT_SUCCESS(Status))
|
|
{
|
|
Status = NtOpenFile(&FileHandle,
|
|
FILE_WRITE_DATA,
|
|
&ObjAttr,
|
|
&IoStatus,
|
|
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
|
|
0);
|
|
}
|
|
|
|
// Now put the handle to the target
|
|
if(NT_SUCCESS(Status))
|
|
{
|
|
hDirTarget = FileHandle;
|
|
*phHandle = FileHandle;
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
static LPTSTR FileIDToFileName(
|
|
LPCTSTR szVolumeName,
|
|
PVOID pvFileID,
|
|
ULONG cbFileID)
|
|
{
|
|
PFILE_NAME_INFORMATION pFileInfo = NULL;
|
|
OBJECT_ATTRIBUTES ObjAttr;
|
|
IO_STATUS_BLOCK IoStatus;
|
|
UNICODE_STRING DeviceName;
|
|
UNICODE_STRING FileName;
|
|
NTSTATUS Status = STATUS_SUCCESS;
|
|
HANDLE VolumeHandle = NULL;
|
|
HANDLE FileHandle = NULL;
|
|
LPTSTR szFileName = NULL;
|
|
BYTE FileInfoBuff[0x400];
|
|
|
|
// Sanity check
|
|
assert(cbFileID == sizeof(ULONGLONG));
|
|
|
|
// Prepare the native name of the volume
|
|
Status = FileNameToUnicodeString(&DeviceName, szVolumeName);
|
|
|
|
// Open the volume
|
|
if(NT_SUCCESS(Status))
|
|
{
|
|
// Make the OBJECT_ATTRIBUTES structure
|
|
InitializeObjectAttributes(&ObjAttr, &DeviceName, OBJ_CASE_INSENSITIVE, NULL, NULL);
|
|
|
|
// Now try to open the volume/directory/file
|
|
// Use FILE_READ_ATTRIBUTES as the desired access;
|
|
// this allows us to bypass sharing violations
|
|
Status = NtCreateFile(&VolumeHandle,
|
|
FILE_READ_ATTRIBUTES, //FILE_READ_DATA,
|
|
&ObjAttr,
|
|
&IoStatus,
|
|
NULL,
|
|
FILE_ATTRIBUTE_NORMAL,
|
|
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
|
|
FILE_OPEN,
|
|
0,
|
|
NULL,
|
|
0);
|
|
}
|
|
|
|
// Prepare opening the file
|
|
if(NT_SUCCESS(Status))
|
|
{
|
|
InitializeObjectAttributes(&ObjAttr, &FileName, OBJ_CASE_INSENSITIVE, VolumeHandle, NULL);
|
|
FileName.MaximumLength =
|
|
FileName.Length = (USHORT)cbFileID;
|
|
FileName.Buffer = (PWSTR)pvFileID;
|
|
Status = NtOpenFile(&FileHandle,
|
|
FILE_READ_ATTRIBUTES,
|
|
&ObjAttr,
|
|
&IoStatus,
|
|
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
|
|
FILE_OPEN_BY_FILE_ID | FILE_OPEN_REPARSE_POINT);
|
|
}
|
|
|
|
// Query the file name
|
|
if(NT_SUCCESS(Status))
|
|
{
|
|
pFileInfo = (PFILE_NAME_INFORMATION)FileInfoBuff;
|
|
memset(pFileInfo, 0, sizeof(FileInfoBuff));
|
|
Status = NtQueryInformationFile(FileHandle,
|
|
&IoStatus,
|
|
pFileInfo,
|
|
sizeof(FileInfoBuff),
|
|
FileNameInformation);
|
|
}
|
|
|
|
// Allocate the file name
|
|
if(NT_SUCCESS(Status))
|
|
{
|
|
// Copy the volume-relative file name
|
|
szFileName = new TCHAR[(pFileInfo->FileNameLength / 2) + 1];
|
|
if(szFileName != NULL)
|
|
{
|
|
memcpy(szFileName, pFileInfo->FileName, pFileInfo->FileNameLength);
|
|
szFileName[pFileInfo->FileNameLength / 2] = 0;
|
|
}
|
|
}
|
|
|
|
// Close handles
|
|
if(FileHandle != NULL)
|
|
NtClose(FileHandle);
|
|
if(VolumeHandle != NULL)
|
|
NtClose(VolumeHandle);
|
|
FreeFileNameString(&DeviceName);
|
|
return szFileName;
|
|
}
|
|
|
|
static int DataToItemText(TStructMember * pMember, LPTSTR szBuffer, size_t nMaxChars, BOOL bTextForEdit)
|
|
{
|
|
LPTSTR szEndChar = szBuffer + nMaxChars - 1;
|
|
|
|
// If there is not even space for ending zero, do nothing
|
|
if(nMaxChars == 0)
|
|
return 0;
|
|
|
|
// Insert "MemberName: " prefix
|
|
if(bTextForEdit == FALSE)
|
|
{
|
|
StringCchPrintfEx(szBuffer, (szEndChar - szBuffer), &szBuffer, NULL, 0, _T("%s: "), pMember->szMemberName);
|
|
}
|
|
|
|
// Now insert the member value
|
|
switch(pMember->nDataType)
|
|
{
|
|
case TYPE_BOOLEAN:
|
|
{
|
|
LPCTSTR szBoolean = (*(PBOOLEAN)(pMember->pbDataPtr)) ? _T("TRUE") : _T("FALSE");
|
|
|
|
StringCchCopyEx(szBuffer, (szEndChar - szBuffer), szBoolean, &szBuffer, NULL, 0);
|
|
break;
|
|
}
|
|
|
|
case TYPE_UINT8:
|
|
{
|
|
PUCHAR pucValue = (PUCHAR)pMember->pbDataPtr;
|
|
|
|
StringCchPrintfEx(szBuffer, (szEndChar - szBuffer), &szBuffer, NULL, 0, _T("0x%02lX"), *pucValue);
|
|
break;
|
|
}
|
|
|
|
case TYPE_UINT16:
|
|
{
|
|
PUSHORT pusValue = (PUSHORT)pMember->pbDataPtr;
|
|
|
|
StringCchPrintfEx(szBuffer, (szEndChar - szBuffer), &szBuffer, NULL, 0, _T("0x%04lX"), *pusValue);
|
|
break;
|
|
}
|
|
|
|
case TYPE_UINT32:
|
|
{
|
|
PULONG pulValue = (PULONG)pMember->pbDataPtr;
|
|
|
|
StringCchPrintfEx(szBuffer, (szEndChar - szBuffer), &szBuffer, NULL, 0, _T("0x%08lX"), *pulValue);
|
|
break;
|
|
}
|
|
|
|
case TYPE_UINT64:
|
|
{
|
|
PLARGE_INTEGER pliValue = (PLARGE_INTEGER)pMember->pbDataPtr;
|
|
|
|
StringCchPrintfEx(szBuffer, (szEndChar - szBuffer), &szBuffer, NULL, 0, _T("%08lX-%08lX"), pliValue->HighPart, pliValue->LowPart);
|
|
break;
|
|
}
|
|
|
|
case TYPE_FILEID128:
|
|
{
|
|
PLARGE_INTEGER pliValue = (PLARGE_INTEGER)pMember->pbDataPtr;
|
|
|
|
StringCchPrintfEx(szBuffer, (szEndChar - szBuffer), &szBuffer, NULL, 0, _T("%016I64X-%016I64X"), pliValue[1].QuadPart, pliValue[0].QuadPart);
|
|
break;
|
|
}
|
|
|
|
case TYPE_ARRAY8_FIXED:
|
|
{
|
|
LPBYTE pbData = (LPBYTE)pMember->pbDataPtr;
|
|
|
|
if(szEndChar > szBuffer)
|
|
*szBuffer++ = _T('"');
|
|
|
|
for(UINT i = 0; i < pMember->nMemberSize; i++)
|
|
{
|
|
StringCchPrintfEx(szBuffer, (szEndChar - szBuffer), &szBuffer, NULL, 0, _T("%02lX "), *pbData++);
|
|
}
|
|
|
|
if(szEndChar > szBuffer)
|
|
*szBuffer++ = _T('"');
|
|
break;
|
|
}
|
|
|
|
case TYPE_HANDLE:
|
|
case TYPE_POINTER:
|
|
{
|
|
PHANDLE phHandle = (PHANDLE)pMember->pbDataPtr;
|
|
|
|
StringCchPrintfEx(szBuffer, (szEndChar - szBuffer), &szBuffer, NULL, 0, _T("%p"), *phHandle);
|
|
break;
|
|
}
|
|
|
|
case TYPE_DIR_HANDLE:
|
|
{
|
|
PHANDLE phHandle = (PHANDLE)pMember->pbDataPtr;
|
|
|
|
if(*phHandle != NULL)
|
|
{
|
|
StringCchPrintfEx(szBuffer, (szEndChar - szBuffer), &szBuffer, NULL, 0, _T("%p"), *phHandle);
|
|
break;
|
|
}
|
|
|
|
// Display a prompt text
|
|
szBuffer += LoadString(g_hInst, IDS_ENTER_DIRECTORY_NAME, szBuffer, (int)(szEndChar - szBuffer));
|
|
break;
|
|
}
|
|
|
|
case TYPE_FLAG8:
|
|
{
|
|
PBYTE pbValue = (PBYTE)pMember->pbStructPtr;
|
|
|
|
StringCchPrintfEx(szBuffer, (szEndChar - szBuffer), &szBuffer, NULL, 0, _T("0x%02hhX"), *pbValue);
|
|
break;
|
|
}
|
|
|
|
case TYPE_FLAG16:
|
|
{
|
|
PWORD pwValue = (PWORD)pMember->pbStructPtr;
|
|
|
|
StringCchPrintfEx(szBuffer, (szEndChar - szBuffer), &szBuffer, NULL, 0, _T("0x%04hX"), *pwValue);
|
|
break;
|
|
}
|
|
|
|
case TYPE_FLAG32:
|
|
{
|
|
PULONG pulValue = (PULONG)pMember->pbStructPtr;
|
|
|
|
StringCchPrintfEx(szBuffer, (szEndChar - szBuffer), &szBuffer, NULL, 0, _T("0x%08lX"), *pulValue);
|
|
break;
|
|
}
|
|
|
|
case TYPE_FILETIME:
|
|
{
|
|
szBuffer = FileTimeToText(szBuffer,
|
|
szEndChar,
|
|
(PFILETIME)pMember->pbDataPtr,
|
|
bTextForEdit);
|
|
break;
|
|
}
|
|
|
|
case TYPE_CNAME_L8B:
|
|
{
|
|
// Use this if it's name as CHAR array, of variable length.
|
|
// The 'nMemberSize' must contain offset of 8-bit value, containing length
|
|
// of the string in bytes.
|
|
PUCHAR PtrLength = (PUCHAR)(pMember->pbStructPtr + pMember->nMemberSize);
|
|
ULONG Length = *PtrLength;
|
|
|
|
// Process the file name as non-null-terminated
|
|
// array of WCHARs with variable length
|
|
szBuffer = AStringToItemText(szBuffer,
|
|
szEndChar,
|
|
(LPSTR)pMember->pbDataPtr,
|
|
Length,
|
|
bTextForEdit);
|
|
break;
|
|
}
|
|
|
|
case TYPE_WNAME_L32B:
|
|
{
|
|
// Use this if it's name as WCHAR array, of variable length.
|
|
// The 'nMemberSize' must contain offset of 32-bit value, containing length
|
|
// of the string in bytes.
|
|
PULONG PtrLength = (PULONG)(pMember->pbStructPtr + pMember->nMemberSize);
|
|
ULONG Length = *PtrLength;
|
|
|
|
// Process the file name as non-null-terminated
|
|
// array of WCHARs with variable length
|
|
szBuffer = WStringToItemText(szBuffer,
|
|
szEndChar,
|
|
(LPWSTR)pMember->pbDataPtr,
|
|
Length,
|
|
bTextForEdit);
|
|
break;
|
|
}
|
|
|
|
case TYPE_WNAME_L32W:
|
|
{
|
|
// Use this if it's name as WCHAR array, of variable length.
|
|
// The 'nMemberSize' must contain offset of 32-bit value, containing length
|
|
// of the string in WCHARs.
|
|
PULONG PtrLength = (PULONG)(pMember->pbStructPtr + pMember->nMemberSize);
|
|
ULONG Length = *PtrLength;
|
|
|
|
// Process the file name as non-null-terminated
|
|
// array of WCHARs with variable length
|
|
szBuffer = WStringToItemText(szBuffer,
|
|
szEndChar,
|
|
(LPWSTR)pMember->pbDataPtr,
|
|
Length * sizeof(WCHAR),
|
|
bTextForEdit);
|
|
break;
|
|
}
|
|
|
|
case TYPE_VNAME_FBDI: // ShortName in FILE_BOTH_DIR_INFORMATION
|
|
{
|
|
PFILE_BOTH_DIR_INFORMATION FileInfo;
|
|
|
|
// We have to take the whole structure and get the length
|
|
// (the name doesn't have to be zero terminated)
|
|
FileInfo = (PFILE_BOTH_DIR_INFORMATION)pMember->pbStructPtr;
|
|
|
|
// Process the file name as non-null-terminated
|
|
// string with variable length
|
|
szBuffer = WStringToItemText(szBuffer,
|
|
szEndChar,
|
|
FileInfo->ShortName,
|
|
FileInfo->ShortNameLength,
|
|
bTextForEdit);
|
|
break;
|
|
}
|
|
|
|
case TYPE_VNAME_FIBD: // ShortName in FILE_ID_BOTH_DIR_INFORMATION
|
|
{
|
|
PFILE_ID_BOTH_DIR_INFORMATION FileInfo;
|
|
|
|
// We have to take the whole structure and get the length
|
|
// (the name must not be zero terminated)
|
|
FileInfo = (PFILE_ID_BOTH_DIR_INFORMATION)
|
|
(pMember->pbDataPtr - FIELD_OFFSET(FILE_ID_BOTH_DIR_INFORMATION, ShortName));
|
|
|
|
// Process the stream name as non-null-terminated string
|
|
// with variable length
|
|
szBuffer = WStringToItemText(szBuffer,
|
|
szEndChar,
|
|
FileInfo->ShortName,
|
|
FileInfo->ShortNameLength,
|
|
bTextForEdit);
|
|
break;
|
|
}
|
|
|
|
case TYPE_VNAME_FIEBD: // ShortName in FILE_ID_EXTD_BOTH_DIR_INFORMATION
|
|
{
|
|
PFILE_ID_EXTD_BOTH_DIR_INFORMATION FileInfo;
|
|
|
|
// We have to take the whole structure and get the length
|
|
// (the name must not be zero terminated)
|
|
FileInfo = (PFILE_ID_EXTD_BOTH_DIR_INFORMATION)
|
|
(pMember->pbDataPtr - FIELD_OFFSET(FILE_ID_EXTD_BOTH_DIR_INFORMATION, ShortName));
|
|
|
|
// Process the stream name as non-null-terminated string
|
|
// with variable length
|
|
szBuffer = WStringToItemText(szBuffer,
|
|
szEndChar,
|
|
FileInfo->ShortName,
|
|
FileInfo->ShortNameLength,
|
|
bTextForEdit);
|
|
break;
|
|
}
|
|
|
|
case TYPE_FILEID64: // File ID (unresolved)
|
|
{
|
|
PLARGE_INTEGER pFileId = (PLARGE_INTEGER)pMember->pbDataPtr;
|
|
|
|
StringCchPrintfEx(szBuffer, (szEndChar - szBuffer), &szBuffer, NULL, 0, _T("%08lX-%08lX"), pFileId->HighPart, pFileId->LowPart);
|
|
break;
|
|
}
|
|
|
|
case TYPE_GUID:
|
|
{
|
|
LPGUID pGuid = (LPGUID)pMember->pbDataPtr;
|
|
TCHAR szGuidText[0x40];
|
|
|
|
GuidToString(pGuid, szGuidText, _countof(szGuidText));
|
|
StringCchPrintfEx(szBuffer, (szEndChar - szBuffer), &szBuffer, NULL, 0, _T("%s"), szGuidText);
|
|
break;
|
|
}
|
|
|
|
case TYPE_SID:
|
|
{
|
|
PSID pSid = (PSID)pMember->pbDataPtr;
|
|
TCHAR szSidText[SECURITY_MAX_SID_STRING_CHARACTERS];
|
|
|
|
if(IsValidSid(pSid))
|
|
{
|
|
SidToString(pSid, szSidText, _countof(szSidText), TRUE);
|
|
}
|
|
|
|
StringCchPrintfEx(szBuffer, (szEndChar - szBuffer), &szBuffer, NULL, 0, _T("%s"), IsValidSid(pSid) ? szSidText : _T("<invalid>"));
|
|
break;
|
|
}
|
|
|
|
default:
|
|
StringCchPrintfEx(szBuffer, (szEndChar - szBuffer), &szBuffer, NULL, 0, _T("<unsupported>"));
|
|
// No break here !!
|
|
|
|
case TYPE_STRUCT:
|
|
break;
|
|
}
|
|
|
|
// Terminate the buffer with EOS
|
|
*szBuffer = 0;
|
|
return ERROR_SUCCESS;
|
|
}
|
|
|
|
static NTSTATUS ItemTextToData(TStructMember * pMember, LPTSTR szItemText)
|
|
{
|
|
// Now insert the member value
|
|
switch(pMember->nDataType)
|
|
{
|
|
case TYPE_BOOLEAN:
|
|
{
|
|
PBOOLEAN pbValue = (PBOOLEAN)pMember->pbDataPtr;
|
|
|
|
if(!_tcsicmp(szItemText, _T("TRUE")) || !_tcsicmp(szItemText, _T("1")))
|
|
{
|
|
*pbValue = TRUE;
|
|
return STATUS_SUCCESS;
|
|
}
|
|
if(!_tcsicmp(szItemText, _T("FALSE")) || !_tcsicmp(szItemText, _T("0")))
|
|
{
|
|
*pbValue = FALSE;
|
|
return STATUS_SUCCESS;
|
|
}
|
|
break;
|
|
}
|
|
|
|
case TYPE_UINT8:
|
|
{
|
|
PUCHAR pucValue = (PUCHAR)pMember->pbDataPtr;
|
|
int nValue = 0;
|
|
int nRoot = 10;
|
|
|
|
// We allow either text or binary value
|
|
if(szItemText[0] == _T('0') && toupper(szItemText[1]) == _T('X'))
|
|
{
|
|
szItemText += 2;
|
|
nRoot = 16;
|
|
}
|
|
|
|
// Convert the text value to binary data
|
|
nValue = StrToInt(szItemText, &szItemText, nRoot);
|
|
if(*szItemText != 0 || nValue > 0xFF)
|
|
return STATUS_INVALID_DATA_FORMAT;
|
|
*pucValue = (UCHAR)nValue;
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
case TYPE_UINT16:
|
|
{
|
|
PUSHORT pusValue = (PUSHORT)pMember->pbDataPtr;
|
|
int nValue = 0;
|
|
int nRoot = 10;
|
|
|
|
// We allow either text or binary value
|
|
if(szItemText[0] == _T('0') && toupper(szItemText[1]) == _T('X'))
|
|
{
|
|
szItemText += 2;
|
|
nRoot = 16;
|
|
}
|
|
|
|
// Convert the text value to binary data
|
|
nValue = StrToInt(szItemText, &szItemText, nRoot);
|
|
if(*szItemText != 0 || nValue > 0xFFFF)
|
|
return STATUS_INVALID_DATA_FORMAT;
|
|
*pusValue = (USHORT)nValue;
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
case TYPE_UINT32:
|
|
{
|
|
PULONG pulValue = (PULONG)pMember->pbDataPtr;
|
|
int nRoot = 10;
|
|
|
|
// We allow either text or binary value
|
|
if(szItemText[0] == _T('0') && toupper(szItemText[1]) == _T('X'))
|
|
{
|
|
szItemText += 2;
|
|
nRoot = 16;
|
|
}
|
|
|
|
*pulValue = (ULONG)StrToInt(szItemText, &szItemText, nRoot);
|
|
return (*szItemText == 0) ? STATUS_SUCCESS : STATUS_INVALID_DATA_FORMAT;
|
|
}
|
|
|
|
case TYPE_UINT64:
|
|
{
|
|
PLARGE_INTEGER pliValue = (PLARGE_INTEGER)pMember->pbDataPtr;
|
|
ULONG ulValue;
|
|
|
|
// There must be two hexa values separated by '-'
|
|
ulValue = (ULONG)StrToInt(szItemText, &szItemText, 16);
|
|
if(*szItemText == _T('-'))
|
|
{
|
|
pliValue->HighPart = ulValue;
|
|
pliValue->LowPart = (ULONG)StrToInt(szItemText + 1, &szItemText, 16);
|
|
}
|
|
else
|
|
{
|
|
pliValue->HighPart = 0;
|
|
pliValue->LowPart = ulValue;
|
|
}
|
|
|
|
return (*szItemText == 0) ? STATUS_SUCCESS : STATUS_INVALID_DATA_FORMAT;
|
|
}
|
|
|
|
case TYPE_FILETIME:
|
|
{
|
|
return TextToFileTime(szItemText, (PFILETIME)pMember->pbDataPtr);
|
|
}
|
|
|
|
case TYPE_DIR_HANDLE:
|
|
{
|
|
return TextToDirHandle(szItemText, (PHANDLE)pMember->pbDataPtr);
|
|
}
|
|
|
|
case TYPE_FLAG8:
|
|
case TYPE_FLAG16:
|
|
case TYPE_FLAG32:
|
|
{
|
|
int nRoot = 10;
|
|
|
|
// We allow either text or binary value
|
|
if(szItemText[0] == _T('0') && toupper(szItemText[1]) == _T('X'))
|
|
{
|
|
szItemText += 2;
|
|
nRoot = 16;
|
|
}
|
|
|
|
ULONG ulValue = (ULONG)StrToInt(szItemText, &szItemText, nRoot);
|
|
|
|
switch (pMember->nDataType)
|
|
{
|
|
case TYPE_FLAG8:
|
|
*(PBYTE)pMember->pbStructPtr = (BYTE)ulValue;
|
|
break;
|
|
|
|
case TYPE_FLAG16:
|
|
*(PWORD)pMember->pbStructPtr = (WORD)ulValue;
|
|
break;
|
|
|
|
case TYPE_FLAG32:
|
|
*(PULONG)pMember->pbStructPtr = ulValue;
|
|
break;
|
|
}
|
|
|
|
return (*szItemText == 0) ? STATUS_SUCCESS : STATUS_INVALID_DATA_FORMAT;
|
|
}
|
|
|
|
case TYPE_WNAME_L32B:
|
|
{
|
|
// Use this if it's name as WCHAR array, of variable length.
|
|
// The 'nMemberSize' must contain offset of 32-bit value, containing length
|
|
// of the string in bytes.
|
|
PULONG PtrLength = (PULONG)(pMember->pbStructPtr + pMember->nMemberSize);
|
|
ULONG Length;
|
|
|
|
// Copy the string
|
|
Length = (ULONG)(wcslen(szItemText) * sizeof(WCHAR));
|
|
memcpy(pMember->pbDataPtr, szItemText, Length);
|
|
*PtrLength = Length;
|
|
return STATUS_SUCCESS;
|
|
}
|
|
}
|
|
|
|
return STATUS_NOT_SUPPORTED;
|
|
}
|
|
|
|
static int InsertTreeItemFlags32(
|
|
HWND hTreeView,
|
|
HTREEITEM hParentItem,
|
|
TStructMember * pMember,
|
|
LPBYTE pbData,
|
|
LPBYTE pbDataEnd)
|
|
{
|
|
TStructMember * pMemberInfo;
|
|
TCHAR szItemText[128] = {0};
|
|
|
|
// Sanity check
|
|
assert((UINT)(pbDataEnd - pbData) >= pMember->nMemberSize);
|
|
UNREFERENCED_PARAMETER(pbDataEnd);
|
|
assert(pMember->pFlags != NULL);
|
|
|
|
// Allocate the data structure
|
|
pMemberInfo = new TStructMember;
|
|
if(pMemberInfo != NULL)
|
|
{
|
|
// Fill in the item data structure
|
|
pMemberInfo->szMemberName = pMember->szMemberName;
|
|
pMemberInfo->nDataType = pMember->nDataType;
|
|
pMemberInfo->nMemberSize = pMember->nMemberSize;
|
|
pMemberInfo->pbStructPtr = pbData;
|
|
pMemberInfo->pFlags = pMember->pFlags;
|
|
|
|
// Insert the tree item to the tree
|
|
if(DataToItemText(pMemberInfo, szItemText, _countof(szItemText), FALSE) == ERROR_SUCCESS)
|
|
InsertTreeItem(hTreeView, hParentItem, szItemText, pMemberInfo);
|
|
}
|
|
|
|
return pMember->nMemberSize;
|
|
}
|
|
|
|
static NTSTATUS OpenProcessAnyMethod(PHANDLE ProcessHandle, HANDLE ProcessId)
|
|
{
|
|
ULONG dwProcessId = (DWORD)(DWORD_PTR)ProcessId;
|
|
HANDLE hProcess;
|
|
|
|
// Try normal access
|
|
hProcess = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, dwProcessId);
|
|
if(hProcess != NULL)
|
|
{
|
|
ProcessHandle[0] = hProcess;
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
// Try with limited access
|
|
hProcess = OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, FALSE, dwProcessId);
|
|
if(hProcess != NULL)
|
|
{
|
|
ProcessHandle[0] = hProcess;
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
return STATUS_ACCESS_DENIED;
|
|
}
|
|
|
|
static NTSTATUS GetProcessImageFileNameByProcessId(HANDLE ProcessId, UNICODE_STRING & ImageName)
|
|
{
|
|
SYSTEM_PROCESS_ID_INFORMATION processIdInfo;
|
|
NTSTATUS Status;
|
|
HANDLE hProcess;
|
|
BYTE NameBuff[0x200] = {0};
|
|
|
|
// Method 1 (Vista+): Try to retrieve the process image file name by PID.
|
|
// This does not require an open process handle. Credit: Matthijs Lavrijsen
|
|
processIdInfo.UniqueProcessId = ProcessId;
|
|
processIdInfo.ImageName = ImageName;
|
|
Status = NtQuerySystemInformation(SystemProcessIdInformation, &processIdInfo, sizeof(processIdInfo), NULL);
|
|
if(NT_SUCCESS(Status))
|
|
{
|
|
ImageName.Length = processIdInfo.ImageName.Length;
|
|
return Status;
|
|
}
|
|
|
|
// Method 2) Use OpenProcess and query the image name
|
|
Status = OpenProcessAnyMethod(&hProcess, ProcessId);
|
|
if(NT_SUCCESS(Status))
|
|
{
|
|
// Retrieve the process information
|
|
Status = NtQueryInformationProcess(hProcess, ProcessImageFileName, NameBuff, sizeof(NameBuff), NULL);
|
|
CloseHandle(hProcess);
|
|
|
|
// If succeeded, copy the name
|
|
if(NT_SUCCESS(Status))
|
|
{
|
|
PUNICODE_STRING TempName = (PUNICODE_STRING)NameBuff;
|
|
size_t CopyLength;
|
|
|
|
// For "System" process (PID = 0x04), the function succeeds but doesn't return anything
|
|
if(TempName->Buffer && TempName->Length)
|
|
{
|
|
CopyLength = min(ImageName.MaximumLength, TempName->Length);
|
|
memcpy(ImageName.Buffer, TempName->Buffer, CopyLength);
|
|
ImageName.Length = (USHORT)CopyLength;
|
|
}
|
|
}
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
static size_t InsertTreeItemProcess(HWND hTreeView, HTREEITEM hSubItem, HANDLE ProcessId, int nIndex)
|
|
{
|
|
UNICODE_STRING ImageName;
|
|
LPCWSTR szPlainName = NULL;
|
|
LPCWSTR szFormat;
|
|
NTSTATUS Status;
|
|
WCHAR szBuffer[0x200] = {0};
|
|
ULONG dwProcessId = (DWORD)(DWORD_PTR)ProcessId;
|
|
|
|
// Initialize the UNICODE_STRING holding the file name
|
|
ImageName.MaximumLength = (USHORT)(sizeof(szBuffer) - sizeof(WCHAR));
|
|
ImageName.Length = 0;
|
|
ImageName.Buffer = szBuffer;
|
|
|
|
// Try to retrieve the process image file name
|
|
Status = GetProcessImageFileNameByProcessId(ProcessId, ImageName);
|
|
if(NT_SUCCESS(Status) && ImageName.Length)
|
|
{
|
|
ImageName.Buffer[ImageName.Length / sizeof(WCHAR)] = L'\0';
|
|
szPlainName = GetPlainName(ImageName.Buffer);
|
|
}
|
|
else if(dwProcessId == 0)
|
|
{
|
|
szPlainName = L"System Idle Process";
|
|
}
|
|
else if(dwProcessId == 4)
|
|
{
|
|
szPlainName = L"System";
|
|
}
|
|
|
|
// Construct the image name
|
|
szFormat = (szPlainName != NULL) ? _T("[0x%02X]: %u (%s)") : _T("[0x%02X]: %u (unknown)");
|
|
StringCchPrintf(szBuffer, _countof(szBuffer), szFormat, nIndex, dwProcessId, szPlainName);
|
|
InsertTreeItem(hTreeView, hSubItem, szBuffer);
|
|
return sizeof(UINT_PTR);
|
|
}
|
|
|
|
static int InsertTreeItemByDataType(
|
|
HWND hTreeView,
|
|
HTREEITEM hParentItem,
|
|
TStructMember * pMember,
|
|
PBYTE pbStructPtr,
|
|
PBYTE pbDataPtr,
|
|
PBYTE pbDataEnd)
|
|
{
|
|
TStructMember * pMemberInfo;
|
|
TCHAR szItemText[1024] = _T("");
|
|
int nBytesUsed = pMember->nMemberSize;
|
|
|
|
if(pMember->nDataType == TYPE_ARRAY8_VARIABLE)
|
|
{
|
|
UINT nTotalDataLength = (UINT)(pbDataEnd - pbDataPtr);
|
|
UINT nChunkDataLength;
|
|
|
|
// Limit the total length to 1024 bytes
|
|
nBytesUsed = nTotalDataLength;
|
|
if(nTotalDataLength > 1024)
|
|
nTotalDataLength = 1024;
|
|
|
|
// Enter multiple lines, 1 paragraph per line
|
|
while(nTotalDataLength != 0)
|
|
{
|
|
// Find out the maximum data length
|
|
nChunkDataLength = min(nTotalDataLength, 0x10);
|
|
|
|
// Allocate the data structure
|
|
pMemberInfo = new TStructMember;
|
|
if(pMemberInfo != NULL)
|
|
{
|
|
// Fill in the item data structure
|
|
pMemberInfo->szMemberName = pMember->szMemberName;
|
|
pMemberInfo->nDataType = TYPE_ARRAY8_FIXED;
|
|
pMemberInfo->nMemberSize = nChunkDataLength;
|
|
pMemberInfo->pbStructPtr = pbStructPtr;
|
|
pMemberInfo->pbDataPtr = pbDataPtr;
|
|
|
|
// Get the item text
|
|
if(DataToItemText(pMemberInfo, szItemText, _countof(szItemText), FALSE) == ERROR_SUCCESS)
|
|
InsertTreeItem(hTreeView, hParentItem, szItemText, pMemberInfo);
|
|
}
|
|
|
|
// Move the pointer
|
|
nTotalDataLength -= nChunkDataLength;
|
|
pbDataPtr += nChunkDataLength;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Allocate the data structure
|
|
pMemberInfo = new TStructMember;
|
|
if(pMemberInfo != NULL)
|
|
{
|
|
// Fill in the item data structure
|
|
pMemberInfo->szMemberName = pMember->szMemberName;
|
|
pMemberInfo->nDataType = pMember->nDataType;
|
|
pMemberInfo->nMemberSize = pMember->nMemberSize;
|
|
pMemberInfo->pbStructPtr = pbStructPtr;
|
|
pMemberInfo->pbDataPtr = pbDataPtr;
|
|
|
|
// Get the item text
|
|
if(DataToItemText(pMemberInfo, szItemText, _countof(szItemText), FALSE) == ERROR_SUCCESS)
|
|
InsertTreeItem(hTreeView, hParentItem, szItemText, pMemberInfo);
|
|
}
|
|
}
|
|
|
|
return nBytesUsed;
|
|
}
|
|
|
|
static int GetStructLength(TStructMember * pMember)
|
|
{
|
|
int nStructLength = 0;
|
|
|
|
// We don't need recursion here; structure members in structures
|
|
// have also their size present, so we just add it
|
|
for(; pMember->szMemberName != NULL; pMember++)
|
|
nStructLength += pMember->nMemberSize;
|
|
|
|
// If the structure size is greater than 4 bytes,
|
|
// we have to align it to 8-byte boundary
|
|
if(nStructLength > 0x04)
|
|
nStructLength = ALIGN_INT64(nStructLength);
|
|
|
|
return nStructLength;
|
|
}
|
|
|
|
static void EnableOrDisableButtons(HWND hDlg)
|
|
{
|
|
TFileTestData * pData = GetDialogData(hDlg);
|
|
BOOL bEnable = FALSE;
|
|
|
|
// Controls on the dialog will be enabled only if the
|
|
// handle is valid and it is a NT handle
|
|
|
|
if(IsHandleValid(pData->hFile))
|
|
bEnable = TRUE;
|
|
if(GetDlgItem(hDlg, IDC_QUERY_INFO) != NULL)
|
|
EnableDlgItems(hDlg, bEnable, IDC_QUERY_INFO, IDC_QUERY_DIR, IDC_SET_INFO, 0);
|
|
if(GetDlgItem(hDlg, IDC_QUERY_VOL_INFO) != NULL)
|
|
EnableDlgItems(hDlg, bEnable, IDC_QUERY_VOL_INFO, IDC_SET_VOL_INFO, 0);
|
|
}
|
|
|
|
static PUNICODE_STRING GetQueryDirectoryMask(HWND hDlg, UINT nID)
|
|
{
|
|
PUNICODE_STRING FileMask;
|
|
SIZE_T cbToAllocate;
|
|
SIZE_T cbFileMask;
|
|
HWND hWndChild = GetDlgItem(hDlg, nID);
|
|
int nTextLength;
|
|
|
|
// Retrieve the length of the mask
|
|
nTextLength = GetWindowTextLength(hWndChild);
|
|
cbFileMask = (nTextLength * sizeof(WCHAR));
|
|
cbToAllocate = sizeof(UNICODE_STRING) + cbFileMask + sizeof(WCHAR);
|
|
FileMask = (PUNICODE_STRING)HeapAlloc(g_hHeap, HEAP_ZERO_MEMORY, cbToAllocate);
|
|
if(FileMask != NULL)
|
|
{
|
|
// Initialize the self-relative UNICODE_STRING
|
|
FileMask->MaximumLength = (USHORT)(cbFileMask + sizeof(WCHAR));
|
|
FileMask->Length = (USHORT)(cbFileMask);
|
|
FileMask->Buffer = (LPWSTR)(FileMask + 1);
|
|
|
|
// Copy the string
|
|
GetWindowText(hWndChild, FileMask->Buffer, nTextLength + 1);
|
|
|
|
// Special case: If the text is "NULL", then a NULL UNICODE_STRING is returned
|
|
if(!RtlCompareUnicodeString(FileMask, &NullString, TRUE))
|
|
{
|
|
HeapFree(g_hHeap, 0, FileMask);
|
|
FileMask = NULL;
|
|
}
|
|
}
|
|
|
|
return FileMask;
|
|
}
|
|
|
|
static int ReloadTreeViewItems(HWND hDlg, HWND hTreeView, HTREEITEM hParentItem)
|
|
{
|
|
TStructMember * pMemberInfo;
|
|
HTREEITEM hItem = TreeView_GetNextItem(hTreeView, hParentItem, TVGN_CHILD);
|
|
TVITEM tvi;
|
|
TCHAR szItemText[1024];
|
|
|
|
// Process all items at the same level
|
|
while(hItem != NULL)
|
|
{
|
|
// Retrieve data struct associated with treeview item
|
|
pMemberInfo = (TStructMember *)TreeView_GetItemParam(hTreeView, hItem);
|
|
|
|
// If any structure associated, get its text
|
|
if(pMemberInfo != NULL)
|
|
{
|
|
// Get the item text
|
|
if(DataToItemText(pMemberInfo, szItemText, _countof(szItemText), FALSE) == ERROR_SUCCESS)
|
|
{
|
|
ZeroMemory(&tvi, sizeof(TVITEM));
|
|
tvi.mask = TVIF_TEXT;
|
|
tvi.hItem = hItem;
|
|
tvi.pszText = szItemText;
|
|
TreeView_SetItem(hTreeView, &tvi);
|
|
}
|
|
}
|
|
|
|
// If the tree view item has a subitem, we have to recursively
|
|
// reload subtree too
|
|
if(TreeView_GetNextItem(hTreeView, hItem, TVGN_CHILD) != NULL)
|
|
ReloadTreeViewItems(hDlg, hTreeView, hItem);
|
|
|
|
// And finally, move to the next item at the same level
|
|
hItem = TreeView_GetNextItem(hTreeView, hItem, TVGN_NEXT);
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
static size_t FillStructureMembers(
|
|
HWND hTreeView,
|
|
HTREEITEM hParentItem,
|
|
TStructMember * pMembers,
|
|
LPBYTE pbData,
|
|
LPBYTE pbDataEnd)
|
|
{
|
|
HTREEITEM hSubItem;
|
|
LPBYTE pbStructPtr = pbData; // Pointer to the begin of the structure
|
|
size_t nTotalLength = 0; // Length, in bytes, of the structure member
|
|
|
|
// Hack: In Windows 10, the FILE_STANDARD_INFORMATION becomes FILE_STANDARD_INFORMATION_EX
|
|
if(pMembers == FileStandardInformationMembers && g_dwWinVer >= 0x0A00)
|
|
pMembers = FileStandardInformationMembersEx;
|
|
|
|
// Parse the members and fill them
|
|
for(; pMembers->szMemberName != NULL; pMembers++)
|
|
{
|
|
size_t nDataLength = 0;
|
|
|
|
switch(pMembers->nDataType)
|
|
{
|
|
case TYPE_STRUCT:
|
|
assert(pMembers->pSubItems != NULL);
|
|
|
|
hSubItem = InsertTreeItem(hTreeView, hParentItem, pMembers->szMemberName);
|
|
nDataLength = FillStructureMembers(hTreeView,
|
|
hSubItem,
|
|
pMembers->pSubItems,
|
|
pbData,
|
|
pbDataEnd);
|
|
break;
|
|
|
|
case TYPE_CHAINED_STRUCT:
|
|
|
|
hSubItem = InsertTreeItem(hTreeView, hParentItem, pMembers->szMemberName);
|
|
nDataLength = FillStructMembersChained(hTreeView,
|
|
hSubItem,
|
|
pMembers->pSubItems,
|
|
pbData,
|
|
pbDataEnd);
|
|
break;
|
|
|
|
case TYPE_ARRAY_PROCESS:
|
|
{
|
|
// Use this if it's array of handles or INT_PTRs
|
|
// The 'nMemberSize' must contain offset of 32-bit value, containing length
|
|
// of the string in bytes.
|
|
PHANDLE HandleArray = (PHANDLE)pbData;
|
|
PULONG PtrHandleCount = (PULONG)(pbStructPtr + pMembers->nMemberSize);
|
|
|
|
// Insert the subitem
|
|
hSubItem = InsertTreeItem(hTreeView, hParentItem, pMembers->szMemberName);
|
|
|
|
// Parse the array of process ID
|
|
if(PtrHandleCount && PtrHandleCount[0])
|
|
{
|
|
for(ULONG i = 0; i < PtrHandleCount[0]; i++)
|
|
{
|
|
nDataLength += InsertTreeItemProcess(hTreeView, hSubItem, HandleArray[i], i);
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
|
|
case TYPE_FLAG8:
|
|
case TYPE_FLAG16:
|
|
case TYPE_FLAG32: // Insert the flag array
|
|
nDataLength = InsertTreeItemFlags32(hTreeView, hParentItem, pMembers, pbData, pbDataEnd);
|
|
|
|
// If there is an alignment following the data member, do a proper alignment
|
|
if(pMembers[1].nDataType == TYPE_PADDING)
|
|
{
|
|
nDataLength = GetAlignedDataLength(pbStructPtr, pbData, pMembers[0].nMemberSize, pMembers[1].nMemberSize);
|
|
pMembers++;
|
|
}
|
|
break;
|
|
|
|
default:
|
|
|
|
// Insert the data member
|
|
nDataLength = InsertTreeItemByDataType(hTreeView, hParentItem, pMembers, pbStructPtr, pbData, pbDataEnd);
|
|
|
|
// If there is an alignment following the data member, do a proper alignment
|
|
if(pMembers[1].nDataType == TYPE_PADDING)
|
|
{
|
|
nDataLength = GetAlignedDataLength(pbStructPtr, pbData, pMembers[0].nMemberSize, pMembers[1].nMemberSize);
|
|
pMembers++;
|
|
}
|
|
break;
|
|
}
|
|
|
|
// Move the data pointer and total length by the item size
|
|
nTotalLength += nDataLength;
|
|
pbData += nDataLength;
|
|
}
|
|
|
|
// If the structure size is greater than 4 bytes,
|
|
// we have to align it to 8-byte boundary
|
|
if(nTotalLength > 0x04)
|
|
nTotalLength = ALIGN_INT64(nTotalLength);
|
|
|
|
// At the end, we have to round the structure size up to 8-byte boundary
|
|
TreeView_Expand(hTreeView, hParentItem, TVE_EXPAND);
|
|
return nTotalLength;
|
|
}
|
|
|
|
// This function fills a variable length structure
|
|
// The data structure must contain "ULONG NextEntryOffset"
|
|
// as its very first member
|
|
static int FillStructMembersChained(
|
|
HWND hTreeView,
|
|
HTREEITEM hParentItem,
|
|
TStructMember * pMembers,
|
|
LPBYTE pbData,
|
|
LPBYTE pbDataEnd)
|
|
{
|
|
HTREEITEM hItem;
|
|
LPBYTE pbDataBegin = pbData;
|
|
TCHAR szItemName[128];
|
|
int nIndex = 0;
|
|
|
|
// Insert infos about the streams
|
|
while(pbData < pbDataEnd)
|
|
{
|
|
PCHAINED_ENTRY ChainedEntry = (PCHAINED_ENTRY)(pbData);
|
|
ULONG NextEntryOffset = ChainedEntry->NextEntryOffset;
|
|
|
|
// Fixup entries with artificial NextEntryOffset
|
|
if(ChainedEntry->NextEntryOffset & NEXT_ENTRY_OFFSET_ATRIFICIAL)
|
|
{
|
|
NextEntryOffset &= ~NEXT_ENTRY_OFFSET_ATRIFICIAL;
|
|
ChainedEntry->NextEntryOffset = 0;
|
|
}
|
|
|
|
StringCchPrintf(szItemName, _countof(szItemName), _T("[%u]"), nIndex++);
|
|
hItem = InsertTreeItem(hTreeView, hParentItem, szItemName, pbData);
|
|
FillStructureMembers(hTreeView, hItem, pMembers, pbData, pbDataEnd);
|
|
|
|
// If the "NextEntryOffset" is zero, we stop searching
|
|
if(NextEntryOffset == 0)
|
|
break;
|
|
pbData += NextEntryOffset;
|
|
}
|
|
|
|
// At the end, we have to round the structure size up to 8-byte boundary
|
|
// Return the total length of the stream info
|
|
TreeView_Expand(hTreeView, hParentItem, TVE_EXPAND);
|
|
return (ULONG)(pbData - pbDataBegin);
|
|
}
|
|
|
|
static size_t FillDialogWithFileInfo(HWND hDlg, TInfoData * pInfoData, int nInfoClass)
|
|
{
|
|
TFileTestData * pData = GetDialogData(hDlg);
|
|
HTREEITEM hRootItem = NULL;
|
|
LPBYTE pbNtInfoBuffEnd = pData->NtInfoData.pbData + pData->NtInfoData.cbData;
|
|
HWND hTreeView = GetDlgItem(hDlg, IDC_FILE_INFO);
|
|
HWND hComment = GetDlgItem(hDlg, IDC_COMMENT);
|
|
size_t nInputLength = 0;
|
|
BOOL bEnable = FALSE;
|
|
BOOL bShowTreeView = FALSE;
|
|
|
|
// Delete all items in the tree view
|
|
TreeView_DeleteAllItems(hTreeView);
|
|
|
|
// File infos and FS infos start from 1
|
|
assert(nInfoClass >= 1);
|
|
pInfoData = pInfoData + nInfoClass - 1;
|
|
|
|
// Fill the tree view.
|
|
// For some structures (like FILE_STREAM_INFORMATION),
|
|
// we have to do it manually, because our data struct description
|
|
// don't allow us to process the variable structs following each other
|
|
if(pInfoData->szStructName != NULL)
|
|
{
|
|
hRootItem = InsertTreeItem(hTreeView, TVI_ROOT, pInfoData->szStructName);
|
|
if(hRootItem != NULL && pInfoData->pStructMembers != NULL)
|
|
{
|
|
// Chained structures, like FILE_DIRECTORY_INFORMATION,
|
|
// require different approach.
|
|
if(pInfoData->bIsChain == FALSE)
|
|
{
|
|
nInputLength = FillStructureMembers(hTreeView,
|
|
hRootItem,
|
|
pInfoData->pStructMembers,
|
|
pData->NtInfoData.pbData,
|
|
pbNtInfoBuffEnd);
|
|
}
|
|
else
|
|
{
|
|
nInputLength = FillStructMembersChained(hTreeView,
|
|
hRootItem,
|
|
pInfoData->pStructMembers,
|
|
pData->NtInfoData.pbData,
|
|
pbNtInfoBuffEnd);
|
|
}
|
|
|
|
// Expand all subitems
|
|
bShowTreeView = TRUE;
|
|
bEnable = TRUE;
|
|
}
|
|
}
|
|
|
|
// Enable/disable input length and setinfo button
|
|
EnableDlgItems(hDlg, bEnable, IDC_INPUT_LENGTH_TITLE,
|
|
IDC_INPUT_LENGTH,
|
|
IDC_DEFAULT_LENGTH,
|
|
IDC_MAXIMUM_LENGTH,
|
|
0);
|
|
|
|
// Enable/disable the buttons
|
|
EnableOrDisableButtons(hDlg);
|
|
|
|
// Show/hide the tree view
|
|
if(bShowTreeView != IsWindowVisible(hTreeView))
|
|
{
|
|
ShowWindow(hTreeView, bShowTreeView ? SW_SHOW : SW_HIDE);
|
|
ShowWindow(hComment, bShowTreeView ? SW_HIDE : SW_SHOW);
|
|
}
|
|
|
|
return nInputLength;
|
|
}
|
|
|
|
static void FillDialogWithMasks(HWND hWndCombo)
|
|
{
|
|
ComboBox_InsertString(hWndCombo, -1, _T("NULL"));
|
|
ComboBox_InsertString(hWndCombo, -1, _T("*"));
|
|
ComboBox_InsertString(hWndCombo, -1, _T("*.*"));
|
|
ComboBox_InsertString(hWndCombo, -1, _T("*.exe"));
|
|
|
|
ComboBox_SetCurSel(hWndCombo, 0);
|
|
}
|
|
|
|
VOID CALLBACK TimerTooltipProc(HWND hDlg, UINT /* uMsg */, UINT_PTR /* idEvent */, DWORD /* dwTime */)
|
|
{
|
|
// Destroy the tooltip window
|
|
if(hToolTip != NULL)
|
|
DestroyWindow(hToolTip);
|
|
hToolTip = NULL;
|
|
|
|
// Kill the timer
|
|
if(nTimerTooltip != 0)
|
|
KillTimer(hDlg, nTimerTooltip);
|
|
nTimerTooltip = 0;
|
|
}
|
|
|
|
static int CopyItemToClipboard(HWND hDlg, TStructMember * pMemberInfo)
|
|
{
|
|
HGLOBAL hMem = NULL;
|
|
LPTSTR szClipboard = NULL;
|
|
size_t cbMemberData = 0;
|
|
DWORD dwErrCode = ERROR_CAN_NOT_COMPLETE;
|
|
|
|
// Get the binary length of the data
|
|
if(pMemberInfo->nDataType == TYPE_WNAME_L32B)
|
|
cbMemberData = *(PULONG)(pMemberInfo->pbStructPtr + pMemberInfo->nMemberSize);
|
|
|
|
// Only for known data
|
|
assert(cbMemberData != 0);
|
|
|
|
// Allocate space for clipboard
|
|
hMem = GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT, cbMemberData + 2);
|
|
if(hMem != NULL)
|
|
{
|
|
// Lock the memory
|
|
szClipboard = (LPTSTR)GlobalLock(hMem);
|
|
if(szClipboard != NULL)
|
|
{
|
|
// Copy the data to the clipboard
|
|
CopyMemory(szClipboard, pMemberInfo->pbDataPtr, cbMemberData);
|
|
GlobalUnlock(hMem);
|
|
|
|
// Open the clipboard
|
|
if(OpenClipboard(hDlg))
|
|
{
|
|
EmptyClipboard();
|
|
if(SetClipboardData(CF_UNICODETEXT, hMem))
|
|
dwErrCode = ERROR_SUCCESS;
|
|
CloseClipboard();
|
|
}
|
|
}
|
|
|
|
GlobalFree(hMem);
|
|
}
|
|
|
|
return dwErrCode;
|
|
}
|
|
|
|
static bool FileIdHasFileName(HWND hTreeView, HTREEITEM hItem)
|
|
{
|
|
TVITEM tvi;
|
|
bool bResult = false;
|
|
|
|
// Allocate buffer for a maximum possible file name length
|
|
tvi.mask = TVIF_TEXT;
|
|
tvi.hItem = hItem;
|
|
tvi.pszText = new TCHAR[MAX_NT_PATH + 1];
|
|
tvi.cchTextMax = MAX_NT_PATH;
|
|
if(tvi.pszText != NULL)
|
|
{
|
|
// Load the tree view text
|
|
TreeView_GetItem(hTreeView, &tvi);
|
|
if(tvi.cchTextMax != 0)
|
|
{
|
|
// If there is a file name tail (" (\"), then we have file name there
|
|
if(_tcschr(tvi.pszText, _T('(')))
|
|
bResult = true;
|
|
}
|
|
|
|
delete [] tvi.pszText;
|
|
}
|
|
|
|
return bResult;
|
|
}
|
|
|
|
static TInfoData * GetSelectedInfoClass(HWND hDlg, UINT nIDCombo, TInfoData * pInfoData)
|
|
{
|
|
TCHAR szSelection[MAX_PATH];
|
|
HWND hWndCombo = GetDlgItem(hDlg, nIDCombo);
|
|
int nSelection = ComboBox_GetCurSel(hWndCombo);
|
|
|
|
// If there's an active selection,
|
|
// we need to find the proper item by the string
|
|
if(nSelection != CB_ERR)
|
|
{
|
|
// Retrieve the actually selected item
|
|
if(ComboBox_GetLBText(hWndCombo, nSelection, szSelection) > 0)
|
|
{
|
|
// Find the proper info class
|
|
for(int i = 0; pInfoData[i].szInfoClass != NULL; i++)
|
|
{
|
|
if(!_tcsicmp(pInfoData[i].szInfoClass, szSelection))
|
|
{
|
|
return pInfoData + i;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Message handlers
|
|
|
|
static TAnchors * pAnchors1 = NULL; // For NtFileInfo
|
|
static TAnchors * pAnchors2 = NULL; // For NtVolInfo
|
|
|
|
static int OnInitDialog(HWND hDlg, LPARAM lParam)
|
|
{
|
|
TFileTestData * pData;
|
|
PROPSHEETPAGE * pPage = (PROPSHEETPAGE *)lParam;
|
|
TAnchors * pAnchors = NULL;
|
|
HWND hWndChild;
|
|
|
|
// Allocate the buffer for file information class.
|
|
// Hopefully the struct size will never exceed 32 KB
|
|
pData = (TFileTestData *)pPage->lParam;
|
|
|
|
// Initialize the dialog
|
|
SetDialogData(hDlg, pPage->lParam);
|
|
hDirTarget = NULL;
|
|
|
|
// Configure dialog resizing
|
|
if(pData->bEnableResizing)
|
|
{
|
|
if(GetDlgItem(hDlg, IDC_QUERY_INFO) != NULL)
|
|
{
|
|
pAnchors1 = new TAnchors(hDlg);
|
|
pAnchors = pAnchors1;
|
|
}
|
|
|
|
if(GetDlgItem(hDlg, IDC_QUERY_VOL_INFO) != NULL)
|
|
{
|
|
pAnchors2 = new TAnchors(hDlg);
|
|
pAnchors = pAnchors2;
|
|
}
|
|
|
|
pAnchors->AddAnchor(hDlg, IDC_FILE_INFO_CLASS_TITLE, akLeft | akTop | akRight);
|
|
pAnchors->AddAnchor(hDlg, IDC_FILE_INFO_CLASS, akLeft | akTop | akRight);
|
|
pAnchors->AddAnchor(hDlg, IDC_VOL_INFO_CLASS_TITLE, akLeft | akTop | akRight);
|
|
pAnchors->AddAnchor(hDlg, IDC_VOL_INFO_CLASS, akLeft | akTop | akRight);
|
|
// pAnchors->AddAnchor(hDlg, IDC_SEARCH_MASK_TITLE, akLeft | akTop);
|
|
// pAnchors->AddAnchor(hDlg, IDC_SEARCH_MASK, akLeft | akTop);
|
|
pAnchors->AddAnchor(hDlg, IDC_INPUT_LENGTH_TITLE, akLeft | akTop | akRight);
|
|
pAnchors->AddAnchor(hDlg, IDC_INPUT_LENGTH, akLeft | akTop | akRight);
|
|
pAnchors->AddAnchor(hDlg, IDC_DEFAULT_LENGTH, akTop | akRight);
|
|
pAnchors->AddAnchor(hDlg, IDC_MAXIMUM_LENGTH, akTop | akRight);
|
|
pAnchors->AddAnchor(hDlg, IDC_COMMENT, akAll);
|
|
pAnchors->AddAnchor(hDlg, IDC_FILE_INFO, akAll);
|
|
pAnchors->AddAnchor(hDlg, IDC_QUERY_INFO, akLeft | akBottom);
|
|
pAnchors->AddAnchor(hDlg, IDC_QUERY_DIR, akLeftCenter | akBottom);
|
|
pAnchors->AddAnchor(hDlg, IDC_SET_INFO, akRight | akBottom);
|
|
pAnchors->AddAnchor(hDlg, IDC_QUERY_VOL_INFO, akLeft | akBottom);
|
|
pAnchors->AddAnchor(hDlg, IDC_SET_VOL_INFO, akRight | akBottom);
|
|
pAnchors->AddAnchor(hDlg, IDC_RESULT_FRAME, akLeft | akRight | akBottom);
|
|
pAnchors->AddAnchor(hDlg, IDC_ERROR_CODE_TITLE, akLeft | akBottom);
|
|
pAnchors->AddAnchor(hDlg, IDC_ERROR_CODE, akLeft | akRight | akBottom);
|
|
pAnchors->AddAnchor(hDlg, IDC_INFORMATION_TITLE, akLeft | akBottom);
|
|
pAnchors->AddAnchor(hDlg, IDC_INFORMATION, akLeft | akRight | akBottom);
|
|
}
|
|
|
|
// Allocate default size for the FileInfo.
|
|
pData->NtInfoData.SetLength(INITIAL_FILEINFO_BUFFER_SIZE);
|
|
|
|
// Fill the combo box with names of file information classes
|
|
hWndChild = GetDlgItem(hDlg, IDC_FILE_INFO_CLASS);
|
|
if(hWndChild != NULL)
|
|
{
|
|
// Fill all info classes for NtSetInformationFile
|
|
FillComboBoxFiltered(hWndChild, FileInfoData, _T(""));
|
|
ComboBox_SetCurSel(hWndChild, (int)InitialFileInfo - 1);
|
|
SetFocus(hWndChild);
|
|
|
|
// Initialize tree view with structure for current
|
|
// file information class
|
|
FillDialogWithFileInfo(hDlg, FileInfoData, (int)InitialFileInfo);
|
|
}
|
|
|
|
// Fill the combo box with names of volume information classes
|
|
hWndChild = GetDlgItem(hDlg, IDC_VOL_INFO_CLASS);
|
|
if(hWndChild != NULL)
|
|
{
|
|
// Fill all info classes for NtSetVolumeInformationFile
|
|
FillComboBoxFiltered(hWndChild, FsInfoData, _T(""));
|
|
ComboBox_SetCurSel(hWndChild, (int)InitialFsInfo - 1);
|
|
SetFocus(hWndChild);
|
|
|
|
// Initialize tree view with structure for current
|
|
// file information class
|
|
FillDialogWithFileInfo(hDlg, FsInfoData, (int)InitialFsInfo);
|
|
}
|
|
|
|
// Configure the search mask edit box
|
|
hWndChild = GetDlgItem(hDlg, IDC_SEARCH_MASK);
|
|
if(hWndChild != NULL)
|
|
FillDialogWithMasks(hWndChild);
|
|
|
|
// Initialize the in/out data length
|
|
Hex2DlgText32(hDlg, IDC_INPUT_LENGTH, (DWORD)(pData->NtInfoData.cbData));
|
|
|
|
// Configure the buttons
|
|
EnableOrDisableButtons(hDlg);
|
|
return TRUE;
|
|
}
|
|
|
|
// Posted when the item label has been edited.
|
|
// We will fix the tree item to contain "Name: Value" text
|
|
static int OnReloadItems(HWND hDlg, HWND hTreeView, HTREEITEM hTreeItem)
|
|
{
|
|
// If the treeview edit process has not been completed yet,
|
|
// post the processing again
|
|
if(TreeView_GetEditControl(hTreeView) != NULL)
|
|
{
|
|
PostMessage(hDlg, WM_RELOADITEMS, (WPARAM)hTreeView, (LPARAM)hTreeItem);
|
|
return TRUE;
|
|
}
|
|
|
|
ReloadTreeViewItems(hDlg, hTreeView, hTreeItem);
|
|
return TRUE;
|
|
}
|
|
|
|
static int OnShowDateFormats(HWND hDlg, HWND hTreeItem, HTREEITEM hItem)
|
|
{
|
|
TOOLINFO ti;
|
|
LPTSTR szText;
|
|
TCHAR szDateFormatPrefix[120];
|
|
TCHAR szTimeFormatPrefix[120];
|
|
TCHAR szTitle[120];
|
|
POINT pt;
|
|
RECT rect;
|
|
int nMaxChars = 0x1000;
|
|
|
|
// Get the position of the treeview item
|
|
TreeView_GetItemRect(hTreeItem, hItem, &rect, TRUE);
|
|
pt.x = rect.left + (rect.right - rect.left) / 2;
|
|
pt.y = rect.top + (rect.bottom - rect.top) / 2;
|
|
ClientToScreen(hTreeItem, &pt);
|
|
|
|
// Allocate text for error
|
|
szText = new TCHAR[nMaxChars + 1];
|
|
if(szText == NULL)
|
|
return TRUE;
|
|
|
|
// Prepare the text for the tooltip
|
|
LoadString(g_hInst, IDS_BAD_DATETIME_FORMAT, szTitle, _countof(szTitle));
|
|
LoadString(g_hInst, IDS_DATE_FORMAT_PREFIX, szDateFormatPrefix, _countof(szDateFormatPrefix));
|
|
LoadString(g_hInst, IDS_TIME_FORMAT_PREFIX, szTimeFormatPrefix, _countof(szTimeFormatPrefix));
|
|
GetSupportedDateTimeFormats(szDateFormatPrefix, szTimeFormatPrefix, szText, nMaxChars);
|
|
|
|
// Create the additional tooltip window
|
|
if(hToolTip == NULL)
|
|
{
|
|
hToolTip = CreateWindowEx(WS_EX_TOPMOST,
|
|
TOOLTIPS_CLASS,
|
|
NULL,
|
|
WS_POPUP | TTS_NOPREFIX | TTS_ALWAYSTIP | TTS_BALLOON | TTS_CLOSE,
|
|
CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
|
|
hDlg,
|
|
NULL,
|
|
g_hInst,
|
|
NULL);
|
|
}
|
|
|
|
if(hToolTip != NULL)
|
|
{
|
|
// Set the one (and only one) tooltip window for the list view
|
|
ZeroMemory(&ti, sizeof(TOOLINFO));
|
|
ti.cbSize = sizeof(TOOLINFO);
|
|
ti.uFlags = TTF_TRACK | TTF_TRANSPARENT | TTF_IDISHWND;
|
|
ti.hinst = g_hInst;
|
|
ti.lpszText = szText;
|
|
ti.uId = (UINT_PTR)hTreeItem;
|
|
SendMessage(hToolTip, TTM_ADDTOOL, 0, (LPARAM)&ti);
|
|
|
|
// Set the icon and title
|
|
SendMessage(hToolTip, TTM_SETTITLE, TTI_INFO, (LPARAM)szTitle);
|
|
|
|
// Force the tooltip to be multi-line by specifying max width
|
|
GetClientRect(hDlg, &rect);
|
|
SendMessage(hToolTip, TTM_SETMAXTIPWIDTH, 0, (LPARAM)(rect.right - rect.left));
|
|
|
|
// Set the tooltip position
|
|
SendMessage(hToolTip, TTM_TRACKPOSITION, 0, MAKELONG(pt.x, pt.y));
|
|
|
|
// Show the tooltip
|
|
SendMessage(hToolTip, TTM_TRACKACTIVATE, TRUE, (LPARAM)&ti);
|
|
|
|
// Set the tooltip timer
|
|
nTimerTooltip = SetTimer(hDlg, WM_TIMER_TOOLTIP, 10000, TimerTooltipProc);
|
|
}
|
|
|
|
// Free buffers and exit
|
|
if(szText != NULL)
|
|
delete [] szText;
|
|
return TRUE;
|
|
}
|
|
|
|
static int OnSetActive(HWND hDlg)
|
|
{
|
|
EnableOrDisableButtons(hDlg);
|
|
return TRUE;
|
|
}
|
|
|
|
static int OnBeginLabelEdit(HWND hDlg, NMTVDISPINFO * pTVDispInfo)
|
|
{
|
|
TStructMember * pMemberInfo = (TStructMember *)pTVDispInfo->item.lParam;
|
|
TInfoData * pInfoData;
|
|
NTSTATUS CantEditStatus = STATUS_CANNOT_EDIT_THIS;
|
|
TCHAR szItemText[1024] = _T("");
|
|
HWND hTreeView = pTVDispInfo->hdr.hwndFrom;
|
|
HWND hEdit;
|
|
BOOL bStartEditing = FALSE;
|
|
bool bCopyToClipboard = false;
|
|
bool bEditable = true;
|
|
|
|
// If there is a tooltip active, destroy it
|
|
TimerTooltipProc(hDlg, 0, 0, 0);
|
|
|
|
// Verify if the selected file info class is editable
|
|
pInfoData = GetSelectedInfoClass(hDlg, IDC_FILE_INFO_CLASS, FileInfoData);
|
|
if(pInfoData != NULL)
|
|
{
|
|
if(pInfoData->bIsChain == TRUE || pInfoData->bIsEditable == FALSE)
|
|
bEditable = false;
|
|
if(pMemberInfo != NULL && pMemberInfo->nDataType == TYPE_WNAME_L32B)
|
|
bCopyToClipboard = true;
|
|
}
|
|
|
|
// Verify if the selected FS info class is editable
|
|
pInfoData = GetSelectedInfoClass(hDlg, IDC_VOL_INFO_CLASS, FsInfoData);
|
|
if(pInfoData != NULL)
|
|
{
|
|
if(pInfoData->bIsChain == TRUE || pInfoData->bIsEditable == FALSE)
|
|
bEditable = false;
|
|
}
|
|
|
|
// If not editable, show message
|
|
if(bEditable == false)
|
|
{
|
|
if(bCopyToClipboard)
|
|
{
|
|
CopyItemToClipboard(hDlg, pMemberInfo);
|
|
CantEditStatus = STATUS_COPIED_TO_CLIPBOARD;
|
|
}
|
|
|
|
SetResultInfo(hDlg, RSI_NTSTATUS | RSI_NOINFO, CantEditStatus);
|
|
SetWindowLongPtr(hDlg, DWLP_MSGRESULT, TRUE);
|
|
return TRUE;
|
|
}
|
|
|
|
// If the item has an associated struct member, allow editing
|
|
if(pMemberInfo != NULL)
|
|
{
|
|
// Get the edit control which will be shown
|
|
hEdit = TreeView_GetEditControl(hTreeView);
|
|
if(hEdit != NULL)
|
|
{
|
|
// Get the item text
|
|
if(DataToItemText(pMemberInfo, szItemText, _countof(szItemText), TRUE) == ERROR_SUCCESS)
|
|
{
|
|
SetWindowText(hEdit, szItemText);
|
|
bStartEditing = TRUE;
|
|
}
|
|
}
|
|
}
|
|
|
|
// If we start editing something, make sure that Esc key will not
|
|
// cancel the entire FileTest
|
|
DisableCloseDialog(hDlg, bStartEditing);
|
|
|
|
// Store the result info the dialog's private variables
|
|
SetWindowLongPtr(hDlg, DWLP_MSGRESULT, bStartEditing ? FALSE : TRUE);
|
|
return TRUE;
|
|
}
|
|
|
|
static int OnEndLabelEdit(HWND hDlg, NMTVDISPINFO * pTVDispInfo)
|
|
{
|
|
TStructMember * pMemberInfo = (TStructMember *)pTVDispInfo->item.lParam;
|
|
NTSTATUS Status;
|
|
HWND hTreeView = pTVDispInfo->hdr.hwndFrom;
|
|
BOOL bAcceptChanges = FALSE;
|
|
|
|
// If the item has an associated member, analyze the result text
|
|
if(pMemberInfo != NULL && pTVDispInfo->item.pszText != NULL)
|
|
{
|
|
// Try to convert the text to appropriate data item
|
|
Status = ItemTextToData(pMemberInfo, pTVDispInfo->item.pszText);
|
|
if(NT_SUCCESS(Status))
|
|
{
|
|
HTREEITEM hParentItem;
|
|
|
|
// We have to reload all items at the same level, because
|
|
// the ItemTextToData might have changed more than one item data
|
|
// (Example: variable length strings editation change also the length)
|
|
hParentItem = TreeView_GetNextItem(hTreeView, pTVDispInfo->item.hItem, TVGN_PARENT);
|
|
PostMessage(hDlg, WM_RELOADITEMS, (WPARAM)hTreeView, (LPARAM)hParentItem);
|
|
bAcceptChanges = TRUE;
|
|
}
|
|
else
|
|
{
|
|
// If the user failed to enter proper date/time, show him the possible options
|
|
if(pMemberInfo->nDataType == TYPE_FILETIME)
|
|
PostMessage(hDlg, WM_SHOW_DATE_FORMATS, (WPARAM)hTreeView, (LPARAM)pTVDispInfo->item.hItem);
|
|
|
|
// We should warn the user about that the item
|
|
// has invalid format for its data type
|
|
SetResultInfo(hDlg, RSI_NTSTATUS | RSI_NOINFO, Status);
|
|
}
|
|
}
|
|
|
|
// Enable the exit button
|
|
DisableCloseDialog(hDlg, FALSE);
|
|
SetWindowLongPtr(hDlg, DWLP_MSGRESULT, bAcceptChanges);
|
|
return TRUE;
|
|
}
|
|
|
|
static int OnDoubleClick(HWND hDlg, LPNMHDR pNMHDR)
|
|
{
|
|
TStructMember * pMemberInfo;
|
|
TFileTestData * pData = GetDialogData(hDlg);
|
|
PLARGE_INTEGER pliValue;
|
|
TInfoData * pInfoData;
|
|
HTREEITEM hParentItem;
|
|
HTREEITEM hItem;
|
|
LPCTSTR szFormat = _T("%s: %08X-%08X (%s)");
|
|
LPTSTR szFileName = NULL;
|
|
LPTSTR szItemText = NULL;
|
|
TVITEM tvi;
|
|
size_t nLength;
|
|
HWND hTreeView;
|
|
|
|
// Only accept doubleclicks on IDC_FILE_INFO
|
|
if(pNMHDR->idFrom != IDC_FILE_INFO)
|
|
return TRUE;
|
|
hTreeView = GetDlgItem(hDlg, (int)pNMHDR->idFrom);
|
|
|
|
// Retrieve the selected item
|
|
hItem = TreeView_GetSelection(hTreeView);
|
|
if(hItem == NULL)
|
|
return TRUE;
|
|
|
|
// Retrieve the item's data
|
|
pMemberInfo = (TStructMember *)TreeView_GetItemParam(hTreeView, hItem);
|
|
if(pMemberInfo == NULL)
|
|
return TRUE;
|
|
|
|
// Doubleclick on a file ID appends a file name after it
|
|
if(pMemberInfo->nDataType == TYPE_FILEID64)
|
|
{
|
|
// If the file name is not there yet, query the file name
|
|
if(FileIdHasFileName(hTreeView, hItem) == false)
|
|
{
|
|
szFileName = FileIDToFileName(pData->szFileName1, pMemberInfo->pbDataPtr, pMemberInfo->nMemberSize);
|
|
if(szFileName != NULL)
|
|
{
|
|
nLength = _tcslen(pMemberInfo->szMemberName) + _tcslen(szFormat) + 16 + _tcslen(szFileName);
|
|
szItemText = new TCHAR[nLength];
|
|
if(szItemText != NULL)
|
|
{
|
|
// Format the item text
|
|
pliValue = (PLARGE_INTEGER)pMemberInfo->pbDataPtr;
|
|
StringCchPrintf(szItemText, nLength,
|
|
szFormat,
|
|
pMemberInfo->szMemberName,
|
|
pliValue->HighPart,
|
|
pliValue->LowPart,
|
|
szFileName);
|
|
|
|
// Apply the item text to the tree view
|
|
ZeroMemory(&tvi, sizeof(TVITEM));
|
|
tvi.mask = TVIF_TEXT;
|
|
tvi.hItem = hItem;
|
|
tvi.pszText = szItemText;
|
|
TreeView_SetItem(hTreeView, &tvi);
|
|
delete [] szItemText;
|
|
}
|
|
|
|
delete [] szFileName;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
ULONGLONG FileId = *(PULONGLONG)pMemberInfo->pbDataPtr;
|
|
TCHAR szFileId[MAX_FILEID_PATH];
|
|
|
|
FileIDToString(pData, FileId, szFileId);
|
|
NtUseFileId(hDlg, szFileId);
|
|
}
|
|
}
|
|
|
|
// Doubleclick on a subdirectory or stream name
|
|
// creates a full path and switches to "NtCreate"
|
|
if(pMemberInfo->nDataType == TYPE_WNAME_L32B)
|
|
{
|
|
HWND hWndParent = GetParent(hDlg);
|
|
HWND hTabCtrl = GetDlgItem(hWndParent, IDC_TAB);
|
|
ULONG FileNameLength = *(PULONG)(pMemberInfo->pbStructPtr + pMemberInfo->nMemberSize);
|
|
|
|
szFileName = CreateFullName(pData->szFileName1, (LPWSTR)pMemberInfo->pbDataPtr, FileNameLength);
|
|
if(szFileName != NULL)
|
|
{
|
|
StringCchCopy(pData->szFileName1, MAX_NT_PATH, szFileName);
|
|
TabCtrl_SelectPageByID(hTabCtrl, MAKEINTRESOURCE(IDD_PAGE02_NTCREATE));
|
|
delete [] szFileName;
|
|
}
|
|
}
|
|
|
|
// Doubleclick on TYPE_FLAG* opens a dialog with flags
|
|
if(pMemberInfo->nDataType == TYPE_FLAG8 || pMemberInfo->nDataType == TYPE_FLAG16 || pMemberInfo->nDataType == TYPE_FLAG32)
|
|
{
|
|
DWORD Flags;
|
|
|
|
switch (pMemberInfo->nDataType)
|
|
{
|
|
case TYPE_FLAG8:
|
|
Flags = *(PBYTE)pMemberInfo->pbStructPtr;
|
|
break;
|
|
|
|
case TYPE_FLAG16:
|
|
Flags = *(PWORD)pMemberInfo->pbStructPtr;
|
|
break;
|
|
|
|
case TYPE_FLAG32:
|
|
Flags = *(PDWORD)pMemberInfo->pbStructPtr;
|
|
break;
|
|
}
|
|
|
|
if(FlagsDialog(hDlg, IDS_ENTER_FLAGS, pMemberInfo->pFlags, Flags))
|
|
{
|
|
// Only change the item if editable
|
|
pInfoData = GetSelectedInfoClass(hDlg, IDC_FILE_INFO_CLASS, FileInfoData);
|
|
if(pInfoData != NULL && pInfoData->bIsEditable)
|
|
{
|
|
switch (pMemberInfo->nDataType)
|
|
{
|
|
case TYPE_FLAG8:
|
|
*(PBYTE)pMemberInfo->pbStructPtr = (BYTE)Flags;
|
|
break;
|
|
|
|
case TYPE_FLAG16:
|
|
*(PWORD)pMemberInfo->pbStructPtr = (WORD)Flags;
|
|
break;
|
|
|
|
case TYPE_FLAG32:
|
|
*(PDWORD)pMemberInfo->pbStructPtr = Flags;
|
|
break;
|
|
}
|
|
|
|
hParentItem = TreeView_GetNextItem(hTreeView, hItem, TVGN_PARENT);
|
|
PostMessage(hDlg, WM_RELOADITEMS, (WPARAM)hTreeView, (LPARAM)hParentItem);
|
|
}
|
|
}
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
//
|
|
// Provides some extension to the default combo box search
|
|
//
|
|
// When the user types something, the combo box's drop list
|
|
// is filtered. Only those items that are in the list are included
|
|
//
|
|
// If the user types "Stand", then only these items are displayed:
|
|
//
|
|
// "FileStandardInformation"
|
|
// "FileStandardLinkInformation"
|
|
//
|
|
static int OnComboBoxEditUpdate(HWND hDlg, UINT nID, TInfoData * pInfoData)
|
|
{
|
|
TCHAR szEditText[MAX_PATH+1];
|
|
HWND hWndCombo = GetDlgItem(hDlg, nID);
|
|
|
|
if(!ComboBox_GetDroppedState(hWndCombo))
|
|
ComboBox_ShowDropdown(hWndCombo, TRUE);
|
|
|
|
// Get the text from the combo box
|
|
GetWindowText(hWndCombo, szEditText, MAX_PATH);
|
|
|
|
// Reset the combo box to only contain items with that substring
|
|
CharUpper(szEditText);
|
|
FillComboBoxFiltered(hWndCombo, pInfoData, szEditText);
|
|
|
|
// The text might have been changed by the text filling
|
|
return TRUE;
|
|
}
|
|
|
|
static int OnComboBoxItemSelected(HWND hDlg, UINT nID, TInfoData * pInfoData)
|
|
{
|
|
TFileTestData * pData = GetDialogData(hDlg);
|
|
|
|
// If there's an active selection, fill the dialog
|
|
pInfoData = GetSelectedInfoClass(hDlg, nID, pInfoData);
|
|
if(pInfoData != NULL)
|
|
{
|
|
ZeroMemory(pData->NtInfoData.pbData, pData->NtInfoData.cbData);
|
|
FillDialogWithFileInfo(hDlg, pInfoData, 1);
|
|
Hex2DlgText32(hDlg, IDC_INPUT_LENGTH, (DWORD)(pData->NtInfoData.cbDataMax));
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
static int OnDefaultLengthClick(HWND hDlg)
|
|
{
|
|
TFileTestData * pData = GetDialogData(hDlg);
|
|
TInfoData * pInfoData;
|
|
UINT nDataLength = 0;
|
|
|
|
// Default length for file info class
|
|
pInfoData = GetSelectedInfoClass(hDlg, IDC_FILE_INFO_CLASS, FileInfoData);
|
|
if(pInfoData != NULL)
|
|
nDataLength = GetStructLength(pInfoData->pStructMembers);
|
|
|
|
// Default length for FS info class
|
|
pInfoData = GetSelectedInfoClass(hDlg, IDC_VOL_INFO_CLASS, FsInfoData);
|
|
if(pInfoData != NULL)
|
|
nDataLength = GetStructLength(pInfoData->pStructMembers);
|
|
|
|
pData->NtInfoData.SetLength(nDataLength);
|
|
Hex2DlgText32(hDlg, IDC_INPUT_LENGTH, nDataLength);
|
|
return TRUE;
|
|
}
|
|
|
|
static int OnMaximumLengthClick(HWND hDlg)
|
|
{
|
|
TFileTestData * pData = GetDialogData(hDlg);
|
|
|
|
pData->NtInfoData.SetLength(pData->NtInfoData.cbDataMax);
|
|
Hex2DlgText32(hDlg, IDC_INPUT_LENGTH, (DWORD)(pData->NtInfoData.cbDataMax));
|
|
return TRUE;
|
|
}
|
|
|
|
static int OnQueryInfoClick(HWND hDlg)
|
|
{
|
|
FILE_INFORMATION_CLASS FileInfoClass;
|
|
TFileTestData * pData = GetDialogData(hDlg);
|
|
IO_STATUS_BLOCK IoStatus = {0};
|
|
TInfoData * pInfoData;
|
|
NTSTATUS Status = STATUS_SUCCESS;
|
|
ULONG Length = 0;
|
|
|
|
// Test if the handle is an NT file handle and get the file info class
|
|
if(IsHandleValid(pData->hFile) == FALSE)
|
|
return FALSE;
|
|
|
|
// Get the selected info data
|
|
pInfoData = GetSelectedInfoClass(hDlg, IDC_FILE_INFO_CLASS, FileInfoData);
|
|
if(pInfoData == NULL)
|
|
return FALSE;
|
|
|
|
// Get the file information class
|
|
FileInfoClass = (FILE_INFORMATION_CLASS)(pInfoData->InfoClass);
|
|
|
|
// Get the input length
|
|
DlgText2Hex32(hDlg, IDC_INPUT_LENGTH, &Length);
|
|
|
|
// If the required length is bigger than the current one, reallocate the buffer
|
|
pData->NtInfoData.SetLength(Length);
|
|
|
|
// Perform the call
|
|
if(NT_SUCCESS(Status))
|
|
{
|
|
Status = NtQueryInformationFile(pData->hFile,
|
|
&IoStatus,
|
|
pData->NtInfoData.pbData,
|
|
Length,
|
|
FileInfoClass);
|
|
}
|
|
|
|
// If succeeded, we have to fill the dialog with file info
|
|
if(NT_SUCCESS(Status) || Status == STATUS_BUFFER_OVERFLOW)
|
|
FillDialogWithFileInfo(hDlg, FileInfoData, (int)FileInfoClass);
|
|
|
|
// Set the result status and return
|
|
SetResultInfo(hDlg, RSI_NTSTATUS | RSI_INFORMATION, Status, &IoStatus);
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
static int OnQueryDirClick(HWND hDlg)
|
|
{
|
|
FILE_INFORMATION_CLASS FileInfoClass;
|
|
TFileTestData * pData = GetDialogData(hDlg);
|
|
IO_STATUS_BLOCK IoStatus = {0};
|
|
PUNICODE_STRING FileMask = NULL;
|
|
TInfoData * pInfoData;
|
|
ULONG_PTR TotalLength = 0;
|
|
NTSTATUS Status = STATUS_SUCCESS;
|
|
BOOLEAN RestartScan = TRUE;
|
|
HANDLE hEvent = NULL;
|
|
ULONG Length = 0;
|
|
|
|
// Test if the handle is an NT file handle and get the file info class
|
|
if(IsHandleValid(pData->hFile) == FALSE)
|
|
return FALSE;
|
|
|
|
// Get the selected info data
|
|
pInfoData = GetSelectedInfoClass(hDlg, IDC_FILE_INFO_CLASS, FileInfoData);
|
|
if(pInfoData == NULL)
|
|
return FALSE;
|
|
|
|
// Get the file information class
|
|
FileInfoClass = (FILE_INFORMATION_CLASS)(pInfoData->InfoClass);
|
|
|
|
// Get the input mask
|
|
FileMask = GetQueryDirectoryMask(hDlg, IDC_SEARCH_MASK);
|
|
|
|
// Get the input length
|
|
DlgText2Hex32(hDlg, IDC_INPUT_LENGTH, &Length);
|
|
|
|
// If the required length is bigger than the current one, reallocate the buffer
|
|
pData->NtInfoData.SetLength(Length);
|
|
|
|
// Create event for asynchronous calls
|
|
if(NT_SUCCESS(Status))
|
|
{
|
|
hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
|
|
if(hEvent == NULL)
|
|
Status = STATUS_UNSUCCESSFUL;
|
|
}
|
|
|
|
// Perform the directory query. Note that we need to keep enumerating
|
|
// until we get out of memory or until STATUS_NO_MORE_FILES is returned.
|
|
// https://github.com/ladislav-zezula/FileTest/issues/32
|
|
if(NT_SUCCESS(Status))
|
|
{
|
|
PCHAINED_ENTRY LastEntry = NULL;
|
|
LPBYTE pbDataEnd = pData->NtInfoData.pbData + pData->NtInfoData.cbData;
|
|
LPBYTE pbDataPtr = pData->NtInfoData.pbData;
|
|
|
|
// Do not allow buffer overflow
|
|
while(pbDataPtr < pbDataEnd)
|
|
{
|
|
// Perform the single directory query
|
|
Status = NtQueryDirectoryFile(pData->hFile,
|
|
hEvent,
|
|
NULL,
|
|
NULL,
|
|
&IoStatus,
|
|
pbDataPtr,
|
|
(ULONG)(pbDataEnd - pbDataPtr),
|
|
FileInfoClass,
|
|
FALSE,
|
|
FileMask,
|
|
RestartScan);
|
|
|
|
// If the operation is pending, we have to wait until it's complete
|
|
if(Status == STATUS_PENDING)
|
|
{
|
|
WaitForSingleObject(hEvent, INFINITE);
|
|
Status = IoStatus.Status;
|
|
}
|
|
|
|
// Calculate the total length returned
|
|
TotalLength = (pbDataPtr + IoStatus.Information) - pData->NtInfoData.pbData;
|
|
|
|
// Anything else than STATUS_SUCCESS will break the loop.
|
|
// At the end of the search, we expect STATUS_NO_MORE_FILES
|
|
if(Status != STATUS_SUCCESS)
|
|
break;
|
|
|
|
// If we have data from the previous search, mark the last entry
|
|
// so we can later process the whole buffer as if it was result of a single search
|
|
if(LastEntry != NULL)
|
|
DirEntry_Mark(LastEntry, pbDataPtr);
|
|
LastEntry = DirEntry_Find(pbDataPtr, IoStatus.Information);
|
|
|
|
// Prepare the 8-byte-aligned pointer to the next directory query
|
|
pbDataPtr += ALIGN_TO_SIZE(IoStatus.Information, 0x08);
|
|
RestartScan = FALSE;
|
|
}
|
|
}
|
|
|
|
// If succeeded, we have to fill the dialog with file info
|
|
if(NT_SUCCESS(Status) || Status == STATUS_NO_MORE_FILES || Status == STATUS_BUFFER_OVERFLOW)
|
|
{
|
|
pData->NtInfoData.SetLength(TotalLength);
|
|
FillDialogWithFileInfo(hDlg, FileInfoData, (int)FileInfoClass);
|
|
}
|
|
|
|
// Set the result status and return
|
|
if(hEvent != NULL)
|
|
CloseHandle(hEvent);
|
|
if(FileMask != NULL)
|
|
HeapFree(g_hHeap, 0, FileMask);
|
|
SetResultInfo(hDlg, RSI_NTSTATUS | RSI_INFORMATION, Status, &IoStatus);
|
|
return TRUE;
|
|
}
|
|
|
|
static int OnSetInfoClick(HWND hDlg)
|
|
{
|
|
FILE_INFORMATION_CLASS FileInfoClass;
|
|
TFileTestData * pData = GetDialogData(hDlg);
|
|
IO_STATUS_BLOCK IoStatus = {0};
|
|
TInfoData * pInfoData;
|
|
NTSTATUS Status = STATUS_SUCCESS;
|
|
ULONG Length = 0;
|
|
|
|
// Test if the handle is an NT file handle and get the file info class
|
|
if(IsHandleValid(pData->hFile) == FALSE)
|
|
return FALSE;
|
|
|
|
// Get the selected info data
|
|
pInfoData = GetSelectedInfoClass(hDlg, IDC_FILE_INFO_CLASS, FileInfoData);
|
|
if(pInfoData == NULL)
|
|
return FALSE;
|
|
|
|
// Get the file information class
|
|
FileInfoClass = (FILE_INFORMATION_CLASS)(pInfoData->InfoClass);
|
|
|
|
// Get the length of the input data
|
|
DlgText2Hex32(hDlg, IDC_INPUT_LENGTH, &Length);
|
|
|
|
// If the required length is bigger than the current one, reallocate the buffer
|
|
pData->NtInfoData.SetLength(Length);
|
|
|
|
// Call NtSetInformationFile
|
|
if(NT_SUCCESS(Status))
|
|
{
|
|
Status = NtSetInformationFile(pData->hFile,
|
|
&IoStatus,
|
|
pData->NtInfoData.pbData,
|
|
Length,
|
|
FileInfoClass);
|
|
}
|
|
|
|
// Set the result status and return
|
|
SetResultInfo(hDlg, RSI_NTSTATUS | RSI_INFORMATION, Status, &IoStatus);
|
|
return TRUE;
|
|
}
|
|
|
|
static int OnQueryFsInfoClick(HWND hDlg)
|
|
{
|
|
FS_INFORMATION_CLASS FsInfoClass;
|
|
TFileTestData * pData = GetDialogData(hDlg);
|
|
TInfoData * pInfoData;
|
|
IO_STATUS_BLOCK IoStatus = {0};
|
|
NTSTATUS Status = STATUS_SUCCESS;
|
|
ULONG Length = 0;
|
|
|
|
// Test if the handle is an NT file handle and get the file info class
|
|
if(IsHandleValid(pData->hFile) == FALSE)
|
|
return FALSE;
|
|
|
|
// Get the selected info data
|
|
pInfoData = GetSelectedInfoClass(hDlg, IDC_VOL_INFO_CLASS, FsInfoData);
|
|
if(pInfoData == NULL)
|
|
return FALSE;
|
|
|
|
// Get the file system info class
|
|
FsInfoClass = (FS_INFORMATION_CLASS)(pInfoData->InfoClass);
|
|
|
|
// Get the input length
|
|
DlgText2Hex32(hDlg, IDC_INPUT_LENGTH, &Length);
|
|
|
|
// If the required length is bigger than the current one, reallocate the buffer
|
|
pData->NtInfoData.SetLength(Length);
|
|
|
|
// Perform the call
|
|
if(NT_SUCCESS(Status))
|
|
{
|
|
Status = NtQueryVolumeInformationFile(pData->hFile,
|
|
&IoStatus,
|
|
pData->NtInfoData.pbData,
|
|
Length,
|
|
FsInfoClass);
|
|
}
|
|
|
|
// If succeeded, we have to fill the dialog with file info
|
|
if(NT_SUCCESS(Status) || Status == STATUS_BUFFER_OVERFLOW)
|
|
FillDialogWithFileInfo(hDlg, FsInfoData, (int)FsInfoClass);
|
|
|
|
// Set the result status and return
|
|
SetResultInfo(hDlg, RSI_NTSTATUS | RSI_INFORMATION, Status, &IoStatus);
|
|
return TRUE;
|
|
}
|
|
|
|
static int OnSetFsInfoClick(HWND hDlg)
|
|
{
|
|
FS_INFORMATION_CLASS FsInfoClass;
|
|
TFileTestData * pData = GetDialogData(hDlg);
|
|
IO_STATUS_BLOCK IoStatus = {0};
|
|
TInfoData * pInfoData;
|
|
NTSTATUS Status = STATUS_SUCCESS;
|
|
ULONG Length = 0;
|
|
|
|
// Test if the handle is an NT file handle and get the file info class
|
|
if(IsHandleValid(pData->hFile) == FALSE)
|
|
return FALSE;
|
|
|
|
// Get the selected info data
|
|
pInfoData = GetSelectedInfoClass(hDlg, IDC_VOL_INFO_CLASS, FsInfoData);
|
|
if(pInfoData == NULL)
|
|
return FALSE;
|
|
|
|
// Get the file system info class
|
|
FsInfoClass = (FS_INFORMATION_CLASS)(pInfoData->InfoClass);
|
|
|
|
// Get the length of the input data
|
|
DlgText2Hex32(hDlg, IDC_INPUT_LENGTH, &Length);
|
|
|
|
// If the required length is bigger than the current one, reallocate the buffer
|
|
pData->NtInfoData.SetLength(Length);
|
|
|
|
// Call NtSetInformationFile
|
|
if(NT_SUCCESS(Status))
|
|
{
|
|
Status = NtSetVolumeInformationFile(pData->hFile,
|
|
&IoStatus,
|
|
pData->NtInfoData.pbData,
|
|
Length,
|
|
FsInfoClass);
|
|
}
|
|
|
|
// Set the result status and return
|
|
SetResultInfo(hDlg, RSI_NTSTATUS | RSI_INFORMATION, Status, &IoStatus);
|
|
return TRUE;
|
|
}
|
|
|
|
static int OnCommand(HWND hDlg, UINT nNotify, UINT nIDCtrl)
|
|
{
|
|
if(nNotify == BN_CLICKED || nNotify == 1)
|
|
{
|
|
switch(nIDCtrl)
|
|
{
|
|
case ID_EDIT_LABEL:
|
|
return TreeView_EditLabel_ID(hDlg, IDC_FILE_INFO);
|
|
|
|
case IDC_DEFAULT_LENGTH:
|
|
return OnDefaultLengthClick(hDlg);
|
|
|
|
case IDC_MAXIMUM_LENGTH:
|
|
return OnMaximumLengthClick(hDlg);
|
|
|
|
case IDC_QUERY_INFO:
|
|
return OnQueryInfoClick(hDlg);
|
|
|
|
case IDC_QUERY_DIR:
|
|
return OnQueryDirClick(hDlg);
|
|
|
|
case IDC_SET_INFO:
|
|
return OnSetInfoClick(hDlg);
|
|
|
|
case IDC_QUERY_VOL_INFO:
|
|
return OnQueryFsInfoClick(hDlg);
|
|
|
|
case IDC_SET_VOL_INFO:
|
|
return OnSetFsInfoClick(hDlg);
|
|
}
|
|
}
|
|
|
|
// Extra handling for comboboxes with info class
|
|
if(nIDCtrl == IDC_FILE_INFO_CLASS || nIDCtrl == IDC_VOL_INFO_CLASS)
|
|
{
|
|
switch(nNotify)
|
|
{
|
|
// Provide more convenient item search than the default one
|
|
case CBN_EDITUPDATE:
|
|
OnComboBoxEditUpdate(hDlg, nIDCtrl, (nIDCtrl == IDC_FILE_INFO_CLASS) ? FileInfoData : FsInfoData);
|
|
return TRUE;
|
|
|
|
// If the selection has been changed, reflect it in the dialog
|
|
case CBN_SELENDOK:
|
|
OnComboBoxItemSelected(hDlg, nIDCtrl, (nIDCtrl == IDC_FILE_INFO_CLASS) ? FileInfoData : FsInfoData);
|
|
return TRUE;
|
|
}
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
static int OnNotify(HWND hDlg, NMHDR * pNMHDR)
|
|
{
|
|
switch(pNMHDR->code)
|
|
{
|
|
case PSN_SETACTIVE:
|
|
return OnSetActive(hDlg);
|
|
|
|
case PSN_KILLACTIVE:
|
|
TimerTooltipProc(hDlg, WM_TIMER, 0, 0);
|
|
break;
|
|
|
|
case TVN_SELCHANGED:
|
|
TimerTooltipProc(hDlg, WM_TIMER, 0, 0);
|
|
break;
|
|
|
|
case TVN_BEGINLABELEDIT:
|
|
return OnBeginLabelEdit(hDlg, (NMTVDISPINFO *)pNMHDR);
|
|
|
|
case TVN_ENDLABELEDIT:
|
|
return OnEndLabelEdit(hDlg, (NMTVDISPINFO *)pNMHDR);
|
|
|
|
case TVN_KEYDOWN:
|
|
return OnTVKeyDown_CopyToClipboard(hDlg, (LPNMTVKEYDOWN)pNMHDR);
|
|
|
|
case NM_DBLCLK:
|
|
return OnDoubleClick(hDlg, pNMHDR);
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
static int OnDestroy(HWND hDlg)
|
|
{
|
|
TimerTooltipProc(hDlg, WM_TIMER, 0, 0);
|
|
|
|
// Free the first anchors, if exist
|
|
if(pAnchors1 != NULL && pAnchors1->GetParentWindow() == hDlg)
|
|
{
|
|
delete pAnchors1;
|
|
pAnchors1 = NULL;
|
|
}
|
|
|
|
// Free the second anchors, if exist
|
|
if(pAnchors2 != NULL && pAnchors2->GetParentWindow() == hDlg)
|
|
{
|
|
delete pAnchors2;
|
|
pAnchors2 = NULL;
|
|
}
|
|
|
|
// Close the target directory handle
|
|
if(IsHandleValid(hDirTarget))
|
|
NtClose(hDirTarget);
|
|
hDirTarget = NULL;
|
|
return FALSE;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Public functions
|
|
|
|
INT_PTR CALLBACK PageProc06(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
switch(uMsg)
|
|
{
|
|
case WM_INITDIALOG:
|
|
return OnInitDialog(hDlg, lParam);
|
|
|
|
case WM_SIZE:
|
|
if(pAnchors1 != NULL && pAnchors1->GetParentWindow() == hDlg)
|
|
pAnchors1->OnMessage(uMsg, wParam, lParam);
|
|
if(pAnchors2 != NULL && pAnchors2->GetParentWindow() == hDlg)
|
|
pAnchors2->OnMessage(uMsg, wParam, lParam);
|
|
return FALSE;
|
|
|
|
case WM_ACTIVATE:
|
|
if(wParam == WA_INACTIVE)
|
|
TimerTooltipProc(hDlg, WM_TIMER, 0, 0);
|
|
break;
|
|
|
|
case WM_RELOADITEMS:
|
|
return OnReloadItems(hDlg, (HWND)wParam, (HTREEITEM)lParam);
|
|
|
|
case WM_SHOW_DATE_FORMATS:
|
|
return OnShowDateFormats(hDlg, (HWND)wParam, (HTREEITEM)lParam);
|
|
|
|
case WM_COMMAND:
|
|
return OnCommand(hDlg, HIWORD(wParam), LOWORD(wParam));
|
|
|
|
case WM_NOTIFY:
|
|
return OnNotify(hDlg, (NMHDR *)lParam);
|
|
|
|
case WM_DESTROY:
|
|
return OnDestroy(hDlg);
|
|
}
|
|
return FALSE;
|
|
}
|