windows-nt/Source/XPSP1/NT/sdktools/fsdump/lib/engine.cpp
2020-09-26 16:20:57 +08:00

837 lines
34 KiB
C++

/*++
Copyright (c) 2000-2001 Microsoft Corporation
Module Name:
engine.cpp
Abstract:
The file system dump utility engine.
Author:
Stefan R. Steiner [ssteiner] 02-18-2000
Revision History:
--*/
#include "stdafx.h"
#include "direntrs.h"
#include "extattr.h"
#include "engine.h"
static VOID
TimeString(
IN FILETIME *pFileTime,
IN BOOL bAddMillisecsToTimestamps,
OUT LPWSTR pwszTimeStr
);
/*++
Routine Description:
Performs the actual dump of the directory or file.
Arguments:
Return Value:
<Enter return values here>
--*/
DWORD
CDumpEngine::PerformDump()
{
//
// Perform the actual dump
//
DWORD dwRet;
//
// Kind of a hack, set the no data string if we want something other than dashes
//
if ( m_pcParams->m_bDumpCommaDelimited )
FsdEaSetNoDataString( L"" );
//
// Volume state manager manages all state about all volumes that are encountered during
// the dump.
//
CFsdVolumeStateManager cFsdVolStateManager( m_pcParams );
//
// Get information about the volume
//
CFsdVolumeState *pcFsdVolState;
dwRet = cFsdVolStateManager.GetVolumeState( m_cwsDirFileSpec, &pcFsdVolState );
assert( dwRet != ERROR_ALREADY_EXISTS );
if ( dwRet != ERROR_SUCCESS )
return dwRet;
if ( m_pcParams->m_bDumpCommaDelimited )
{
m_pcParams->DumpPrintAlways( L"File name,Short Name,Creation date,Last modification date,File size,Attr,DACE,SACE,SDCtl,UNamChkS,DStr,DStrSize,DStrChkS,Prop,RPTag,RPSize,RPChkS,EncrChkS,DACLSize,DACLChkS,SACLSize,SACLChkS,NLnk,ObjectId,OIDChkS,FS,Owner Sid,Group Sid" );
//
// Put the current time into the CSV dump file for easy detection of when
// dumps are taken
//
FILETIME sSysFT, sLocalFT;
::GetSystemTimeAsFileTime( &sSysFT );
::FileTimeToLocalFileTime( &sSysFT, &sLocalFT );
WCHAR wszCurrentTime[32];
::TimeString( &sLocalFT, FALSE, wszCurrentTime );
m_pcParams->DumpPrintAlways( L"Dump time: %s", wszCurrentTime );
}
else
{
// if ( ( m_pcParams->m_eFsDumpType == eFsDumpVolume ) &&
// ( m_cwsDirFileSpec != pcFsdVolState->GetVolumePath() ) )
// {
// m_pcParams->ErrPrint( L"'%s' is not a drive specifier or mountpoint, use -dd instead",
// m_cwsDirFileSpec.c_str() );
// return 1;
// }
m_pcParams->DumpPrintAlways( L"\nDumping: '%s' on volume '%s'", m_cwsDirFileSpec.c_str(), pcFsdVolState->GetVolumePath() );
if ( m_pcParams->m_bAddMillisecsToTimestamps )
m_pcParams->DumpPrintAlways(
L" Creation date Last modification date FileSize Attr FileName ShortName DACE SACE SDCtl UNamChkS DStr DStrSize DStrChkS Prop RPTag RPSize RPChkS EncrChkS DACLSize DACLChkS SACLSize SACLChkS NLnk ObjectId OIDChkS OwnerSid/GroupSid" );
else
m_pcParams->DumpPrintAlways( L" Creation date Last mod. date FileSize Attr FileName ShortName DACE SACE SDCtl UNamChkS DStr DStrSize DStrChkS Prop RPTag RPSize RPChkS EncrChkS DACLSize DACLChkS SACLSize SACLChkS NLnk ObjectId OIDChkS OwnerSid/GroupSid" );
}
////////////////////////////////////////////////////////////////////
//
// Get the file info for the root dir or file
// Bug # 157915
//
////////////////////////////////////////////////////////////////////
bool bRootIsADir = true;
CBsString cwsDirFileSpecWithoutSlash( m_cwsDirFileSpec );
if ( cwsDirFileSpecWithoutSlash.Right( 1 ) == L"\\" )
cwsDirFileSpecWithoutSlash = cwsDirFileSpecWithoutSlash.Left( cwsDirFileSpecWithoutSlash.GetLength() - 1 );
try
{
CDirectoryEntries cRootEntry(
m_pcParams,
cwsDirFileSpecWithoutSlash
);
//
// Only one entry should be returned in either the directory list or file list
//
SDirectoryEntry *psDirEntry;
//
// See if it is file entry
//
CDirectoryEntriesIterator *pListIter;
pListIter = cRootEntry.GetFileListIterator();
if ( pListIter->GetNext( psDirEntry ) )
{
bRootIsADir = false;
++m_ullNumFiles;
m_ullNumBytesTotalUnnamedStream += ( ( ( ULONGLONG )psDirEntry->m_sFindData.nFileSizeHigh ) << 32 ) |
psDirEntry->m_sFindData.nFileSizeLow;
if ( psDirEntry->m_sFindData.dwFileAttributes & FILE_ATTRIBUTE_ENCRYPTED )
++m_ullNumEncryptedFiles;
PrintEntry( pcFsdVolState, cwsDirFileSpecWithoutSlash,
cwsDirFileSpecWithoutSlash.GetLength(), psDirEntry, TRUE );
ASSERT( pListIter->GetNext( psDirEntry ) == false );
}
delete pListIter;
//
// See if it is a directory entry
//
pListIter = cRootEntry.GetDirListIterator();
if ( pListIter->GetNext( psDirEntry ) )
{
ASSERT( bRootIsADir );
// It is
++m_ullNumDirs;
PrintEntry( pcFsdVolState, cwsDirFileSpecWithoutSlash,
cwsDirFileSpecWithoutSlash.GetLength(), psDirEntry, TRUE );
ASSERT( pListIter->GetNext( psDirEntry ) == false );
}
delete pListIter;
}
catch ( DWORD dwRet )
{
if ( dwRet == ERROR_INVALID_NAME || dwRet == ERROR_BAD_NET_NAME )
{
//
// Must be working with the root of the drive letter name space which
// means we do things slightly differently.
//
SDirectoryEntry sDirEntry;
::memset( &sDirEntry.m_sFindData, 0x00, sizeof( sDirEntry.m_sFindData ) );
PrintEntry( pcFsdVolState, m_cwsDirFileSpec,
m_cwsDirFileSpec.GetLength(), &sDirEntry, TRUE );
}
else
m_pcParams->ErrPrint( L"PerformDump: Unexpected error trying to process '%s', dwRet: %d",
m_cwsDirFileSpec.c_str(), dwRet );
}
catch ( ... )
{
m_pcParams->ErrPrint( L"ProcessDir() Caught an unexpected exception processing file: '%s', Last dwRet: %d",
m_cwsDirFileSpec.c_str(), ::GetLastError() );
}
//
// Now traverse into the volume/directory if necessary
//
if ( m_pcParams->m_eFsDumpType != eFsDumpFile )
{
if ( bRootIsADir )
{
dwRet = ProcessDir(
&cFsdVolStateManager,
pcFsdVolState,
m_cwsDirFileSpec,
m_cwsDirFileSpec.GetLength(),
::wcslen( pcFsdVolState->GetVolumePath() ) );
}
//
// Print out some stats about the dump
//
m_pcParams->DumpPrint( L"\nSTATISTICS for '%s':", m_cwsDirFileSpec.c_str() );
if ( m_pcParams->m_bHex )
{
m_pcParams->DumpPrint( L" Number of directories (including mountpoints): %16I64x(hex)", m_ullNumDirs );
m_pcParams->DumpPrint( L" Number of files: %16I64x(hex)", m_ullNumFiles );
m_pcParams->DumpPrint( L" Number of mountpoints: %16I64x(hex)", m_ullNumMountpoints );
m_pcParams->DumpPrint( L" Number of reparse points (excluding mountpoints): %16I64x(hex)", m_ullNumReparsePoints );
m_pcParams->DumpPrint( L" Number of hard-linked files: %16I64x(hex)", m_ullNumHardLinks );
m_pcParams->DumpPrint( L" Number of discrete DACL ACEs: %16I64x(hex)", m_ullNumDiscreteDACEs );
m_pcParams->DumpPrint( L" Number of discrete SACL ACEs: %16I64x(hex)", m_ullNumDiscreteSACEs );
m_pcParams->DumpPrint( L" Number of encrypted files: %16I64x(hex)", m_ullNumEncryptedFiles );
m_pcParams->DumpPrint( L" Number of files with object ids: %16I64x(hex)", m_ullNumFilesWithObjectIds );
if ( m_pcParams->m_bUseExcludeProcessor )
m_pcParams->DumpPrint( L" Number of files excluded due to exclusion rules: %16I64x(hex)", m_ullNumFilesExcluded );
m_pcParams->DumpPrint( L" Total bytes of checksummed data: %16I64x(hex)", m_ullNumBytesChecksummed );
m_pcParams->DumpPrint( L" Total bytes of unnamed stream data: %16I64x(hex)", m_ullNumBytesTotalUnnamedStream );
m_pcParams->DumpPrint( L" Total bytes of named data stream data: %16I64x(hex)", m_ullNumBytesTotalNamedDataStream );
}
else
{
m_pcParams->DumpPrint( L" Number of directories (including mountpoints): %16I64u", m_ullNumDirs );
m_pcParams->DumpPrint( L" Number of files: %16I64u", m_ullNumFiles );
m_pcParams->DumpPrint( L" Number of mountpoints: %16I64u", m_ullNumMountpoints );
m_pcParams->DumpPrint( L" Number of reparse points (excluding mountpoints): %16I64u", m_ullNumReparsePoints );
m_pcParams->DumpPrint( L" Number of hard-linked files: %16I64u", m_ullNumHardLinks );
m_pcParams->DumpPrint( L" Number of discrete DACL ACEs: %16I64u", m_ullNumDiscreteDACEs );
m_pcParams->DumpPrint( L" Number of discrete SACL ACEs: %16I64u", m_ullNumDiscreteSACEs );
m_pcParams->DumpPrint( L" Number of encrypted files: %16I64u", m_ullNumEncryptedFiles );
m_pcParams->DumpPrint( L" Number of files with object ids: %16I64u", m_ullNumFilesWithObjectIds );
if ( m_pcParams->m_bUseExcludeProcessor )
m_pcParams->DumpPrint( L" Number of files excluded due to exclusion rules: %16I64u", m_ullNumFilesExcluded );
m_pcParams->DumpPrint( L" Total bytes of checksummed data: %16I64u", m_ullNumBytesChecksummed );
m_pcParams->DumpPrint( L" Total bytes of unnamed stream data: %16I64u", m_ullNumBytesTotalUnnamedStream );
m_pcParams->DumpPrint( L" Total bytes of named data stream data: %16I64u", m_ullNumBytesTotalNamedDataStream );
}
if ( m_pcParams->m_bUseExcludeProcessor )
{
//
// Print out exclusion information
//
cFsdVolStateManager.PrintExclusionInformation();
}
cFsdVolStateManager.PrintHardLinkInfo();
}
return dwRet;
}
/*++
Routine Description:
Traverses into a directory and dumps all the information about the dir.
NOTE: This is a recursive function.
Arguments:
cwsDirPath - The directory path or file to dump information about
Return Value:
<Enter return values here>
--*/
DWORD
CDumpEngine::ProcessDir(
IN CFsdVolumeStateManager *pcFsdVolStateManager,
IN CFsdVolumeState *pcFsdVolState,
IN const CBsString& cwsDirPath,
IN INT cDirFileSpecLength,
IN INT cVolMountPointOffset
)
{
DWORD dwRet = ERROR_SUCCESS;
try
{
if ( !m_pcParams->m_bDumpCommaDelimited )
{
if ( cwsDirPath.GetLength() == cDirFileSpecLength )
{
//
// This is the root of the directory
//
m_pcParams->DumpPrintAlways( L"'.\\' - %s", ( pcFsdVolState != NULL ) ? pcFsdVolState->GetFileSystemName() : L"???" );
}
else
{
m_pcParams->DumpPrintAlways( L"'%s' - %s", cwsDirPath.c_str() + cDirFileSpecLength,
( pcFsdVolState != NULL ) ? pcFsdVolState->GetFileSystemName() : L"???" );
}
}
//
// Get the directory entries for the directory/file
//
CDirectoryEntries cDirEntries(
m_pcParams,
cwsDirPath + L"*"
);
SDirectoryEntry *psDirEntry;
//
// First dump out the sub-directory entries
//
CDirectoryEntriesIterator *pDirListIter;
pDirListIter = cDirEntries.GetDirListIterator();
while ( pDirListIter->GetNext( psDirEntry ) )
{
++m_ullNumDirs;
if ( psDirEntry->m_sFindData.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT )
{
++m_ullNumMountpoints;
}
PrintEntry( pcFsdVolState, cwsDirPath, cDirFileSpecLength, psDirEntry );
}
//
// Next dump out the non-sub-directory entries
//
CDirectoryEntriesIterator *pFileListIter;
pFileListIter = cDirEntries.GetFileListIterator();
while ( pFileListIter->GetNext( psDirEntry ) )
{
++m_ullNumFiles;
m_ullNumBytesTotalUnnamedStream += ( ( ( ULONGLONG )psDirEntry->m_sFindData.nFileSizeHigh ) << 32 ) |
psDirEntry->m_sFindData.nFileSizeLow;
if ( psDirEntry->m_sFindData.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT )
++m_ullNumReparsePoints;
if ( psDirEntry->m_sFindData.dwFileAttributes & FILE_ATTRIBUTE_ENCRYPTED )
++m_ullNumEncryptedFiles;
//
// Check to see if we should exclude the file
//
if ( pcFsdVolState->IsExcludedFile( cwsDirPath, cVolMountPointOffset, psDirEntry->GetFileName() ) )
++m_ullNumFilesExcluded;
else
PrintEntry( pcFsdVolState, cwsDirPath, cDirFileSpecLength, psDirEntry );
}
delete pFileListIter;
if ( m_pcParams->m_eFsDumpType == eFsDumpVolume
|| m_pcParams->m_eFsDumpType == eFsDumpDirTraverse )
{
//
// Now traverse into each sub-directory
//
pDirListIter->Reset();
CBsString cwsTraversePath;
while ( pDirListIter->GetNext( psDirEntry ) )
{
if ( m_pcParams->m_bDontTraverseMountpoints
&& psDirEntry->m_sFindData.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT )
continue;
cwsTraversePath = cwsDirPath + psDirEntry->GetFileName();
cwsTraversePath += L'\\';
//
// Now go into recursion mode
//
if ( psDirEntry->m_sFindData.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT )
{
//
// Traversing into another volume, get it's state
//
CFsdVolumeState *pcNewFsdVolState;
DWORD dwRet;
dwRet = pcFsdVolStateManager->GetVolumeState( cwsTraversePath, &pcNewFsdVolState );
if ( dwRet == ERROR_ALREADY_EXISTS )
{
//
// Mountpoint cycle, stop traversing. Need to print the fully qualified
// path if the traversal mountpoint is the same as the mountpoint
// we started with, otherwise we AV.
//
INT cVolStateSpecLength;
cVolStateSpecLength = ( ::wcslen( pcNewFsdVolState->GetVolumePath() ) <= (size_t)cDirFileSpecLength )
? 0 : cDirFileSpecLength;
m_pcParams->DumpPrint( L"'%s' - Not traversing, already traversed through '%s' mountpoint",
cwsTraversePath.c_str() + cDirFileSpecLength, pcNewFsdVolState->GetVolumePath() + cVolStateSpecLength );
}
else if ( dwRet == ERROR_SUCCESS )
{
ProcessDir(
pcFsdVolStateManager,
pcNewFsdVolState,
cwsTraversePath,
cDirFileSpecLength,
::wcslen( pcNewFsdVolState->GetVolumePath() ) );
}
else
{
//
// Error message already printed out
//
}
}
else
{
ProcessDir(
pcFsdVolStateManager,
pcFsdVolState,
cwsTraversePath,
cDirFileSpecLength,
cVolMountPointOffset );
}
}
}
delete pDirListIter;
}
catch ( DWORD dwRet )
{
m_pcParams->ErrPrint( L"ProcessDir: Error trying to process '%s' directory, dwRet: %d", cwsDirPath.c_str(), dwRet );
}
catch ( ... )
{
m_pcParams->ErrPrint( L"ProcessDir() Caught an unexpected exception processing dir: '%s', Last dwRet: %d",
cwsDirPath.c_str(), ::GetLastError() );
}
return 0;
}
//
// printf style format strings which format each line
//
#define DIR_STR L"<DIR>"
#define JUNCTION_STR L"<JUNCTION>"
#define FMT_DIR_STR_HEX L" %s %s %-16s %04x %-32s %-12s %4d %4d %04x -------- %4d %8I64x %s %4d %s %6hx %s %s %8hx %s %8hx %s %4d %36s %s %%s/%s"
#define FMT_DIR_STR L" %s %s %-16s %04x %-32s %-12s %4d %4d %04x -------- %4d %8I64d %s %4d %s %6hu %s %s %8hd %s %8hd %s %4d %36s %s %s/%s"
#define FMT_FILE_STR_HEX L" %s %s %16I64x %04x %-32s %-12s %4d %4d %04x %s %4d %8I64x %s %4d %s %6hx %s %s %8hx %s %8hx %s %4d %36s %s %s/%s"
#define FMT_FILE_STR L" %s %s %16I64d %04x %-32s %-12s %4d %4d %04x %s %4d %8I64d %s %4d %s %6hu %s %s %8hd %s %8hd %s %4d %36s %s %s/%s"
#define BLANKTIMESTAMPWITHOUTMS L" "
#define BLANKTIMESTAMPWITHMS L" "
#define FMT_CSV_DIR_STR L"\"'%s%s\\'\",%s,%s,%s,%s,0x%04x,%d,%d,0x%04x,,%d,%I64d,%s,%d,%s,%hu,%s,%s,%hd,%s,%hd,%s,%d,%s,%s,%s,%s,%s"
#define FMT_CSV_FILE_STR L"\"'%s%s'\",%s,%s,%s,%I64d,0x%04x,%d,%d,0x%04x,%s,%d,%I64d,%s,%d,%s,%hu,%s,%s,%hd,%s,%hd,%s,%d,%s,%s,%s,%s,%s"
/*++
Routine Description:
Prints out all the information about one directory entry.
Arguments:
cwsDirPath - The path leading up to the entry
psDirEntry - The directory entry information
Return Value:
NONE
--*/
VOID
CDumpEngine::PrintEntry(
IN CFsdVolumeState *pcFsdVolState,
IN const CBsString& cwsDirPath,
IN INT cDirFileSpecLength,
IN SDirectoryEntry *psDirEntry,
IN BOOL bSingleEntryOutput
)
{
WIN32_FILE_ATTRIBUTE_DATA *pFD = &psDirEntry->m_sFindData;
LPWSTR pwszFmtStr;
WCHAR wszCreationTime[32];
WCHAR wszLastWriteTime[32];
//
// Get the additional information about the file/dir
//
SFileExtendedInfo sExtendedInfo;
::GetExtendedFileInfo( m_pcParams, pcFsdVolState, cwsDirPath, bSingleEntryOutput, psDirEntry, &sExtendedInfo );
//
// Convert the timestamps into formatted strings
//
if ( pFD->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY
&& m_pcParams->m_bDontShowDirectoryTimestamps )
{
if ( m_pcParams->m_bDumpCommaDelimited )
{
wszCreationTime[0] = L'\0';
wszLastWriteTime[0] = L'\0';
}
else if ( m_pcParams->m_bAddMillisecsToTimestamps )
{
::wcscpy( wszCreationTime, BLANKTIMESTAMPWITHMS );
::wcscpy( wszLastWriteTime, BLANKTIMESTAMPWITHMS );
}
else
{
::wcscpy( wszCreationTime, BLANKTIMESTAMPWITHOUTMS );
::wcscpy( wszLastWriteTime, BLANKTIMESTAMPWITHOUTMS );
}
}
else
{
TimeString( &psDirEntry->m_sFindData.ftCreationTime,
m_pcParams->m_bAddMillisecsToTimestamps,
wszCreationTime );
TimeString( &psDirEntry->m_sFindData.ftLastWriteTime,
m_pcParams->m_bAddMillisecsToTimestamps,
wszLastWriteTime );
}
//
// Mask out the requested file attribute bits
//
pFD->dwFileAttributes &= ~m_pcParams->m_dwFileAttributesMask;
m_ullNumBytesChecksummed += sExtendedInfo.ullTotalBytesChecksummed;
m_ullNumBytesTotalNamedDataStream += sExtendedInfo.ullTotalBytesNamedDataStream;
if ( sExtendedInfo.lNumberOfLinks > 1 )
++m_ullNumHardLinks;
if ( sExtendedInfo.lNumDACEs != -1 )
m_ullNumDiscreteDACEs += sExtendedInfo.lNumDACEs;
if ( sExtendedInfo.lNumSACEs != -1 )
m_ullNumDiscreteSACEs += sExtendedInfo.lNumSACEs;
if ( !sExtendedInfo.cwsObjectId.IsEmpty() )
++m_ullNumFilesWithObjectIds;
WCHAR wszReparsePointTag[32];
if ( sExtendedInfo.ulReparsePointTag == 0 )
{
if ( m_pcParams->m_bDumpCommaDelimited )
wszReparsePointTag[0] = L'\0';
else
::memcpy( wszReparsePointTag, L"--------", sizeof( WCHAR ) * 9 );
}
else
{
wsprintf( wszReparsePointTag, m_pcParams->m_pwszULongHexFmt, sExtendedInfo.ulReparsePointTag );
}
if ( pFD->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY )
{
LPWSTR pwszDirType;
if ( pFD->dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT )
pwszDirType = JUNCTION_STR;
else
pwszDirType = DIR_STR;
if ( m_pcParams->m_bDumpCommaDelimited )
{
//
// If single file output mode, then processing the root directory
//
if ( bSingleEntryOutput )
psDirEntry->m_cwsFileName = L".";
CBsString cwsFixedShortName;
if ( !psDirEntry->GetShortName().IsEmpty() )
{
cwsFixedShortName = L"\"'" + psDirEntry->GetShortName() + L"'\"";
}
m_pcParams->DumpPrintAlways( FMT_CSV_DIR_STR,
cwsDirPath.c_str() + cDirFileSpecLength,
LPCWSTR( psDirEntry->GetFileName() ),
LPCWSTR( cwsFixedShortName ),
wszCreationTime,
wszLastWriteTime,
pwszDirType,
pFD->dwFileAttributes,
sExtendedInfo.lNumDACEs,
sExtendedInfo.lNumSACEs,
sExtendedInfo.wSecurityDescriptorControl,
sExtendedInfo.lNumNamedDataStreams,
sExtendedInfo.ullTotalBytesNamedDataStream,
sExtendedInfo.cwsNamedDataStreamChecksum.c_str(),
sExtendedInfo.lNumPropertyStreams,
wszReparsePointTag,
sExtendedInfo.wReparsePointDataSize,
sExtendedInfo.cwsReparsePointDataChecksum.c_str(),
sExtendedInfo.cwsEncryptedRawDataChecksum.c_str(),
sExtendedInfo.wDACLSize,
sExtendedInfo.cwsDACLChecksum.c_str(),
sExtendedInfo.wSACLSize,
sExtendedInfo.cwsSACLChecksum.c_str(),
sExtendedInfo.lNumberOfLinks,
sExtendedInfo.cwsObjectId.c_str(),
sExtendedInfo.cwsObjectIdExtendedDataChecksum.c_str(),
pcFsdVolState->GetFileSystemName(),
sExtendedInfo.cwsOwnerSid.c_str(),
sExtendedInfo.cwsGroupSid.c_str() );
}
else
{
//
// If single file output mode, then processing the root directory
//
if ( bSingleEntryOutput )
psDirEntry->m_cwsFileName = L".";
//
// Print with quotes around the file name
//
WCHAR wszNameWithQuotes[ MAX_PATH + 2 ];
wszNameWithQuotes[ 0 ] = L'\'';
::wcscpy( wszNameWithQuotes + 1, psDirEntry->GetFileName() );
::wcscat( wszNameWithQuotes, L"\\\'" );
if ( m_pcParams->m_bHex )
pwszFmtStr = FMT_DIR_STR_HEX;
else
pwszFmtStr = FMT_DIR_STR;
m_pcParams->DumpPrintAlways( pwszFmtStr,
wszCreationTime,
wszLastWriteTime,
pwszDirType,
pFD->dwFileAttributes,
wszNameWithQuotes,
LPCWSTR( psDirEntry->GetShortName() ),
sExtendedInfo.lNumDACEs,
sExtendedInfo.lNumSACEs,
sExtendedInfo.wSecurityDescriptorControl,
sExtendedInfo.lNumNamedDataStreams,
sExtendedInfo.ullTotalBytesNamedDataStream,
sExtendedInfo.cwsNamedDataStreamChecksum.c_str(),
sExtendedInfo.lNumPropertyStreams,
wszReparsePointTag,
sExtendedInfo.wReparsePointDataSize,
sExtendedInfo.cwsReparsePointDataChecksum.c_str(),
sExtendedInfo.cwsEncryptedRawDataChecksum.c_str(),
sExtendedInfo.wDACLSize,
sExtendedInfo.cwsDACLChecksum.c_str(),
sExtendedInfo.wSACLSize,
sExtendedInfo.cwsSACLChecksum.c_str(),
sExtendedInfo.lNumberOfLinks,
sExtendedInfo.cwsObjectId.c_str(),
sExtendedInfo.cwsObjectIdExtendedDataChecksum.c_str(),
sExtendedInfo.cwsOwnerSid.c_str(),
sExtendedInfo.cwsGroupSid.c_str() );
}
}
else
{
ULONGLONG ullFileSize = ( ( (ULONGLONG)pFD->nFileSizeHigh ) << 32 ) + pFD->nFileSizeLow;
if ( m_pcParams->m_bDumpCommaDelimited )
{
CBsString cwsFixedShortName;
if ( !psDirEntry->GetShortName().IsEmpty() )
{
cwsFixedShortName = L"\"'" + psDirEntry->GetShortName() + L"'\"";
}
m_pcParams->DumpPrintAlways( FMT_CSV_FILE_STR,
cwsDirPath.c_str() + cDirFileSpecLength,
LPCWSTR( psDirEntry->GetFileName() ),
LPCWSTR( cwsFixedShortName ),
wszCreationTime,
wszLastWriteTime,
ullFileSize,
pFD->dwFileAttributes,
sExtendedInfo.lNumDACEs,
sExtendedInfo.lNumSACEs,
sExtendedInfo.wSecurityDescriptorControl,
sExtendedInfo.cwsUnnamedStreamChecksum.c_str(),
sExtendedInfo.lNumNamedDataStreams,
sExtendedInfo.ullTotalBytesNamedDataStream,
sExtendedInfo.cwsNamedDataStreamChecksum.c_str(),
sExtendedInfo.lNumPropertyStreams,
wszReparsePointTag,
sExtendedInfo.wReparsePointDataSize,
sExtendedInfo.cwsReparsePointDataChecksum.c_str(),
sExtendedInfo.cwsEncryptedRawDataChecksum.c_str(),
sExtendedInfo.wDACLSize,
sExtendedInfo.cwsDACLChecksum.c_str(),
sExtendedInfo.wSACLSize,
sExtendedInfo.cwsSACLChecksum.c_str(),
sExtendedInfo.lNumberOfLinks,
sExtendedInfo.cwsObjectId.c_str(),
sExtendedInfo.cwsObjectIdExtendedDataChecksum.c_str(),
pcFsdVolState->GetFileSystemName(),
sExtendedInfo.cwsOwnerSid.c_str(),
sExtendedInfo.cwsGroupSid.c_str() );
}
else
{
//
// Print with quotes around the file name
//
WCHAR wszNameWithQuotes[ MAX_PATH + 2 ];
wszNameWithQuotes[ 0 ] = L'\'';
::wcscpy( wszNameWithQuotes + 1, psDirEntry->GetFileName() );
::wcscat( wszNameWithQuotes, L"\'" );
if ( m_pcParams->m_bHex )
pwszFmtStr = FMT_FILE_STR_HEX;
else
pwszFmtStr = FMT_FILE_STR;
m_pcParams->DumpPrintAlways( pwszFmtStr,
wszCreationTime,
wszLastWriteTime,
ullFileSize,
pFD->dwFileAttributes,
wszNameWithQuotes,
LPCWSTR( psDirEntry->GetShortName() ),
sExtendedInfo.lNumDACEs,
sExtendedInfo.lNumSACEs,
sExtendedInfo.wSecurityDescriptorControl,
sExtendedInfo.cwsUnnamedStreamChecksum.c_str(),
sExtendedInfo.lNumNamedDataStreams,
sExtendedInfo.ullTotalBytesNamedDataStream,
sExtendedInfo.cwsNamedDataStreamChecksum.c_str(),
sExtendedInfo.lNumPropertyStreams,
wszReparsePointTag,
sExtendedInfo.wReparsePointDataSize,
sExtendedInfo.cwsReparsePointDataChecksum.c_str(),
sExtendedInfo.cwsEncryptedRawDataChecksum.c_str(),
sExtendedInfo.wDACLSize,
sExtendedInfo.cwsDACLChecksum.c_str(),
sExtendedInfo.wSACLSize,
sExtendedInfo.cwsSACLChecksum.c_str(),
sExtendedInfo.lNumberOfLinks,
sExtendedInfo.cwsObjectId.c_str(),
sExtendedInfo.cwsObjectIdExtendedDataChecksum.c_str(),
sExtendedInfo.cwsOwnerSid.c_str(),
sExtendedInfo.cwsGroupSid.c_str() );
}
}
}
/*++
Routine Description:
Formats dates into a common string format.
Arguments:
Return Value:
<Enter return values here>
--*/
static VOID
TimeString(
IN FILETIME *pFileTime,
IN BOOL bAddMillisecsToTimestamps,
OUT LPWSTR pwszTimeStr
)
{
SYSTEMTIME szTime;
::FileTimeToSystemTime( pFileTime, &szTime );
if ( bAddMillisecsToTimestamps )
{
wsprintf( pwszTimeStr,
L"%02d/%02d/%02d %02d:%02d:%02d.%03d",
szTime.wMonth,
szTime.wDay,
szTime.wYear,
szTime.wHour,
szTime.wMinute,
szTime.wSecond,
szTime.wMilliseconds );
}
else
{
wsprintf( pwszTimeStr,
L"%02d/%02d/%02d %02d:%02d:%02d",
szTime.wMonth,
szTime.wDay,
szTime.wYear,
szTime.wHour,
szTime.wMinute,
szTime.wSecond );
}
}
LPCSTR
CDumpEngine::GetHeaderInformation()
{
LPSTR pszHeaderInfo =
"Creation date - Creation date of the file/dir\n"
"Last mod. date - Last modification date of the file/dir\n"
"FileSize - Size of the unnamed data stream if a file\n"
"Attr - File attributes with Archive and Normal bits masked by\n"
" default (hex)\n"
"FileName - Name of the file in single quotes\n"
"ShortName - The classic 8.3 file name. If <->, FileName is in\n"
" classic format\n"
"DACE - Number of discretionary ACL entries\n"
"SACE - Number of system ACL entries\n"
"SDCtl - Security Descripter control word (hex)\n"
"UNamChkS - Data checksum of the unnamed data stream (hex)\n"
"DStr - Number of named data streams\n"
"DStrSize - Size of all of the named data streams\n"
"DStrChkS - Data checksum of all named data streams including their\n"
" names (hex)\n"
"Prop - Number of property data streams\n"
"RPTag - Reparse point tag value (hex)\n"
"RPSize - Size of reparse point data\n"
"RPChkS - Checksum of the reparse point data (hex)\n"
"EncrChkS - Raw encrypted data checksum (hex)\n"
"DACLSize - Size of the complete discretionary ACL\n"
"DACLChkS - Checksum of the complete discretionary ACL (hex)\n"
"SACLSize - Size of the complete system ACL\n"
"SACLChkS - Checksum of the complete system ACL (hex)\n"
"NLnk - Number of hard links\n"
"ObjectId - Object Id GUID on the file if it has one\n"
"OIDChkS - Object Id extended data checksum\n"
"FS - Type of file system (in CSV format only)\n"
"OwnerSid/GroupSid - The owner and group sid values\n";
return pszHeaderInfo;
}