windows-nt/Source/XPSP1/NT/inetsrv/query/apps/pd1.1/main.cxx
2020-09-26 16:20:57 +08:00

551 lines
17 KiB
C++

//+-------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1996 - 1998
//
// File: main.cxx
//
// Contents: Index Server V1.x property file dumper.
//
// History: 29 Oct 1996 KyleP Created
//
//--------------------------------------------------------------------------
#include <pch.cxx>
#pragma hdrstop
#include <proprec.hxx>
#include <propdesc.hxx>
DECLARE_INFOLEVEL(ci)
unsigned const SixtyFourK = 1024 * 64;
unsigned const cMaxFields = 10;
unsigned fVerbose = 0;
enum eRecType
{
Virgin,
Top,
Overflow,
Free
};
struct SmallInfo
{
ULONG Type;
ULONG Length;
ULONG ulPrev;
ULONG ulNext;
ULONG ulChainLength;
};
int __cdecl main( int argc, char * argv[] )
{
char * pszFile = argv[1];
BOOL fReadMetadata = 0;
unsigned cField = 0;
int aiField[cMaxFields];
for ( int i = 1; i < argc; i++ )
{
if ( argv[i][0] == '-' )
{
switch ( argv[i][1] )
{
case 'v':
case 'V':
fVerbose = 1;
break;
case 'm':
case 'M':
fReadMetadata = TRUE;
break;
case 'f':
case 'F':
i++;
if ( cField < cMaxFields )
aiField[cField++] = strtol( argv[i], 0, 10 );
break;
}
}
else
pszFile = argv[i];
}
BYTE abTemp[SixtyFourK];
//
// First, read out the metadata
//
unsigned cFixed = 0;
unsigned cTotal = 0;
unsigned culFixed = 0;
CPropDesc aFieldRec[cMaxFields];
if ( fReadMetadata || cField != 0 )
{
//
// Build path.
//
char szPath[MAX_PATH];
strcpy( szPath, pszFile );
char * pLastSlash = strrchr( szPath, '\\' );
pLastSlash++;
strcpy( pLastSlash, "CIPS0000.001" );
HANDLE h = CreateFileA( szPath,
GENERIC_READ,
FILE_SHARE_READ,
0,
OPEN_EXISTING,
0,
0 );
if ( INVALID_HANDLE_VALUE == h )
{
printf( "Can't open file %s. Error %u\n", szPath, GetLastError() );
return 0;
}
ULONG cbRead;
if ( ReadFile( h,
abTemp,
sizeof(abTemp),
&cbRead,
0 ) )
{
//
// Loop through records
//
CPropDesc * pPropDesc = (CPropDesc *)abTemp;
if ( fReadMetadata )
printf( "Record\tPid\t\tType\t\tOffset\tSize\tOrdinal\tMask\n" );
for ( unsigned i = 0; i < cbRead/sizeof(CPropDesc); i++, pPropDesc++ )
{
if ( pPropDesc->Pid() != 0 )
{
if ( fReadMetadata )
printf( "%u:\t%u (0x%x)%s\t%u (0x%x)\t%d\t%u\t%u\t0x%x\n",
pPropDesc->Record(),
pPropDesc->Pid(), pPropDesc->Pid(),
(pPropDesc->Pid() > 10) ? "" : "\t",
pPropDesc->Type(), pPropDesc->Type(),
pPropDesc->Offset(),
pPropDesc->Size(),
pPropDesc->Ordinal(),
pPropDesc->Mask() );
cTotal++;
if ( pPropDesc->Offset() != -1 )
{
cFixed++;
culFixed += (pPropDesc->Size() / sizeof(DWORD));
}
for ( unsigned j = 0; j < cField; j++ )
{
if ( aiField[j] == (int)pPropDesc->Record() )
memcpy( &aFieldRec[j], pPropDesc, sizeof(aFieldRec[0]) );
}
}
}
printf( "\n%u Properties, %u Fixed totaling %u bytes\n\n", cTotal, cFixed, culFixed * sizeof(DWORD) );
}
else
{
printf( "Can't read file %s. Error %u\n", szPath, GetLastError() );
return 0;
}
}
HANDLE h = CreateFileA( pszFile,
GENERIC_READ,
FILE_SHARE_READ,
0,
OPEN_EXISTING,
0,
0 );
if ( INVALID_HANDLE_VALUE == h )
{
printf( "Can't open file %s. Error %u\n", pszFile, GetLastError() );
return 0;
}
BY_HANDLE_FILE_INFORMATION fi;
if ( !GetFileInformationByHandle( h, &fi ) )
{
printf( "Error %u getting size from handle\n", GetLastError() );
return 0;
}
ULONG oFile = 0;
ULONG cbRec = 0;
ULONG cRecPerBuf;
ULONG cRecTotal;
ULONG cTotalSections = 0;
HANDLE hSmallInfo;
SmallInfo * aSmallInfo = 0;
ULONG iSection = 0;
BOOL fFirst = TRUE;
ULONG iCurrentPct = 0;
for (;;)
{
ULONG cbRead;
if ( ReadFile( h,
abTemp,
sizeof(abTemp),
&cbRead,
0 ) )
{
if (fVerbose)
printf( "READ: 0x%x bytes, offset %0x%x\n", cbRead, oFile );
if ( 0 == cbRead )
break;
if ( fFirst )
{
//
// Determine record size
//
if ( abTemp[0] != 0 || abTemp[1] != 0 )
{
printf( "Record 0 not blank. File corrupt!\n" );
break;
}
for ( unsigned i = 0; i < cbRead && abTemp[i] == 0; i++ )
continue;
if ( i == cbRead )
{
printf( "First %uK segment all zero!. File corrupt!\n", sizeof(abTemp)/1024 );
break;
}
switch ( *(USHORT *)&abTemp[i] )
{
case 0x5555:
case 0xAAAA:
case 0xBBBB:
cbRec = i;
if ( cbRec % 4 != 0 )
{
printf( "Record size (%u bytes) not DWORD aligned!\n\n", cbRec );
return 0;
}
cRecPerBuf = sizeof(abTemp) / cbRec;
printf( "Record size: %u bytes (%u / %uK)\n", i, cRecPerBuf, sizeof(abTemp)/1024 );
cTotalSections = (fi.nFileSizeLow + sizeof(abTemp) - 1)/ sizeof abTemp;
hSmallInfo = LocalAlloc( LMEM_MOVEABLE,
((fi.nFileSizeLow / sizeof(abTemp)) + 1) * cRecPerBuf * sizeof(SmallInfo) );
aSmallInfo = (SmallInfo *)LocalLock( hSmallInfo );
break;
default:
printf( "First non-zero byte is not a proper signature (%u)!\n", *(SHORT *)&abTemp[i] );
return 0;
}
fFirst = FALSE;
}
ULONG iRec = 0;
while ( iRec < cRecPerBuf )
{
COnDiskPropertyRecord * pRec = new( iRec, abTemp, cbRec/4 ) COnDiskPropertyRecord;
if ( !pRec->IsValidType() )
{
printf( "Record 0x%x (%u:%u) (file offset 0x%x) is corrupt!\n",
iSection * cRecPerBuf + iRec,
iSection, iRec,
iSection * sizeof(abTemp) + iRec * cbRec );
}
if (fVerbose )
printf( "%u:%u, %s, length = %u record(s)",
iSection, iRec,
pRec->IsTopLevel() ? "Top Level" :
pRec->IsOverflow() ? "Overflow" :
pRec->IsFreeRecord() ? "Free" :
"Virgin",
pRec->CountRecords() );
aSmallInfo[iSection*cRecPerBuf + iRec].ulChainLength = 0;
if ( pRec->IsOverflow() )
{
aSmallInfo[iSection*cRecPerBuf + iRec].Type = Overflow;
/* printf( ", Previous = %u:%u (file offset 0x%x)",
pRec->PreviousBlock() / cRecPerBuf,
pRec->PreviousBlock() % cRecPerBuf,
(pRec->PreviousBlock() / cRecPerBuf) * sizeof(abTemp) +
(pRec->PreviousBlock() % cRecPerBuf) * cbRec ); */
}
else if ( pRec->IsTopLevel() )
{
aSmallInfo[iSection*cRecPerBuf + iRec].Type = Top;
aSmallInfo[iSection*cRecPerBuf + iRec].ulChainLength = pRec->GetOverflowChainLength();
for ( unsigned j = 0; j < cField; j++ )
{
PROPVARIANT var;
BYTE abExtra[MAX_PATH * 5];
unsigned cbExtra = sizeof(abExtra);
if ( 0 == j )
printf( "%6u: ", iSection*cRecPerBuf + iRec );
if ( aFieldRec[j].IsFixedSize() )
{
pRec->ReadFixed( aFieldRec[j].Ordinal(),
aFieldRec[j].Mask(),
aFieldRec[j].Offset(),
cTotal,
aFieldRec[j].Type(),
var,
abExtra,
&cbExtra );
switch ( var.vt )
{
case VT_EMPTY:
printf( "n/a " );
break;
case VT_I4:
printf( "%8d ", var.iVal );
break;
case VT_UI4:
printf( "%8u ", var.uiVal );
break;
case VT_FILETIME:
printf( "%8u,%8u ",
var.filetime.dwHighDateTime,
var.filetime.dwLowDateTime );
break;
case VT_I8:
printf( "%12hu ", var.hVal );
break;
}
}
else
{
BOOL fOk = pRec->ReadVariable( aFieldRec[j].Ordinal(),
aFieldRec[j].Mask(),
culFixed,
cTotal,
cFixed,
var,
abExtra,
&cbExtra );
if ( fOk )
{
switch ( var.vt )
{
case VT_LPSTR:
printf( "%s ", var.pszVal );
break;
case VT_LPWSTR:
printf( "%ws ", var.pwszVal );
break;
}
}
}
}
if ( 0 != cField )
printf( "\n" );
}
else if ( pRec->IsFreeRecord() )
{
aSmallInfo[iSection*cRecPerBuf + iRec].Type = Free;
}
else
{
aSmallInfo[iSection*cRecPerBuf + iRec].Type = Virgin;
}
// 1.1 vs 2.0 change // aSmallInfo[iSection*cRecPerBuf + iRec].ulPrev = pRec->ToplevelBlock();
aSmallInfo[iSection*cRecPerBuf + iRec].ulNext = pRec->OverflowBlock();
aSmallInfo[iSection*cRecPerBuf + iRec].Length = pRec->CountRecords();
if ( pRec->CountRecords() == 0 )
{
printf( "Record %u (file offset 0x%x) is zero length!\n",
iSection * cRecPerBuf + iRec,
iSection * sizeof(abTemp) + iRec * cbRec );
}
if ( pRec->OverflowBlock() != 0 )
{
/* printf( ", Overflow = %u:%u (file offset 0x%x)",
pRec->OverflowBlock() / cRecPerBuf,
pRec->OverflowBlock() % cRecPerBuf,
(pRec->OverflowBlock() / cRecPerBuf) * sizeof(abTemp) +
(pRec->OverflowBlock() % cRecPerBuf) * cbRec ); */
}
if (fVerbose)
printf( "\n" );
if ( pRec->IsValidType() )
iRec += pRec->CountRecords();
else
iRec++;
ULONG iPct = (iSection * (100/5) / cTotalSections) * 5;
if (iPct != iCurrentPct)
{
iCurrentPct = iPct;
printf( "Read %u%%\n", iCurrentPct );
}
}
iSection++;
oFile += cbRead;
}
else
{
ULONG Status = GetLastError();
if ( Status == ERROR_HANDLE_EOF )
break;
else
{
printf( "Error %u reading file.\n", Status );
}
}
}
printf( "Read 100%%\n" );
CloseHandle( h );
//
// Now check inter-record state
//
unsigned iRec = 0;
unsigned iCurrentSection = 0;
iCurrentPct = 0;
while ( iRec < iSection * cRecPerBuf )
{
if ( aSmallInfo[iRec].Type == Top )
{
unsigned iOverflowRec = aSmallInfo[iRec].ulNext;
unsigned cOverflowRec = 0;
while ( 0 != iOverflowRec )
{
if ( aSmallInfo[iOverflowRec].Type != Overflow )
{
printf( "Record 0x%x (%u:%u) (file offset 0x%x) should be overflow and is not!\n Top level = 0x%x (%u:%u) (file offset 0x%x)\n",
iOverflowRec,
iOverflowRec / cRecPerBuf,
iOverflowRec % cRecPerBuf,
(iOverflowRec / cRecPerBuf) * sizeof(abTemp) +
(iOverflowRec % cRecPerBuf) * cbRec,
iRec,
iRec / cRecPerBuf,
iRec % cRecPerBuf,
(iRec / cRecPerBuf) * sizeof(abTemp) +
(iRec % cRecPerBuf) * cbRec );
break;
}
iOverflowRec = aSmallInfo[iOverflowRec].ulNext;
cOverflowRec++;
if ( cOverflowRec > aSmallInfo[iRec].ulChainLength )
break;
}
if ( aSmallInfo[iRec].ulChainLength != cOverflowRec )
{
printf( "Record 0x%x (%u:%u) (file offset 0x%x) chain length mismatch %d,%d!\n",
iRec,
iRec / cRecPerBuf,
iRec % cRecPerBuf,
(iRec / cRecPerBuf) * sizeof(abTemp) +
(iRec % cRecPerBuf) * cbRec,
aSmallInfo[iRec].ulChainLength, cOverflowRec );
}
}
if (aSmallInfo[iRec].Length == 0)
{
printf( "%u:%u (file offset 0x%x) zero length record!\n",
iRec / cRecPerBuf,
iRec % cRecPerBuf,
(iRec / cRecPerBuf) * sizeof(abTemp) +
(iRec % cRecPerBuf) * cbRec );
iRec++;
} else {
iRec += aSmallInfo[iRec].Length;
}
if ( (iRec / cRecPerBuf) != iCurrentSection )
{
if (fVerbose)
printf( "Checked section %u\n", iCurrentSection );
ULONG iPct = (iCurrentSection * (100/5) / iSection) * 5;
if (iPct != iCurrentPct)
{
iCurrentPct = iPct;
printf( "Checked %u%%\n", iCurrentPct );
}
iCurrentSection = (iRec / cRecPerBuf);
}
}
printf( "Checked 100%%\n" );
LocalUnlock( hSmallInfo );
LocalFree( hSmallInfo );
return 0;
}