You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
731 lines
18 KiB
731 lines
18 KiB
/*++
|
|
|
|
Copyright (c) 1998-1999 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
verifyBlob.c
|
|
|
|
Abstract:
|
|
|
|
This file contains blob verification code
|
|
|
|
Author:
|
|
|
|
Neal Christiansen (nealch) 12/18/2000
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
|
|
#include "precomp.h"
|
|
|
|
//
|
|
// If DEBUG is enabled we want to display all of the errors.
|
|
// if NOT DEBUG then return on first error
|
|
//
|
|
|
|
#if DBG
|
|
#define HANDLE_FAILURE(_good) ((_good) = FALSE)
|
|
#else
|
|
#define HANDLE_FAILURE(_good) return FALSE
|
|
#endif
|
|
|
|
//
|
|
// Private prototypes.
|
|
//
|
|
|
|
BOOL
|
|
SrVerifyBlobHeader(
|
|
BlobHeader *BlobHead,
|
|
PCHAR Name,
|
|
DWORD BlobType
|
|
);
|
|
|
|
BOOL
|
|
SrVerifyHashHeader(
|
|
ListHeader *HashHead,
|
|
PCHAR Name,
|
|
DWORD Offset
|
|
);
|
|
|
|
BOOL
|
|
SrVerifyHash(
|
|
ListHeader *HashHead,
|
|
PCHAR Name,
|
|
DWORD Offset
|
|
);
|
|
|
|
BOOL
|
|
SrVerifyTreeHeader(
|
|
TreeHeader *TreeHead,
|
|
PCHAR Name
|
|
);
|
|
|
|
BOOL
|
|
SrVerifyTree(
|
|
TreeHeader *TreeHead,
|
|
PCHAR Name,
|
|
DWORD Offset
|
|
);
|
|
|
|
#ifdef ALLOC_PRAGMA
|
|
|
|
#pragma alloc_text( PAGE, SrVerifyBlobHeader )
|
|
#pragma alloc_text( PAGE, SrVerifyHashHeader )
|
|
#pragma alloc_text( PAGE, SrVerifyHash )
|
|
#pragma alloc_text( PAGE, SrVerifyTreeHeader )
|
|
#pragma alloc_text( PAGE, SrVerifyTree )
|
|
#pragma alloc_text( PAGE, SrVerifyBlob )
|
|
|
|
#endif // ALLOC_PRAGMA
|
|
|
|
|
|
BOOL
|
|
SrVerifyBlobHeader(
|
|
BlobHeader *BlobHead,
|
|
PCHAR Name,
|
|
DWORD BlobType
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Verify that the given BLOB Header is valid
|
|
|
|
Arguments:
|
|
|
|
|
|
Return Value:
|
|
|
|
TRUE if OK else FALSE
|
|
|
|
--*/
|
|
{
|
|
BOOL good = TRUE;
|
|
|
|
UNREFERENCED_PARAMETER( Name );
|
|
|
|
if (BlobHead->m_dwVersion != BLOB_VERSION_NUM)
|
|
{
|
|
SrTrace( BLOB_VERIFICATION,
|
|
("sr!SrVerifyBlobHeader: Invalid VERSION in %s blob header, was %08x, should be %08x\n",
|
|
Name,
|
|
BlobHead->m_dwVersion,
|
|
BLOB_VERSION_NUM) );
|
|
HANDLE_FAILURE(good);
|
|
}
|
|
|
|
if (BlobHead->m_dwBlbType != BlobType)
|
|
{
|
|
SrTrace( BLOB_VERIFICATION,
|
|
("sr!SrVerifyBlobHeader: Invalid TYPE in %s blob header, was %08x, should be %08x\n",
|
|
Name,
|
|
BlobHead->m_dwBlbType,
|
|
BlobType) );
|
|
HANDLE_FAILURE(good);
|
|
}
|
|
|
|
if (BlobHead->m_dwMagicNum != BLOB_MAGIC_NUM)
|
|
{
|
|
SrTrace( BLOB_VERIFICATION,
|
|
("sr!SrVerifyBlobHeader: Invalid MAGIC NUMBER in %s blob header, was %08x, should be %08x\n",
|
|
Name,
|
|
BlobHead->m_dwMagicNum,
|
|
BLOB_MAGIC_NUM) );
|
|
HANDLE_FAILURE(good);
|
|
}
|
|
|
|
if ((BlobHead->m_dwEntries <= 0) || (BlobHead->m_dwEntries >= 10000))
|
|
{
|
|
SrTrace( BLOB_VERIFICATION,
|
|
("sr!SrVerifyBlobHeader: Invalid ENTRIES in %s blob header, was %08x, should be > 0 and < 10,000\n",
|
|
Name,
|
|
BlobHead->m_dwEntries) );
|
|
HANDLE_FAILURE(good);
|
|
}
|
|
|
|
return good;
|
|
}
|
|
|
|
|
|
|
|
BOOL
|
|
SrVerifyHashHeader(
|
|
ListHeader *HashHead,
|
|
PCHAR Name,
|
|
DWORD Offset
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Verify that the given TREE Header is valid
|
|
|
|
Arguments:
|
|
|
|
|
|
Return Value:
|
|
|
|
TRUE if OK else FALSE
|
|
|
|
--*/
|
|
{
|
|
BOOL good = TRUE;
|
|
DWORD calculatedSize;
|
|
DWORD numNodes;
|
|
|
|
UNREFERENCED_PARAMETER( Offset );
|
|
|
|
//
|
|
// Verify BLOB header
|
|
//
|
|
|
|
if (!SrVerifyBlobHeader(&HashHead->m_BlobHeader,Name,BLOB_TYPE_HASHLIST))
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// paulmcd: jan/2001
|
|
// m_iHashBuckets will not be exact with m_dwEntries as it is the next
|
|
// highest prime number. but it will always be larger than or equalto.
|
|
//
|
|
|
|
if (HashHead->m_iHashBuckets < HashHead->m_BlobHeader.m_dwEntries)
|
|
{
|
|
SrTrace( BLOB_VERIFICATION,
|
|
("sr!SrVerifyHashHeader: Invalid HASH BUCKET COUNT in %s header, is %08x, should be %08x or %08x\n",
|
|
Name,
|
|
HashHead->m_iHashBuckets,
|
|
HashHead->m_BlobHeader.m_dwEntries,
|
|
HashHead->m_BlobHeader.m_dwEntries+1) );
|
|
HANDLE_FAILURE(good);
|
|
}
|
|
|
|
if ((HashHead->m_dwDataOff != HashHead->m_BlobHeader.m_dwMaxSize))
|
|
{
|
|
SrTrace( BLOB_VERIFICATION,
|
|
("sr!SrVerifyHashHeader: Invalid DATA OFFSET in %s header, is %08x, should be %08x\n",
|
|
Name,
|
|
HashHead->m_dwDataOff,
|
|
HashHead->m_BlobHeader.m_dwMaxSize) );
|
|
HANDLE_FAILURE(good);
|
|
}
|
|
|
|
if ((HashHead->m_iFreeNode != 0))
|
|
{
|
|
SrTrace( BLOB_VERIFICATION,
|
|
("sr!SrVerifyHashHeader: Invalid FREE NODE in %s header, is %08x, should be 0\n",
|
|
Name,
|
|
HashHead->m_iFreeNode) );
|
|
HANDLE_FAILURE(good);
|
|
}
|
|
|
|
//
|
|
// Make sure the calucalted size is accurate
|
|
//
|
|
|
|
numNodes = HashHead->m_BlobHeader.m_dwEntries + 1;
|
|
|
|
calculatedSize = sizeof(ListHeader) +
|
|
(HashHead->m_iHashBuckets * sizeof(DWORD)) +
|
|
(numNodes * sizeof(ListEntry));
|
|
|
|
if (calculatedSize >= HashHead->m_BlobHeader.m_dwMaxSize)
|
|
{
|
|
SrTrace( BLOB_VERIFICATION,
|
|
("sr!SrVerifyHashHeader: Invalid CALCULATED SIZE in %s header, is %08x, should be < %08x\n",
|
|
Name,
|
|
calculatedSize,
|
|
HashHead->m_BlobHeader.m_dwMaxSize) );
|
|
HANDLE_FAILURE(good);
|
|
}
|
|
|
|
return good;
|
|
}
|
|
|
|
|
|
BOOL
|
|
SrVerifyHash(
|
|
ListHeader *HashHead,
|
|
PCHAR Name,
|
|
DWORD Offset
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Verify that the given TREE entries are valid
|
|
|
|
Arguments:
|
|
|
|
|
|
Return Value:
|
|
|
|
TRUE if OK else FALSE
|
|
|
|
--*/
|
|
{
|
|
BOOL good = TRUE;
|
|
UINT i;
|
|
DWORD dataStart;
|
|
DWORD numNodes;
|
|
DWORD numBuckets;
|
|
DWORD *hTable;
|
|
ListEntry *hNode;
|
|
|
|
//
|
|
// Validate the HEADER
|
|
//
|
|
|
|
if (!SrVerifyHashHeader(HashHead,Name,Offset))
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// paulmcd: we have hash bucket and actual nodes. there is one extra
|
|
// actual node than reported due to offset zero being null. the bucket
|
|
// count is the next largest prime from numNodes
|
|
//
|
|
|
|
numBuckets = HashHead->m_iHashBuckets;
|
|
numNodes = HashHead->m_BlobHeader.m_dwEntries + 1;
|
|
|
|
//
|
|
// Validate Hash table entries
|
|
//
|
|
|
|
hTable = (DWORD *)(HashHead + 1);
|
|
|
|
for (i=0;i < HashHead->m_iHashBuckets;i++,hTable++) {
|
|
|
|
if (*hTable >= numNodes)
|
|
{
|
|
SrTrace( BLOB_VERIFICATION,
|
|
("sr!SrVerifyHash: Invalid HASH TABLE ENTRY[%d] in %s, is %08x, should be < %08x\n",
|
|
i,
|
|
Name,
|
|
*hTable,
|
|
numNodes) );
|
|
HANDLE_FAILURE(good);
|
|
}
|
|
}
|
|
|
|
//
|
|
// Validate the start of the Hash LIST entries
|
|
//
|
|
|
|
{
|
|
ULONG_PTR actualOffset;
|
|
ULONG_PTR calculatedOffset;
|
|
|
|
actualOffset = (ULONG_PTR)hTable - (ULONG_PTR)HashHead;
|
|
calculatedOffset = sizeof(ListHeader) +
|
|
(HashHead->m_iHashBuckets * sizeof(DWORD));
|
|
|
|
if (calculatedOffset != actualOffset)
|
|
{
|
|
SrTrace( BLOB_VERIFICATION,
|
|
("sr!SrVerifyHash: Invalid HASH LIST START in %s, offset is %08x, should be %08x\n",
|
|
Name,
|
|
actualOffset,
|
|
calculatedOffset) );
|
|
HANDLE_FAILURE(good);
|
|
}
|
|
}
|
|
|
|
//
|
|
// Validate the Hash DATA entries
|
|
//
|
|
|
|
hNode = (ListEntry *)hTable;
|
|
dataStart = sizeof(ListHeader) +
|
|
(HashHead->m_iHashBuckets * sizeof(DWORD)) +
|
|
(numNodes * sizeof(ListEntry));
|
|
|
|
for (i=0;i < numNodes;i++,hNode++) {
|
|
|
|
if ((hNode->m_iNext < 0) ||
|
|
(hNode->m_iNext >= (INT)HashHead->m_iHashBuckets))
|
|
{
|
|
SrTrace( BLOB_VERIFICATION,
|
|
("sr!SrVerifyHash: Invalid HASH NODE[%d] NEXT INDEX in %s, is %08x, should be < %08x\n",
|
|
i,
|
|
Name,
|
|
hNode->m_iNext,
|
|
HashHead->m_iHashBuckets) );
|
|
HANDLE_FAILURE(good);
|
|
}
|
|
|
|
if ((hNode->m_dwData != 0) &&
|
|
((hNode->m_dwData < dataStart) ||
|
|
(hNode->m_dwData >= HashHead->m_BlobHeader.m_dwMaxSize)))
|
|
{
|
|
SrTrace( BLOB_VERIFICATION,
|
|
("sr!SrVerifyHash: Invalid HASH NODE[%d] DATA INDEX in %s, is %08x, should be >= %08x and < %08x\n",
|
|
i,
|
|
Name,
|
|
hNode->m_dwData,
|
|
dataStart,
|
|
HashHead->m_BlobHeader.m_dwMaxSize) );
|
|
HANDLE_FAILURE(good);
|
|
}
|
|
else if ((hNode->m_dwData != 0) &&
|
|
((WCHAR)hNode->m_dwDataLen != *(PWCHAR)((DWORD_PTR)HashHead + hNode->m_dwData)))
|
|
{
|
|
SrTrace( BLOB_VERIFICATION,
|
|
("sr!SrVerifyHash: Invalid HASH NODE[%d] DATA LENGTH in %s, is %08x, should be %08x\n",
|
|
i,
|
|
Name,
|
|
hNode->m_dwDataLen,
|
|
*(PWCHAR)((DWORD_PTR)HashHead + hNode->m_dwData)) );
|
|
HANDLE_FAILURE(good);
|
|
}
|
|
|
|
if ((hNode->m_dwType != NODE_TYPE_UNKNOWN) &&
|
|
(hNode->m_dwType != NODE_TYPE_INCLUDE) &&
|
|
(hNode->m_dwType != NODE_TYPE_EXCLUDE))
|
|
{
|
|
SrTrace( BLOB_VERIFICATION,
|
|
("sr!SrVerifyHash: Invalid HASH NODE[%d] TYPE in %s, is %08x, should be %08x, %08x or %08x\n",
|
|
i,
|
|
Name,
|
|
hNode->m_dwType,
|
|
NODE_TYPE_UNKNOWN,
|
|
NODE_TYPE_INCLUDE,
|
|
NODE_TYPE_EXCLUDE) );
|
|
HANDLE_FAILURE(good);
|
|
}
|
|
}
|
|
|
|
return good;
|
|
}
|
|
|
|
|
|
BOOL
|
|
SrVerifyTreeHeader(
|
|
TreeHeader *TreeHead,
|
|
PCHAR Name
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Verify that the given TREE Header is valid
|
|
|
|
Arguments:
|
|
|
|
|
|
Return Value:
|
|
|
|
TRUE if OK else FALSE
|
|
|
|
--*/
|
|
{
|
|
BOOL good = TRUE;
|
|
DWORD calculatedSize;
|
|
|
|
//
|
|
// Verify BLOB header
|
|
//
|
|
|
|
if (!SrVerifyBlobHeader(&TreeHead->m_BlobHeader,Name,BLOB_TYPE_PATHTREE))
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
if ((TreeHead->m_dwMaxNodes != TreeHead->m_BlobHeader.m_dwEntries))
|
|
{
|
|
SrTrace( BLOB_VERIFICATION,
|
|
("sr!SrVerifyTreeHeader: Invalid MAX NODES in %s header, is %08x, should be %08x\n",
|
|
Name,
|
|
TreeHead->m_dwMaxNodes,
|
|
TreeHead->m_BlobHeader.m_dwEntries) );
|
|
HANDLE_FAILURE(good);
|
|
}
|
|
|
|
if ((TreeHead->m_dwDataSize >= TreeHead->m_BlobHeader.m_dwMaxSize))
|
|
{
|
|
SrTrace( BLOB_VERIFICATION,
|
|
("sr!SrVerifyTreeHeader: Invalid DATA SIZE in %s header, is %08x, should be < %08x\n",
|
|
Name,
|
|
TreeHead->m_dwDataSize,
|
|
TreeHead->m_BlobHeader.m_dwMaxSize) );
|
|
HANDLE_FAILURE(good);
|
|
}
|
|
|
|
if ((TreeHead->m_dwDataOff != TreeHead->m_BlobHeader.m_dwMaxSize))
|
|
{
|
|
SrTrace( BLOB_VERIFICATION,
|
|
("sr!SrVerifyTreeHeader: Invalid DATA OFFSET in %s header, is %08x, should be %08x\n",
|
|
Name,
|
|
TreeHead->m_dwDataOff,
|
|
TreeHead->m_BlobHeader.m_dwMaxSize) );
|
|
HANDLE_FAILURE(good);
|
|
}
|
|
|
|
if ((TreeHead->m_iFreeNode != 0))
|
|
{
|
|
SrTrace( BLOB_VERIFICATION,
|
|
("sr!SrVerifyTreeHeader: Invalid FREE NODE in %s header, is %08x, should be 0\n",
|
|
Name,
|
|
TreeHead->m_iFreeNode) );
|
|
HANDLE_FAILURE(good);
|
|
}
|
|
|
|
if ((TreeHead->m_dwDefault != NODE_TYPE_EXCLUDE))
|
|
{
|
|
SrTrace( BLOB_VERIFICATION,
|
|
("sr!SrVerifyTreeHeader: Invalid DEFAULT in %s header, is %08x, should be %08x\n",
|
|
Name,
|
|
TreeHead->m_dwDefault,
|
|
NODE_TYPE_EXCLUDE) );
|
|
HANDLE_FAILURE(good);
|
|
}
|
|
|
|
//
|
|
// Make sure the calucalted size is accurate
|
|
//
|
|
|
|
calculatedSize = sizeof(TreeHeader) +
|
|
(TreeHead->m_dwMaxNodes * sizeof(TreeNode)) +
|
|
TreeHead->m_dwDataSize;
|
|
|
|
if (calculatedSize != TreeHead->m_BlobHeader.m_dwMaxSize)
|
|
{
|
|
SrTrace( BLOB_VERIFICATION,
|
|
("sr!SrVerifyTreeHeader: Invalid CALCULATED SIZE in %s header, is %08x, should be %08x\n",
|
|
Name,
|
|
calculatedSize,
|
|
TreeHead->m_BlobHeader.m_dwMaxSize) );
|
|
HANDLE_FAILURE(good);
|
|
}
|
|
|
|
return good;
|
|
}
|
|
|
|
|
|
BOOL
|
|
SrVerifyTree(
|
|
TreeHeader *TreeHead,
|
|
PCHAR Name,
|
|
DWORD Offset
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Verify that the given TREE entries are valid
|
|
|
|
Arguments:
|
|
|
|
|
|
Return Value:
|
|
|
|
TRUE if OK else FALSE
|
|
|
|
--*/
|
|
{
|
|
BOOL good = TRUE;
|
|
UINT i;
|
|
DWORD dataStart;
|
|
TreeNode *tn;
|
|
ListHeader *localHashHead;
|
|
char localName[128];
|
|
|
|
//
|
|
// Validate the HEADER
|
|
//
|
|
|
|
if (!SrVerifyTreeHeader(TreeHead,Name)) {
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// Validate the DATA entries
|
|
//
|
|
|
|
tn = (TreeNode *)(TreeHead + 1);
|
|
dataStart = sizeof(TreeHeader) +
|
|
(TreeHead->m_dwMaxNodes * sizeof(TreeNode));
|
|
|
|
|
|
for (i=0;i < TreeHead->m_dwMaxNodes;i++,tn++)
|
|
{
|
|
if ((tn->m_iFather < 0) ||
|
|
(tn->m_iFather >= (INT)TreeHead->m_dwMaxNodes))
|
|
{
|
|
SrTrace( BLOB_VERIFICATION,
|
|
("sr!SrVerifyTree: Invalid TREE NODE[%d] FATHER index in %s, is %08x, should be < %08x\n",
|
|
i,
|
|
Name,
|
|
tn->m_iFather,
|
|
TreeHead->m_dwMaxNodes) );
|
|
HANDLE_FAILURE(good);
|
|
}
|
|
|
|
if ((tn->m_iSon < 0) ||
|
|
(tn->m_iSon >= (INT)TreeHead->m_dwMaxNodes))
|
|
{
|
|
SrTrace( BLOB_VERIFICATION,
|
|
("sr!SrVerifyTree: Invalid TREE NODE[%d] SON index in %s, is %08x, should be < %08x\n",
|
|
i,
|
|
Name,
|
|
tn->m_iSon,
|
|
TreeHead->m_dwMaxNodes) );
|
|
HANDLE_FAILURE(good);
|
|
}
|
|
|
|
if ((tn->m_iSibling < 0) ||
|
|
(tn->m_iSibling >= (INT)TreeHead->m_dwMaxNodes))
|
|
{
|
|
SrTrace( BLOB_VERIFICATION,
|
|
("sr!SrVerifyTree: Invalid TREE NODE[%d] SIBLING index in %s, is %08x, should be < %08x\n",
|
|
i,
|
|
Name,
|
|
tn->m_iSibling,
|
|
TreeHead->m_dwMaxNodes) );
|
|
HANDLE_FAILURE(good);
|
|
}
|
|
|
|
if ((tn->m_dwData < dataStart) ||
|
|
(tn->m_dwData >= TreeHead->m_BlobHeader.m_dwMaxSize))
|
|
{
|
|
SrTrace( BLOB_VERIFICATION,
|
|
("sr!SrVerifyTree: Invalid TREE NODE[%d] DATA index in %s, is %08x, should be >= %08x and < %08x\n",
|
|
i,
|
|
Name,
|
|
tn->m_dwData,
|
|
dataStart,
|
|
TreeHead->m_BlobHeader.m_dwMaxSize) );
|
|
HANDLE_FAILURE(good);
|
|
}
|
|
|
|
if (tn->m_dwFileList != 0)
|
|
{
|
|
if ((tn->m_dwFileList < dataStart) ||
|
|
(tn->m_dwFileList >= TreeHead->m_BlobHeader.m_dwMaxSize))
|
|
{
|
|
SrTrace( BLOB_VERIFICATION,
|
|
("sr!SrVerifyTree: Invalid TREE NODE[%d] FILELIST index in %s, is %08x, should be >= %08x and < %08x\n",
|
|
i,
|
|
Name,
|
|
tn->m_dwData,
|
|
dataStart,
|
|
TreeHead->m_BlobHeader.m_dwMaxSize) );
|
|
HANDLE_FAILURE(good);
|
|
}
|
|
else
|
|
{
|
|
localHashHead = (ListHeader *)((DWORD_PTR)TreeHead + tn->m_dwFileList);
|
|
sprintf(localName,"TreeNode[%d]",i);
|
|
|
|
if (!SrVerifyHash(localHashHead,localName,(Offset+tn->m_dwFileList)))
|
|
{
|
|
HANDLE_FAILURE(good);
|
|
}
|
|
}
|
|
}
|
|
|
|
if ((tn->m_dwType != NODE_TYPE_UNKNOWN) &&
|
|
(tn->m_dwType != NODE_TYPE_INCLUDE) &&
|
|
(tn->m_dwType != NODE_TYPE_EXCLUDE))
|
|
{
|
|
SrTrace( BLOB_VERIFICATION,
|
|
("sr!SrVerifyTree: Invalid TREE NODE[%d] TYPE in %s, is %08x, should be %08x, %08x or %08x\n",
|
|
i,
|
|
Name,
|
|
tn->m_dwType,
|
|
NODE_TYPE_UNKNOWN,
|
|
NODE_TYPE_INCLUDE,
|
|
NODE_TYPE_EXCLUDE) );
|
|
HANDLE_FAILURE(good);
|
|
}
|
|
}
|
|
|
|
return good;
|
|
}
|
|
|
|
|
|
|
|
BOOL
|
|
SrVerifyBlob(
|
|
PBYTE Blob
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Verify that the given BLOB is valid
|
|
|
|
Arguments:
|
|
|
|
|
|
Return Value:
|
|
|
|
TRUE if OK else FALSE
|
|
|
|
--*/
|
|
{
|
|
BlobHeader *blobHead;
|
|
TreeHeader *treeHead;
|
|
ListHeader *hashHead;
|
|
DWORD calculatedSize = 0;
|
|
|
|
//
|
|
// Verify header to entire blob
|
|
//
|
|
|
|
blobHead = (BlobHeader *)Blob;
|
|
|
|
if (!SrVerifyBlobHeader(blobHead,"PRIMARY",BLOB_TYPE_CONTAINER))
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
calculatedSize += sizeof(BlobHeader);
|
|
|
|
//
|
|
// Verify TreeHeader and Data
|
|
//
|
|
|
|
treeHead = (TreeHeader *)(Blob + calculatedSize);
|
|
|
|
if (!SrVerifyTree(treeHead,"PRIMARY TREE",calculatedSize))
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
calculatedSize += treeHead->m_BlobHeader.m_dwMaxSize;
|
|
|
|
//
|
|
// Verify HashHeader and DATA
|
|
//
|
|
|
|
hashHead = (ListHeader *)(Blob + calculatedSize);
|
|
|
|
if (!SrVerifyHash(hashHead,"PRIMARY HASH",calculatedSize))
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
calculatedSize += hashHead->m_BlobHeader.m_dwMaxSize;
|
|
|
|
//
|
|
// Validate total SIZE
|
|
//
|
|
|
|
if (calculatedSize != blobHead->m_dwMaxSize)
|
|
{
|
|
SrTrace( BLOB_VERIFICATION,
|
|
("sr!SrVerifyBlob: Invalid PRIMARY BLOB size, is %08x, calculated to be %08x\n",
|
|
blobHead->m_dwMaxSize,
|
|
calculatedSize) );
|
|
return FALSE;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|