Leaked source code of windows server 2003
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.
 
 
 
 
 
 

2215 lines
56 KiB

/*++
Copyright (c) 1997 Microsoft Corporation
Module Name:
recchk.c
Abstract:
This file implements the record database checking code. There are two types of
persistent data structures, the priority Q (or our version of Master FIle Table)
and the hierarchy of files and directories that starts with the superroot which
contains all the shares connected to. The truth is considered to be in the
hierarchy. The Priority Q is supposed to mirror some critical data from the
hierarchy. When fixing the database, we traverse the hierarchy
recursively and build an in memory PQ. We then write that out as the new PQ.
This file gets linked in the usermode and in the kernlemode so that for NT this
can execute in kernel mode while for win9x it can execute in usermode
Author:
Shishir Pardikar [Shishirp] 10-30-1997
Revision History:
split up from usermode.
--*/
#include "precomp.h"
#pragma hdrstop
#pragma code_seg("PAGE")
#include "record.h"
#include "string.h"
#include "stdlib.h"
// Record Buffer Array (RBA). This holds an entire inode file in memory
// It is made up of pointers to 1 or more Record Buffer Entries (RBE).
// Each RBE is a chunk of memory that holds an integral number of records from
// the file represented by ulidShadow entry in the structure
typedef struct tagRBA
{
unsigned ulErrorFlags;
unsigned ulidShadow; // Inode which is represented by this structure
GENERICHEADER sGH; // it's header
CSCHFILE hf; // open handle to the file
DWORD cntRBE; // count of buffer entries in the array
DWORD cntRecsPerRBE; // #of records per buffer entry
DWORD cbRBE; // size in bytes of each buffer entry
LPBYTE rgRBE[]; // Record Buffer Entry (RBE) array
}
RBA, *LPRBA; // stands for RecordBuffArray
#define RBA_ERROR_INVALID_HEADER 0x00000001
#define RAB_ERROR_INVALID_RECORD_COUNT 0x00000002
#define RBA_ERROR_INVALID_OVF 0x00000004
#define RBA_ERROR_INVALID_ENTRY 0x00000008
#define RBA_ERROR_MISMATCHED_SIZE 0x00000010
#define RBA_ERROR_MISALIGNED_RECORD 0x00000020
#define RBA_ERROR_INVALID_INODE 0x00000040
#define RBA_ERROR_LIMIT_EXCEEDED 0x00000080
#define MAX_RECBUFF_ENTRY_SIZE (0x10000-0x100) // max size of an RBE
#define MAX_RBES_EXPECTED 0x30 // Max number of RBEs of the above size in an RBA
// we make provision for max possible # of RBEs, even beyond what the PQ currently
// needs. The max set here is (MAX_RBES_EXPETCED * MAX_RECBUFF_ENTRY_SIZE)
// which amounts to 48 * 65280 which is around 3M which at the current size of
// QREC will hold ~100K entries in the hierarchy. This is far more than
// the # of entries we ever expect to have in our database
// As we allocate memory only as it is needed, it would'nt be a problem to
// increase MAX_RBES_EXPECTED so it handles more inodes
typedef struct tagCSE *LPCSE;
typedef struct tagCSE // CSC Stack Entry
{
LPCSE lpcseNext;
unsigned ulidShare; // server
unsigned ulidParent; // parent of the directory
unsigned ulidDir; // the directory itself
unsigned ulRec;
LPRBA lpRBA; // the contents of ulidDir
}
CSE;
#pragma intrinsic (memcmp, memcpy, memset, strcat, strcmp, strcpy, strlen)
#ifdef DEBUG
//cshadow dbgprint interface
#define RecchkKdPrint(__bit,__x) {\
if (((RECCHK_KDP_##__bit)==0) || FlagOn(RecchkKdPrintVector,(RECCHK_KDP_##__bit))) {\
KdPrint (__x);\
}\
}
#define RECCHK_KDP_ALWAYS 0x00000000
#define RECCHK_KDP_BADERRORS 0x00000001
#define RECCHK_KDP_TRAVERSE 0x00000002
#define RECCHK_KDP_PQ 0x00000004
#define RECCHK_KDP_RBA 0x00000008
ULONG RecchkKdPrintVector = RECCHK_KDP_BADERRORS;
#else
#define RecchkKdPrint(__bit,__x) ;
#endif
#define ValidShadowID(ulidShadow) ((ulidShadow & ~0x80000000) >=ULID_FIRST_USER_DIR)
char vszTemp[] = "csc0.tmp";
char vszTemp1[] = "csc1.tmp";
AssertData;
AssertError;
RebuildPQInRBA(
LPRBA lpRBA
);
BOOL
TraverseDirectory(
LPVOID lpdbID,
unsigned ulidShare,
unsigned ulidParent,
unsigned ulidDir,
LPRBA lpRBAPQ,
BOOL fFix
);
BOOL
AllocateRBA(
DWORD cntRBE, // count of record buffer entries
DWORD cbRBE, // size of each record buffer entry
LPRBA *lplpRBA // result to be returned
);
VOID
FreeRBA(
LPRBA lpRBA
);
BOOL
ReadShadowInRBA(
LPVOID lpdbID,
unsigned ulidShadow,
DWORD cbMaxRBE, // max size of an RBE
DWORD cntRBE, // # of RBEs to be allocated, calculated if 0
LPRBA *lplpRBA
);
BOOL
WriteRBA(
LPVOID lpdbID,
LPRBA lpRBA,
LPSTR lpszFileName
);
LPVOID
GetRecordPointerFromRBA(
LPRBA lpRBA,
unsigned ulRec
);
BOOL
ReadRecordFromRBA(
LPRBA lpRBA,
unsigned ulRec,
LPGENERICREC lpGH
);
BOOL
WriteRecordToRBA(
LPRBA lpRBA,
unsigned ulRec,
LPGENERICREC lpGH,
BOOL fOverwrite,
LPDWORD lpdwError
);
BOOL
FillupRBAUptoThisRBE(
LPRBA lpRBA,
DWORD indxRBE
);
VOID
InitializeRBE(
LPRBA lpRBA,
DWORD indxRBE
);
BOOL
InsertRBAPQEntryFile(
LPRBA lpRBAPQ,
LPQREC lpPQDst,
unsigned ulrecDst
);
BOOL
InsertRBAPQEntryDir(
LPRBA lpRBAPQ,
LPQREC lpPQDst,
unsigned ulrecDst
);
BOOL
ValidateQrecFromFilerec(
unsigned ulidShare,
unsigned ulidDir,
LPFILERECEXT lpFR,
LPQREC lpQR,
unsigned ulrecDirEntry
);
BOOL
TraversePQ(
LPVOID lpdbID
)
/*++
Routine Description:
This routine traverses the priority Q and verifies the consistency of the Q by verifying
that the backward and the forward pointers are pointing correctly
Parameters:
lpdbID CSC database directory
Return Value:
Notes:
--*/
{
QREC sQR, sPrev, sNext;
unsigned ulRec;
BOOL fRet = FALSE, fValidHead=FALSE, fValidTail=FALSE;
LPRBA lpRBA = NULL;
if (!ReadShadowInRBA(lpdbID, ULID_PQ, MAX_RECBUFF_ENTRY_SIZE, 0, &lpRBA))
{
RecchkKdPrint(BADERRORS, ("TraversePQ: Failed to read PQ in memory\r\n"));
goto bailout;
}
if ((((LPQHEADER)&(lpRBA->sGH))->ulrecTail > lpRBA->sGH.ulRecords) ||
(((LPQHEADER)&(lpRBA->sGH))->ulrecHead > lpRBA->sGH.ulRecords))
{
RecchkKdPrint(BADERRORS, ("Invalid head-tail pointers\r\n"));
goto bailout;
}
if (!lpRBA->sGH.ulRecords)
{
fRet = TRUE;
goto bailout;
}
for (ulRec = 1; ulRec <= lpRBA->sGH.ulRecords; ulRec++)
{
if(!ReadRecordFromRBA(lpRBA, ulRec, (LPGENERICREC)&sQR))
{
goto bailout;
}
if (sQR.uchType == REC_DATA)
{
if (sQR.ulrecNext)
{
if (sQR.ulrecNext > lpRBA->sGH.ulRecords)
{
RecchkKdPrint(BADERRORS, ("Invalid next pointer to %d\r\n", ulRec));
goto bailout;
}
if (!ReadRecordFromRBA(lpRBA, sQR.ulrecNext, (LPGENERICREC)&sNext))
{
goto bailout;
}
if (sNext.ulrecPrev != ulRec)
{
RecchkKdPrint(BADERRORS, ("Prev pointer of %d doesn't equal %d\r\n", sNext.ulrecPrev, ulRec));
goto bailout;
}
}
else
{
if (((LPQHEADER)&(lpRBA->sGH))->ulrecTail != ulRec)
{
RecchkKdPrint(BADERRORS, ("Invalid tail pointer to %d\r\n", ulRec));
goto bailout;
}
fValidTail = TRUE;
}
if (sQR.ulrecPrev)
{
if (sQR.ulrecPrev > lpRBA->sGH.ulRecords)
{
RecchkKdPrint(BADERRORS, ("Invalid prev pointer to %d\r\n", ulRec));
goto bailout;
}
if (!ReadRecordFromRBA(lpRBA, sQR.ulrecPrev, (LPGENERICREC)&sPrev))
{
goto bailout;
}
if (sPrev.ulrecNext != ulRec)
{
RecchkKdPrint(BADERRORS, ("Next pointer of %d doesn't equal %d\r\n", sPrev.ulrecNext, ulRec));
goto bailout;
}
}
else
{
if (((LPQHEADER)&(lpRBA->sGH))->ulrecHead != ulRec)
{
RecchkKdPrint(BADERRORS, ("Invalid Head pointer to %d\r\n", ulRec));
goto bailout;
}
fValidHead = TRUE;
}
}
}
if (!fValidHead || !fValidTail)
{
RecchkKdPrint(BADERRORS, ("Head or Tail invalid \r\n"));
goto bailout;
}
fRet = TRUE;
bailout:
if (lpRBA)
{
FreeRBA(lpRBA);
}
return (fRet);
}
BOOL
RebuildPQ(
LPVOID lpdbID
)
/*++
Routine Description:
Parameters:
Return Value:
Notes:
--*/
{
LPRBA lpRBA = NULL;
BOOL fRet = FALSE;
RecchkKdPrint(PQ, ("RebuildPQ: reading PQ \r\n"));
if (!ReadShadowInRBA(lpdbID, ULID_PQ, MAX_RECBUFF_ENTRY_SIZE, 0, &lpRBA))
{
RecchkKdPrint(BADERRORS, ("TraversePQ: Failed to read PQ in memory\r\n"));
goto bailout;
}
RecchkKdPrint(PQ, ("RebuildPQ: read PQ \r\n"));
if (!RebuildPQInRBA(lpRBA))
{
RecchkKdPrint(BADERRORS, ("RebuildPQ: failed to rebuild PQ in RBA \r\n"));
goto bailout;
}
RecchkKdPrint(PQ, ("RebuildPQ: writing PQ \r\n"));
if (!WriteRBA(lpdbID, lpRBA, NULL))
{
RecchkKdPrint(BADERRORS, ("RebuildPQ:Failed to writeout the PQ\r\n"));
goto bailout;
}
RecchkKdPrint(PQ, ("RebuildPQ: wrote PQ \r\n"));
fRet = TRUE;
bailout:
if (lpRBA)
{
FreeRBA(lpRBA);
}
return (fRet);
}
BOOL
RebuildPQInRBA(
LPRBA lpRBA
)
/*++
Routine Description:
Parameters:
Return Value:
Notes:
--*/
{
unsigned ulRec;
LPQHEADER lpQH;
LPQREC lpPQ;
BOOL fRet = FALSE;
lpQH = (LPQHEADER)&(lpRBA->sGH);
// nuke the PQ
lpQH->ulrecHead = lpQH->ulrecTail = 0;
for (ulRec = 1; ulRec <= lpRBA->sGH.ulRecords; ulRec++)
{
if (!(lpPQ = GetRecordPointerFromRBA(lpRBA, ulRec)))
{
RecchkKdPrint(BADERRORS, ("InsertRBAPQEntry: failed reading q entry at %d\r\n", ulRec));
goto bailout;
}
if (lpPQ->uchType != REC_DATA)
{
continue;
}
if (!(lpPQ->ulidShadow & 0x80000000))
{
if (!InsertRBAPQEntryDir(lpRBA, lpPQ, ulRec))
{
RecchkKdPrint(BADERRORS, ("RebuildPQ:Failed inserting %d \r\n", ulRec));
goto bailout;
}
}
else
{
if (!InsertRBAPQEntryFile(lpRBA, lpPQ, ulRec))
{
RecchkKdPrint(BADERRORS, ("RebuildPQ:Failed inserting %d \r\n", ulRec));
goto bailout;
}
}
}
fRet = TRUE;
bailout:
return fRet;
}
BOOL
TraverseHierarchy(
LPVOID lpdbID,
BOOL fFix
)
/*++
Routine Description:
Parameters:
Return Value:
Notes:
--*/
{
unsigned ulRec;
BOOL fRet = FALSE;
LPRBA lpRBA = NULL, lpRBAPQ=NULL;
SHAREREC sSR;
QREC sQR;
BOOL fErrors = FALSE;
DWORD dwError;
if (!ReadShadowInRBA(lpdbID, ULID_SHARE, MAX_RECBUFF_ENTRY_SIZE, 0, &lpRBA))
{
RecchkKdPrint(BADERRORS, ("TraverseHierarchy: Failed to read servers in memory\r\n"));
goto bailout;
}
if (!fFix)
{
if (!ReadShadowInRBA( lpdbID,
ULID_PQ,
MAX_RECBUFF_ENTRY_SIZE,
0,
&lpRBAPQ))
{
RecchkKdPrint(BADERRORS, ("TraverseHierarchy: Failed to read PQ in memory\r\n"));
goto bailout;
}
}
else
{
ULONG cbCountOfTotal= ((LPSHAREHEADER)&(lpRBA->sGH))->sCur.ucntDirs+((LPSHAREHEADER)&(lpRBA->sGH))->sCur.ucntFiles;
ULONG cbMaxEntriesExpected,cbMaxRbesExpected;
cbMaxEntriesExpected = (MAX_RECBUFF_ENTRY_SIZE * MAX_RBES_EXPECTED)/sizeof(QREC);
RecchkKdPrint(BADERRORS, ("TraverseHierarchy: total count=%d\r\n",cbCountOfTotal));
if (cbCountOfTotal >= cbMaxEntriesExpected)
{
fRet = TRUE;
RecchkKdPrint(BADERRORS, ("TraverseHierarchy: Database too big skipping autocheck\r\n"));
goto bailout;
// cbMaxRbesExpected = (cbCountOfTotal*sizeof(QREC)/MAX_RECBUFF_ENTRY_SIZE)+1;
}
else
{
cbMaxRbesExpected = MAX_RBES_EXPECTED;
}
RecchkKdPrint(BADERRORS, ("TraverseHierarchy: MaxRBEs = %d\r\n",cbMaxRbesExpected));
if (!AllocateRBA(cbMaxRbesExpected, MAX_RECBUFF_ENTRY_SIZE, &lpRBAPQ))
{
RecchkKdPrint(BADERRORS, ("TraverseHierarchy: Failed to Allocate PQ\r\n"));
goto bailout;
}
InitQHeader((LPQHEADER)&(lpRBAPQ->sGH));
lpRBAPQ->ulidShadow = ULID_PQ;
lpRBAPQ->cntRecsPerRBE = MAX_RECBUFF_ENTRY_SIZE/lpRBAPQ->sGH.uRecSize;
}
for (ulRec=1; ulRec<=lpRBA->sGH.ulRecords; ++ulRec)
{
ReadRecordFromRBA(lpRBA, ulRec, (LPGENERICREC)&sSR);
if (sSR.uchType != REC_DATA)
{
continue;
}
if(!ValidShadowID(sSR.ulidShadow))
{
fErrors = TRUE;
sSR.uchType = REC_EMPTY;
RecchkKdPrint(BADERRORS, ("Invalid Shadow ID %xh found in %xh \r\n", sSR.ulidShadow, sSR.ulShare));
if (fFix)
{
if (!WriteRecordToRBA(lpRBA, ulRec, (LPGENERICREC)&sSR, TRUE, NULL))
{
RecchkKdPrint(BADERRORS, ("Couldn't write entry for Share Record %xh \r\n", sSR.ulShare));
}
}
continue;
}
if (!fFix)
{
if (!ReadRecordFromRBA(lpRBAPQ, RecFromInode(sSR.ulidShadow), (LPGENERICREC)&sQR))
{
RecchkKdPrint(BADERRORS, ("No PQ entry for Inode %xh \r\n", sSR.ulidShadow));
}
}
else
{
InitPriQRec(ulRec, 0, sSR.ulidShadow, SHADOW_SPARSE, 0, 0, 0, 0, ulRec, &sQR);
if (!WriteRecordToRBA(lpRBAPQ, RecFromInode(sSR.ulidShadow), (LPGENERICREC)&sQR, FALSE, &dwError))
{
if (dwError == ERROR_NOT_ENOUGH_MEMORY)
{
RecchkKdPrint(BADERRORS, ("Couldn't write PQ entry for Inode %xh \r\n", sSR.ulidShadow));
}
fErrors = TRUE;
sSR.uchType = REC_EMPTY;
WriteRecordToRBA(lpRBA, ulRec, (LPGENERICREC)&sSR, TRUE, NULL);
continue;
}
}
if(!TraverseDirectory( lpdbID,
ulRec, // ulidShare
0, // parent inode
sSR.ulidShadow, // dir inode
lpRBAPQ,
fFix
))
{
goto bailout;
}
}
if (fFix)
{
if (fErrors)
{
if (!WriteRBA(lpdbID, lpRBA, NULL))
{
RecchkKdPrint(BADERRORS, ("TraverseHierarchy:Failed to write Shares\r\n"));
goto bailout;
}
}
RecchkKdPrint(TRAVERSE, ("Total records %d \r\n", lpRBAPQ->sGH.ulRecords));
if (lpRBAPQ->ulErrorFlags & RBA_ERROR_LIMIT_EXCEEDED)
{
RecchkKdPrint(BADERRORS, ("TraverseHierarchy: skipping rewriting of new PQ\r\n"));
}
else
{
if (!RebuildPQInRBA(lpRBAPQ))
{
RecchkKdPrint(BADERRORS, ("TraverseHierarchy:Failed to rebuild PQ\r\n"));
goto bailout;
}
if (!WriteRBA(lpdbID, lpRBAPQ, NULL))
{
RecchkKdPrint(BADERRORS, ("TraverseHierarchy:Failed to write PQ\r\n"));
goto bailout;
}
}
}
fRet = TRUE;
bailout:
if (lpRBA)
{
FreeRBA(lpRBA);
}
if (lpRBAPQ)
{
FreeRBA(lpRBAPQ);
}
return fRet;
}
BOOL
TraverseDirectory(
LPVOID lpdbID,
unsigned ulidShare,
unsigned ulidParent,
unsigned ulidDir,
LPRBA lpRBAPQ,
BOOL fFix
)
/*++
Routine Description:
Parameters:
Return Value:
Notes:
--*/
{
unsigned ulDepthLevel = 0, ulidCurParent, ulidCurDir;
BOOL fRet = FALSE, fGoDeeper = TRUE;
FILERECEXT *lpFR = NULL;
QREC *lpQR = NULL;
LPCSE lpcseNextDir = NULL;
LPCSE lpcseHead = NULL, lpcseT;
BOOL fErrors = FALSE;
DWORD dwError;
lpFR = AllocMemPaged(sizeof(FILERECEXT));
lpQR = AllocMemPaged(sizeof(QREC));
if (!lpFR || !lpQR)
{
RecchkKdPrint(BADERRORS, ("AllocMemPaged Failed \r\n"));
goto bailout;
}
ulidCurParent = ulidParent;
ulidCurDir = ulidDir;
for (;;)
{
if (fGoDeeper)
{
// we are going deeper
// allocate a stack entry for the directory which we want
// to traverse
lpcseT = AllocMemPaged(sizeof(CSE));
if (!lpcseT)
{
RecchkKdPrint(BADERRORS, ("AllocMemPaged failed \r\n"));
goto bailout;
}
// do appropriate inits
lpcseT->ulidShare = ulidShare;
lpcseT->ulidParent = ulidCurParent;
lpcseT->ulidDir = ulidCurDir;
lpcseT->ulRec = 1; // start for record # 1
lpcseT->lpcseNext = NULL;
// read the entire directory in memory
if (!ReadShadowInRBA(lpdbID, ulidCurDir, MAX_RECBUFF_ENTRY_SIZE, 0, &(lpcseT->lpRBA)))
{
RecchkKdPrint(BADERRORS, ("TraverseDirectory: Failed to read directory in memory\r\n"));
if (!fFix)
{
RecchkKdPrint(BADERRORS, ("TraverseDirectory: Aborting\r\n"));
FreeMemPaged(lpcseT);
goto bailout;
}
else
{
RecchkKdPrint(TRAVERSE, ("TraverseDirectory: attempting to heal\r\n"));
if(CreateDirInode(lpdbID, ulidShare, ulidCurParent, ulidCurDir) < 0)
{
RecchkKdPrint(BADERRORS, ("TraverseDirectory: failed to heal\r\n"));
}
FreeMemPaged(lpcseT);
fGoDeeper = FALSE;
// continue if there are more things to do
// else stop
if (lpcseHead)
{
continue;
}
else
{
break;
}
}
}
// put it at the head of the queue
lpcseT->lpcseNext = lpcseHead;
lpcseHead = lpcseT;
ulDepthLevel++;
}
fGoDeeper = FALSE;
// we always operate on the head of the list
Assert(lpcseHead != NULL);
RecchkKdPrint(TRAVERSE, ("Processing %x at depth %d\r\n", ulidCurDir, ulDepthLevel));
RecchkKdPrint(TRAVERSE, ("lpcseHead = %x, lpcseHead->lpcseNext = %x \r\n", lpcseHead, lpcseHead->lpcseNext));
for (; lpcseHead->ulRec<=lpcseHead->lpRBA->sGH.ulRecords;)
{
ReadRecordFromRBA(lpcseHead->lpRBA, lpcseHead->ulRec, (LPGENERICREC)lpFR);
if (lpFR->sFR.uchType == REC_DATA)
{
if(!ValidShadowID(lpFR->sFR.ulidShadow))
{
RecchkKdPrint(BADERRORS, ("Invalid Shadow ID %xh found in %xh \r\n", lpFR->sFR.ulidShadow, ulidCurDir));
lpcseHead->lpRBA->ulErrorFlags |= RBA_ERROR_INVALID_INODE;
if (fFix)
{
lpFR->sFR.uchType = REC_EMPTY;
if (!WriteRecordToRBA(lpcseHead->lpRBA, lpcseHead->ulRec, (LPGENERICREC)lpFR, TRUE, NULL))
{
RecchkKdPrint(BADERRORS, ("Couldn't write entry for dir Record #%dh in dir %xh\r\n", lpcseHead->ulRec, ulidCurDir));
}
}
}
else
{
if (!fFix)
{
ReadRecordFromRBA(lpRBAPQ, RecFromInode(lpFR->sFR.ulidShadow), (LPGENERICREC)lpQR);
if (!ValidateQrecFromFilerec(lpcseHead->ulidShare, lpcseHead->ulidDir, lpFR, lpQR, lpcseHead->ulRec))
{
RecchkKdPrint(BADERRORS, ("PQ entry for Inode %xh in directory=%xh doesn't match with filerec\r\n", lpFR->sFR.ulidShadow, lpcseHead->lpRBA->ulidShadow));
}
}
else
{
InitPriQRec(lpcseHead->ulidShare,
lpcseHead->ulidDir,
lpFR->sFR.ulidShadow,
lpFR->sFR.usStatus,
lpFR->sFR.uchRefPri,
lpFR->sFR.uchIHPri,
lpFR->sFR.uchHintPri,
lpFR->sFR.uchHintFlags,
lpcseHead->ulRec,
lpQR);
if (!WriteRecordToRBA(lpRBAPQ, RecFromInode(lpFR->sFR.ulidShadow), (LPGENERICREC)lpQR, FALSE, &dwError))
{
if (dwError == ERROR_NOT_ENOUGH_MEMORY)
{
RecchkKdPrint(BADERRORS, ("Couldn't write PQ entry for Inode %xh \r\n", lpFR->sFR.ulidShadow));
}
lpFR->sFR.uchType = REC_EMPTY;
lpcseHead->lpRBA->ulErrorFlags |= RBA_ERROR_INVALID_INODE;
WriteRecordToRBA(lpcseHead->lpRBA, lpcseHead->ulRec, (LPGENERICREC)lpFR, TRUE, NULL);
// go around one more time, when this entry will get skipped
continue;
}
}
}
}
// point to the next record
lpcseHead->ulRec += (OvfCount(lpFR)+1);
if ((lpFR->sFR.uchType == REC_DATA) && !(lpFR->sFR.ulidShadow & 0x80000000))
{
ulidCurParent = ulidCurDir;
ulidCurDir = lpFR->sFR.ulidShadow;
fGoDeeper = TRUE;
break;
}
}
if (fGoDeeper)
{
continue;
}
else
{
// we completed processing a directory
Assert(fGoDeeper == FALSE);
Assert(lpcseHead);
RecchkKdPrint(TRAVERSE, ("Unwinding \r\n"));
if (fFix && lpcseHead->lpRBA->ulErrorFlags)
{
if (!WriteRBA(lpdbID, lpcseHead->lpRBA, NULL))
{
RecchkKdPrint(BADERRORS, ("Cannot fix errors on %xh \n\r", lpcseHead->lpRBA->ulidShadow));
}
}
// processing of a directory is complete, unwind the stack
lpcseT = lpcseHead;
lpcseHead = lpcseHead->lpcseNext;
FreeRBA(lpcseT->lpRBA);
FreeMemPaged(lpcseT);
if (!lpcseHead)
{
break;
}
ulidCurDir = lpcseHead->ulidDir;
ulidCurParent = lpcseHead->ulidParent;
}
}
fRet = TRUE;
bailout:
if (lpFR)
{
FreeMemPaged(lpFR);
}
if (lpQR)
{
FreeMemPaged(lpQR);
}
Assert(!(fRet && lpcseHead));
for (;lpcseHead;)
{
lpcseT = lpcseHead;
lpcseHead = lpcseHead->lpcseNext;
FreeRBA(lpcseT->lpRBA);
FreeMemPaged(lpcseT);
}
return (fRet);
}
BOOL
AllocateRBA(
DWORD cntRBE, // count of record buffer entries
DWORD cbRBE, // size of each record buffer entry
LPRBA *lplpRBA // result to be returned
)
/*++
Routine Description:
Parameters:
Return Value:
Notes:
--*/
{
LPRBA lpRBA = NULL;
DWORD i;
lpRBA = (LPRBA)AllocMemPaged(sizeof(RBA)+sizeof(LPBYTE)*cntRBE);
if (lpRBA != NULL)
{
// initialize the guy
lpRBA->cntRBE = cntRBE; // count of record buffer entries in rgRBE
lpRBA->cbRBE = cbRBE; // size in bytes of each RBE buffer
}
else
{
RecchkKdPrint(BADERRORS, ("Failed memory allocation while getting RBA\r\n"));
}
if (lpRBA)
{
*lplpRBA = lpRBA;
return (TRUE);
}
return FALSE;
}
VOID
FreeRBA(
LPRBA lpRBA
)
/*++
Routine Description:
Parameters:
Return Value:
Notes:
--*/
{
DWORD i;
RecchkKdPrint(RBA, ("FreeRBA:cntRBE=%d cbRBE=%d lpRBA=%xh\r\n", lpRBA->cntRBE, lpRBA->cbRBE, lpRBA));
for (i=0; i<lpRBA->cntRBE; ++i)
{
if (lpRBA->rgRBE[i])
{
FreeMemPaged(lpRBA->rgRBE[i]);
}
}
if (lpRBA->hf)
{
CloseFileLocal(lpRBA->hf);
}
FreeMemPaged(lpRBA);
}
BOOL
ReadShadowInRBA(
LPVOID lpdbID,
unsigned ulidShadow,
DWORD cbMaxRBEIn, // max size in bytes of an RBE
DWORD cntRBEIn, // # of RBEs in this RBA, calculated if 0
LPRBA *lplpRBA
)
/*++
Routine Description:
Parameters:
Return Value:
Notes:
--*/
{
LPSTR lpszName = NULL;
BOOL fRet = FALSE;
DWORD dwFileSize, cntRBE, cntRecsPerRBE, cbRBE, i;
unsigned ulRecords, ulPos, ulErrorFlags = 0;
CSCHFILE hf = CSCHFILE_NULL;
GENERICHEADER sGH;
LPRBA lpRBA=NULL;
if (lpszName = FormNameString(lpdbID, ulidShadow))
{
hf = OpenFileLocal(lpszName);
if (hf)
{
if ((GetFileSizeLocal(hf, &dwFileSize))==0xffffffff)
{
RecchkKdPrint(BADERRORS, ("Failed to get filesize for %s\r\n", lpszName));
goto bailout;
}
if (ReadHeader(hf, &sGH, sizeof(sGH))< 0)
{
RecchkKdPrint(BADERRORS, ("Failed to read header for %s\r\n", lpszName));
goto bailout;
}
ulRecords = (dwFileSize-sGH.lFirstRec)/sGH.uRecSize;
if (sGH.ulRecords != ulRecords)
{
RecchkKdPrint(BADERRORS, ("Count of total records inconsistent with the file size header=%d expected=%d\r\n",
sGH.ulRecords,
ulRecords
));
ulErrorFlags |= RAB_ERROR_INVALID_RECORD_COUNT;
}
if (sGH.ulRecords > ulRecords)
{
sGH.ulRecords = ulRecords;
}
// integral # of records per RBE
cntRecsPerRBE = cbMaxRBEIn/sGH.uRecSize;
// corresponding size of memory allocation per RBE
cbRBE = cntRecsPerRBE * sGH.uRecSize;
if (!cntRBEIn)
{
// total count of RBEs. Add 1 to take care of partial RBE at the end
cntRBE = sGH.ulRecords/cntRecsPerRBE + 1;
}
else
{
cntRBE = cntRBEIn;
}
if (!AllocateRBA(cntRBE, cbRBE, &lpRBA))
{
RecchkKdPrint(BADERRORS, ("Failed allocation of recbuff array of %d entries for %s\r\n", cntRBE, lpszName));
goto bailout;
}
ulPos = sGH.lFirstRec;
for (i=0; i<cntRBE; ++i)
{
int iRet;
Assert(!lpRBA->rgRBE[i]);
lpRBA->rgRBE[i] = (LPBYTE)AllocMemPaged(cbRBE);
if (!lpRBA->rgRBE[i])
{
RecchkKdPrint(BADERRORS, ("Error allocating RBE for Inode file %s \r\n", lpszName));
goto bailout;
}
iRet = ReadFileLocalEx2(hf, ulPos, lpRBA->rgRBE[i], cbRBE, FLAG_RW_OSLAYER_PAGED_BUFFER);
if (iRet < 0)
{
RecchkKdPrint(BADERRORS, ("Error reading Inode file %s \r\n", lpszName));
goto bailout;
}
if (iRet < (int)cbRBE)
{
break;
}
ulPos += cbRBE;
}
// initialize the guy
lpRBA->ulidShadow = ulidShadow; // Inode
lpRBA->sGH = sGH; // Inode file header
lpRBA->hf = hf; // file handle
lpRBA->cntRBE = cntRBE; // count of record buffer entries in rgRBE
lpRBA->cntRecsPerRBE = cntRecsPerRBE; // count of records in each RBE buffer
lpRBA->cbRBE = cbRBE; // size in bytes of each RBE buffer
lpRBA->ulErrorFlags = ulErrorFlags; // errors found so far
*lplpRBA = lpRBA;
fRet = TRUE;
}
else
{
RecchkKdPrint(BADERRORS, ("Failed to open %s \r\n", lpszName));
}
}
else
{
RecchkKdPrint(BADERRORS, ("Failed memory allocation\r\n"));
}
bailout:
if (lpszName)
{
FreeNameString(lpszName);
}
if (hf)
{
CloseFileLocal(hf);
if (lpRBA)
{
lpRBA->hf = CSCHFILE_NULL;
}
}
if (!fRet)
{
if (lpRBA)
{
FreeRBA(lpRBA);
}
}
return (fRet);
}
BOOL
WriteRBA(
LPVOID lpdbID,
LPRBA lpRBA,
LPSTR lpszFileName
)
/*++
Routine Description:
Parameters:
Return Value:
Notes:
--*/
{
CSCHFILE hf = CSCHFILE_NULL;
BOOL fRet = FALSE;
LPSTR lpszName = NULL, lpszTempName = NULL, lpszTempName1 = NULL;
DWORD i, cntRecsInLastRBE, cbLastRBE, cntRBEReal;
unsigned long ulPos, ulT;
if (!lpszFileName)
{
lpszName = FormNameString(lpdbID, lpRBA->ulidShadow);
if (!lpszName)
{
RecchkKdPrint(BADERRORS, ("Failed to allocate memory\r\n"));
goto bailout;
}
}
else
{
lpszName = lpszFileName;
}
// create tempfilel names
lpszTempName = AllocMemPaged(strlen((LPSTR)lpdbID) + strlen(vszTemp) + 4);
if (!lpszTempName)
{
RecchkKdPrint(BADERRORS, ("Failed to allocate memory\r\n"));
goto bailout;
}
strcpy(lpszTempName, (LPSTR)lpdbID);
strcat(lpszTempName, "\\");
strcat(lpszTempName, vszTemp);
lpszTempName1 = AllocMemPaged(strlen((LPSTR)lpdbID) + strlen(vszTemp1) + 4);
if (!lpszTempName1)
{
RecchkKdPrint(BADERRORS, ("Failed to allocate memory\r\n"));
goto bailout;
}
strcpy(lpszTempName1, (LPSTR)lpdbID);
strcat(lpszTempName1, "\\");
strcat(lpszTempName1, vszTemp1);
hf = R0OpenFileEx(ACCESS_READWRITE, ACTION_CREATEALWAYS, FILE_ATTRIBUTE_SYSTEM, lpszTempName, FALSE);
if (!hf)
{
RecchkKdPrint(BADERRORS, ("Failed to open %s\r\n", lpszTempName));
goto bailout;
}
// this is the real # of RBEs, there might be empty ones
// after this
cntRBEReal = lpRBA->sGH.ulRecords / lpRBA->cntRecsPerRBE;
RecchkKdPrint(RBA, ("Writing %s\r\n", lpszTempName));
// is there a partial RBE at the end?
if (lpRBA->sGH.ulRecords % lpRBA->cntRecsPerRBE)
{
// yes, bump up the count of RBEs to write and caclulate the
// # of bytes
cntRBEReal++;
cntRecsInLastRBE = lpRBA->sGH.ulRecords - (cntRBEReal - 1) * lpRBA->cntRecsPerRBE;
cbLastRBE = cntRecsInLastRBE * lpRBA->sGH.uRecSize;
}
else
{
// records exactly fit in the last RBE.
// so the stats for the last RBE are trivial
cntRecsInLastRBE = lpRBA->cntRecsPerRBE;
cbLastRBE = lpRBA->cbRBE;
}
RecchkKdPrint(RBA, ("%d RBEs, %d bytes in last RBE\r\n", cntRBEReal, cbLastRBE));
Assert(cntRBEReal <= lpRBA->cntRBE);
if(WriteFileLocalEx2(hf, 0, &(lpRBA->sGH), sizeof(lpRBA->sGH), FLAG_RW_OSLAYER_PAGED_BUFFER)!=((int)sizeof(lpRBA->sGH)))
{
RecchkKdPrint(BADERRORS, ("Failed writing header \r\n"));
goto bailout;
}
ulPos = lpRBA->sGH.lFirstRec;
for (i=0; i<cntRBEReal; ++i)
{
DWORD dwSize;
// if last RBE, write the residual size calculated above
dwSize = (((i+1)==cntRBEReal)?cbLastRBE:lpRBA->cbRBE);
// there must be a corresponding RBE
Assert(lpRBA->rgRBE[i]);
if(WriteFileLocalEx2(hf, ulPos, lpRBA->rgRBE[i], dwSize, FLAG_RW_OSLAYER_PAGED_BUFFER)!=(int)dwSize)
{
RecchkKdPrint(BADERRORS, ("Error writing file\r\n"));
goto bailout;
}
ulPos += dwSize;
}
CloseFileLocal(hf);
hf = CSCHFILE_NULL;
if((GetAttributesLocal(lpszTempName1, &ulT)>=0)
&& (DeleteFileLocal(lpszTempName1, ATTRIB_DEL_ANY) < 0))
{
RecchkKdPrint(BADERRORS, ("WriteRBA: failed to delete temp file %s\r\n", lpszTempName1));
goto bailout;
}
if(RenameFileLocal(lpszName, lpszTempName1) < 0)
{
RecchkKdPrint(BADERRORS, ("WriteRBA: failed to rename original %s to temp file %s\r\n", lpszName, lpszTempName1));
goto bailout;
}
if(RenameFileLocal(lpszTempName, lpszName) < 0)
{
RecchkKdPrint(BADERRORS, ("WriteRBA: failed to rename new file %s to the original %s\r\n", lpszTempName, lpszName));
if(RenameFileLocal(lpszTempName1, lpszTempName) < 0)
{
RecchkKdPrint(BADERRORS, ("WriteRBA: failed to rename back %s to the original %s\r\n", lpszTempName1, lpszName));
Assert(FALSE);
}
goto bailout;
}
fRet = TRUE;
bailout:
if (hf)
{
CloseFileLocal(hf);
}
// if a name wasn't sent in, we must have allocated it
if (!lpszFileName)
{
FreeNameString(lpszName);
}
if (lpszTempName)
{
FreeMemPaged(lpszTempName);
}
if (lpszTempName1)
{
FreeMemPaged(lpszTempName1);
}
return (fRet);
}
LPVOID
GetRecordPointerFromRBA(
LPRBA lpRBA,
unsigned ulRec
)
/*++
Routine Description:
Parameters:
Return Value:
Notes:
--*/
{
DWORD indxRec, indxRBE;
if (lpRBA->sGH.ulRecords < ulRec)
{
RecchkKdPrint(BADERRORS, ("GetRecordPointerFromRBA: invalid rec passed in lpRBA->ulidShadow=%xh lpRBA->sGH.ulRecords=%xh ulRec=%xh\r\n",
lpRBA->ulidShadow, lpRBA->sGH.ulRecords, ulRec));
return NULL;
}
indxRBE = (ulRec-1)/lpRBA->cntRecsPerRBE;
indxRec = (ulRec-1)%lpRBA->cntRecsPerRBE;
Assert(lpRBA->rgRBE[indxRBE]);
return ((lpRBA->rgRBE[indxRBE])+indxRec*lpRBA->sGH.uRecSize);
}
BOOL
ReadRecordFromRBA(
LPRBA lpRBA,
unsigned ulRec,
LPGENERICREC lpGR
)
/*++
Routine Description:
Parameters:
Return Value:
Notes:
--*/
{
DWORD indxRec, indxRBE, cntOvf, i;
char uchOvfType;
LPGENERICREC lpGRT;
if(lpRBA->sGH.ulRecords < ulRec)
{
// this must have been fixed when we read the file in
// only in case of priority Q, where the records point
// to each other is it possible that this could happen
Assert(lpRBA->ulidShadow == ULID_PQ);
}
indxRBE = (ulRec-1)/lpRBA->cntRecsPerRBE;
indxRec = (ulRec-1)%lpRBA->cntRecsPerRBE;
Assert(lpRBA->rgRBE[indxRBE]);
lpGRT = (LPGENERICREC)((lpRBA->rgRBE[indxRBE])+indxRec*lpRBA->sGH.uRecSize);
memcpy(lpGR, (lpRBA->rgRBE[indxRBE])+indxRec*lpRBA->sGH.uRecSize, lpRBA->sGH.uRecSize);
if ((lpGR->uchType == REC_DATA)||(lpGR->uchType == REC_EMPTY))
{
cntOvf = (DWORD)OvfCount(lpGR);
uchOvfType = (lpGR->uchType == REC_DATA)?REC_OVERFLOW:REC_EMPTY;
if (cntOvf > MAX_OVERFLOW_RECORDS)
{
lpRBA->ulErrorFlags |= RBA_ERROR_INVALID_OVF;
SetOvfCount(lpGR, MAX_OVERFLOW_RECORDS);
}
if (cntOvf)
{
for (i=1; i<=cntOvf; ++i)
{
indxRBE = (ulRec+i-1)/lpRBA->cntRecsPerRBE;
indxRec = (ulRec+i-1)%lpRBA->cntRecsPerRBE;
memcpy(((LPBYTE)lpGR)+i*lpRBA->sGH.uRecSize, (lpRBA->rgRBE[indxRBE])+indxRec*lpRBA->sGH.uRecSize, lpRBA->sGH.uRecSize);
if (((LPGENERICREC)(((LPBYTE)lpGR)+i*lpRBA->sGH.uRecSize))->uchType != uchOvfType)
{
lpRBA->ulErrorFlags |= RBA_ERROR_INVALID_OVF;
SetOvfCount(lpGR, (i-1));
}
}
}
}
else
{
lpGR->uchType = REC_EMPTY;
SetOvfCount(lpGR, 0);
lpGRT->uchType = REC_EMPTY;
SetOvfCount(lpGRT, 0);
lpRBA->ulErrorFlags |= RBA_ERROR_MISALIGNED_RECORD;
RecchkKdPrint(BADERRORS, ("ReadRecordFromRBA: misaligned record found \r\n"));
}
return (TRUE);
}
BOOL
WriteRecordToRBA(
LPRBA lpRBA,
unsigned ulRec,
LPGENERICREC lpGR,
BOOL fOverwrite,
LPDWORD lpdwError
)
/*++
Routine Description:
Parameters:
Return Value:
Notes:
--*/
{
DWORD indxRec, indxRBE, cntOvf, i, ulRecords;
LPGENERICREC lpGRT;
indxRBE = (ulRec-1)/lpRBA->cntRecsPerRBE;
indxRec = (ulRec-1)%lpRBA->cntRecsPerRBE;
if (indxRBE >= MAX_RBES_EXPECTED)
{
lpRBA->ulErrorFlags |= RBA_ERROR_LIMIT_EXCEEDED;
RecchkKdPrint(BADERRORS, ("WriteRecordToRBA: Limit of reached, for Inode %x, skipping\r\n", lpRBA->ulidShadow));
if (lpdwError)
{
*lpdwError = ERROR_BUFFER_OVERFLOW;
}
return FALSE;
}
if (!lpRBA->rgRBE[indxRBE])
{
if (!FillupRBAUptoThisRBE(lpRBA, indxRBE))
{
RecchkKdPrint(BADERRORS, ("WriteRecordToRBA: failed to fillup RBA\r\n"));
if (lpdwError)
{
*lpdwError = ERROR_NOT_ENOUGH_MEMORY;
}
return FALSE;
}
}
Assert(lpRBA->rgRBE[indxRBE]);
lpGRT = (LPGENERICREC)((lpRBA->rgRBE[indxRBE])+indxRec*lpRBA->sGH.uRecSize);
if (!fOverwrite && ((lpGRT->uchType == REC_DATA)||(lpGRT->uchType == REC_OVERFLOW)))
{
RecchkKdPrint(RBA, ("Not overwriting at ulrec=%d in RBA for Inode 0x%x", ulRec, lpRBA->ulidShadow));
if (lpdwError)
{
*lpdwError = ERROR_INVALID_PARAMETER;
}
return FALSE;
}
memcpy((lpRBA->rgRBE[indxRBE])+indxRec*lpRBA->sGH.uRecSize, lpGR, lpRBA->sGH.uRecSize);
cntOvf = (DWORD)OvfCount(lpGR);
if (cntOvf)
{
for (i=1; i<=cntOvf; ++i)
{
indxRBE = (ulRec+i-1)/lpRBA->cntRecsPerRBE;
indxRec = (ulRec+i-1)%lpRBA->cntRecsPerRBE;
if (!lpRBA->rgRBE[indxRBE])
{
RecchkKdPrint(RBA, ("Extending RBEs upto indx=%d \r\n", indxRBE));
if (!FillupRBAUptoThisRBE(lpRBA, indxRBE))
{
RecchkKdPrint(BADERRORS, ("WriteRecordToRBA: failed to fillup RBA\r\n"));
return FALSE;
}
}
memcpy( (lpRBA->rgRBE[indxRBE])+indxRec*lpRBA->sGH.uRecSize,
((LPBYTE)lpGR)+i*lpRBA->sGH.uRecSize,
lpRBA->sGH.uRecSize);
}
}
// reflect any addition in the count of records
// add up total records in all RBEs except the last one
// which might be partially filled, then add the index of the
// one we just filled in , then add one because the index is
// 0 based
ulRecords = lpRBA->cntRecsPerRBE * indxRBE
+ indxRec
+ 1;
if (ulRecords > lpRBA->sGH.ulRecords)
{
RecchkKdPrint(RBA, ("# of records got increased from %d to %d\r\n", lpRBA->sGH.ulRecords, ulRecords));
lpRBA->sGH.ulRecords = ulRecords;
}
return (TRUE);
}
BOOL
FillupRBAUptoThisRBE(
LPRBA lpRBA,
DWORD indxRBE
)
/*++
Routine Description:
Parameters:
Return Value:
Notes:
--*/
{
DWORD i;
for (i=0; i<= indxRBE; ++i)
{
if (!lpRBA->rgRBE[i])
{
lpRBA->rgRBE[i] = (LPBYTE)AllocMemPaged(lpRBA->cbRBE);
if (!lpRBA->rgRBE[i])
{
RecchkKdPrint(BADERRORS, ("FillupRBAUptoThisPoint:Failed memory allocation \r\n"));
return FALSE;
}
InitializeRBE(lpRBA, i);
}
}
return (TRUE);
}
VOID
InitializeRBE(
LPRBA lpRBA,
DWORD indxRBE
)
/*++
Routine Description:
Parameters:
Return Value:
Notes:
--*/
{
DWORD i;
LPBYTE lpT = lpRBA->rgRBE[indxRBE];
for (i=0; i< lpRBA->cntRecsPerRBE; ++i)
{
Assert(((LPGENERICREC)lpT)->uchType != REC_DATA);
((LPGENERICREC)lpT)->uchType = REC_EMPTY;
lpT += lpRBA->sGH.uRecSize;
}
}
BOOL
InsertRBAPQEntryFile(
LPRBA lpRBAPQ,
LPQREC lpPQDst,
unsigned ulrecDst
)
/*++
Routine Description:
Parameters:
Return Value:
Notes:
--*/
{
LPQREC lpPQCur, lpPQPred=NULL;
LPQHEADER lpQH = NULL;
unsigned ulrecCur, ulrecPred;
lpQH = (LPQHEADER)&(lpRBAPQ->sGH);
if (!lpQH->ulrecHead)
{
Assert(!lpQH->ulrecTail);
lpQH->ulrecHead = lpQH->ulrecTail = ulrecDst;
lpPQDst->ulrecNext = lpPQDst->ulrecPrev = 0;
}
else
{
for(ulrecCur = lpQH->ulrecHead, lpPQPred=NULL, ulrecPred=0;;)
{
if (!(lpPQCur = GetRecordPointerFromRBA(lpRBAPQ, ulrecCur)))
{
RecchkKdPrint(BADERRORS, ("InsertRBAPQEntry: failed getting q entry at %d\r\n", ulrecCur));
return FALSE;
}
// are we greater than or equal to the current one?
if (IComparePri(lpPQDst, lpPQCur) >= 0)
{
// yes, insert here
if (!lpPQPred)
{
// no predecessor, must be the head of the list
Assert(!lpPQCur->ulrecPrev);
// when we become the head, we got no prev
lpPQDst->ulrecPrev = 0;
// and the current head is our next
lpPQDst->ulrecNext = lpQH->ulrecHead;
// fix up the current heads prev to point to us
lpPQCur->ulrecPrev = ulrecDst;
// and fix the current head to point to us
lpQH->ulrecHead = ulrecDst;
}
else
{
// normal case, we go between lpPQPred and lpPQCur
Assert(ulrecPred);
// fix up the passed in guy first
lpPQDst->ulrecPrev = ulrecPred;
lpPQDst->ulrecNext = ulrecCur;
// now fix the predecessor's next and current guys prev to point to us
lpPQPred->ulrecNext = lpPQCur->ulrecPrev = ulrecDst;
}
break;
}
ulrecPred = ulrecCur;
ulrecCur = lpPQCur->ulrecNext;
if (!ulrecCur)
{
// Insert at the tail
lpPQDst->ulrecNext = 0;
lpPQDst->ulrecPrev = lpQH->ulrecTail;
lpPQCur->ulrecNext = ulrecDst;
lpQH->ulrecTail = ulrecDst;
break;
}
lpPQPred = lpPQCur;
}
}
return (TRUE);
}
BOOL
InsertRBAPQEntryDir(
LPRBA lpRBAPQ,
LPQREC lpPQDst,
unsigned ulrecDst
)
/*++
Routine Description:
Parameters:
Return Value:
Notes:
--*/
{
LPQREC lpPQCur, lpPQSucc=NULL;
LPQHEADER lpQH = NULL;
unsigned ulrecCur, ulrecSucc;
lpQH = (LPQHEADER)&(lpRBAPQ->sGH);
if (!lpQH->ulrecHead)
{
Assert(!lpQH->ulrecTail);
lpQH->ulrecHead = lpQH->ulrecTail = ulrecDst;
lpPQDst->ulrecNext = lpPQDst->ulrecPrev = 0;
}
else
{
for(ulrecCur = lpQH->ulrecTail, lpPQSucc=NULL, ulrecSucc=0;;)
{
if (!(lpPQCur = GetRecordPointerFromRBA(lpRBAPQ, ulrecCur)))
{
RecchkKdPrint(BADERRORS, ("InsertRBAPQEntry: failed getting q entry at %d\r\n", ulrecCur));
return FALSE;
}
// are we less than or equal to the current one?
if (IComparePri(lpPQDst, lpPQCur) <= 0)
{
// yes, insert here
if (!lpPQSucc)
{
// no Succecessor, must be the tail of the list
Assert(!lpPQCur->ulrecNext);
// when we become the tail, we got no next
lpPQDst->ulrecNext = 0;
// and the current tail is our prev
lpPQDst->ulrecPrev = lpQH->ulrecTail;
Assert(lpQH->ulrecTail == ulrecCur);
Assert(!lpPQCur->ulrecNext);
// fix up the current tails next to point to us
lpPQCur->ulrecNext = ulrecDst;
// and fix the current tail to point to us
lpQH->ulrecTail = ulrecDst;
}
else
{
// normal case, we go between lpPQCur and lpPQSucc
Assert(ulrecSucc);
// fix up the passed in guy first
lpPQDst->ulrecNext = ulrecSucc;
lpPQDst->ulrecPrev = ulrecCur;
// now fix the Succecessor's prev and current guys next to point to us
lpPQSucc->ulrecPrev = lpPQCur->ulrecNext = ulrecDst;
}
break;
}
ulrecSucc = ulrecCur;
ulrecCur = lpPQCur->ulrecPrev;
if (!ulrecCur)
{
// Insert at the head
lpPQDst->ulrecPrev = 0;
lpPQDst->ulrecNext = lpQH->ulrecHead;
lpPQCur->ulrecPrev = ulrecDst;
lpQH->ulrecHead = ulrecDst;
break;
}
lpPQSucc = lpPQCur;
}
}
return (TRUE);
}
BOOL
ValidateQrecFromFilerec(
unsigned ulidShare,
unsigned ulidDir,
LPFILERECEXT lpFR,
LPQREC lpQR,
unsigned ulrecDirEntry
)
/*++
Routine Description:
Parameters:
Return Value:
Notes:
--*/
{
if (lpQR->uchType != REC_DATA)
{
RecchkKdPrint(BADERRORS, ("Invalid Qrec type %c \r\n", lpQR->uchType));
return FALSE;
}
if ((lpQR->ulidShare != ulidShare)||
(lpQR->ulidDir != ulidDir)||
(lpQR->ulidShadow != lpFR->sFR.ulidShadow))
{
RecchkKdPrint(BADERRORS, ("Mismatched server, dir or inode \r\n"));
return FALSE;
}
if ((lpQR->usStatus != lpFR->sFR.usStatus)||
(lpQR->uchRefPri != lpFR->sFR.uchRefPri)||
(lpQR->uchIHPri != lpFR->sFR.uchIHPri)||
(lpQR->uchHintFlags != lpFR->sFR.uchHintFlags)||
(lpQR->uchHintPri != lpFR->sFR.uchHintPri))
{
RecchkKdPrint(BADERRORS, ("Mismatched status or pincount\r\n"));
return FALSE;
}
if (ulidDir && (lpQR->ulrecDirEntry != ulrecDirEntry))
{
RecchkKdPrint(BADERRORS, ("Mismatched ulrecDirEntry\r\n"));
return FALSE;
}
return TRUE;
}
#if 0
#ifdef DEBUG
VOID
PrintShareHeader(
LPSHAREHEADER lpSH,
LPFNPRINTPROC lpfnPrintProc
)
/*++
Routine Description:
Parameters:
Return Value:
Notes:
--*/
{
int iRet=0;
if (lpfnPrintProc)
{
iRet += wsprintfA(vchPrintBuff,"****ShareHeader****\r\n" );
iRet+=wsprintfA(vchPrintBuff+iRet,"Header: Flags=%xh Version=%lxh Records=%ld Size=%d \r\n",
lpSH->uchFlags, lpSH->ulVersion, lpSH->ulRecords, lpSH->uRecSize);
iRet+=wsprintfA(vchPrintBuff+iRet,"Store: Max=%ld Current=%ld \r\n", lpSH->sMax.ulSize, lpSH->sCur.ulSize);
iRet+=wsprintfA(vchPrintBuff+iRet,"\r\n");
(lpfnPrintProc)(vchPrintBuff);
}
}
VOID
PrintPQHeader(
LPQHEADER lpQH,
PRINTPROC lpfnPrintProc
)
{
int iRet=0;
if (lpfnPrintProc)
{
iRet += wsprintfA(vchPrintBuff+iRet,"****PQHeader****\r\n" );
iRet += wsprintfA(vchPrintBuff+iRet,"Flags=%xh Version=%lxh Records=%ld Size=%d head=%ld tail=%ld\r\n",
lpQH->uchFlags, lpQH->ulVersion, lpQH->ulRecords, lpQH->uRecSize, lpQH->ulrecHead, lpQH->ulrecTail);
iRet += wsprintfA(vchPrintBuff+iRet,"\r\n");
(lpfnPrintProc)(vchPrintBuff);
}
}
VOID
PrintFileHeader(
LPFILEHEADER lpFH,
unsigned ulSpaces,
PRINTPROC lpfnPrintProc
)
/*++
Routine Description:
Parameters:
Return Value:
Notes:
--*/
{
int iRet=0;
if (lpfnPrintProc)
{
iRet += PrintSpaces(vchPrintBuff+iRet, ulSpaces);
iRet += wsprintfA(vchPrintBuff+iRet,"****FileHeader****\r\n" );
iRet += PrintSpaces(vchPrintBuff+iRet, ulSpaces);
iRet += wsprintfA(vchPrintBuff+iRet,"Flags=%xh Version=%lxh Records=%ld Size=%d\r\n",
lpFH->uchFlags, lpFH->ulVersion, lpFH->ulRecords, lpFH->uRecSize);
iRet += PrintSpaces(vchPrintBuff+iRet, ulSpaces);
iRet += wsprintfA(vchPrintBuff+iRet,"bytes=%ld entries=%d Share=%xh Dir=%xh\r\n",
lpFH->ulsizeShadow, lpFH->ucShadows, lpFH->ulidShare, lpFH->ulidDir);
iRet += wsprintfA(vchPrintBuff+iRet,"\r\n");
(lpfnPrintProc)(vchPrintBuff);
}
}
VOID
PrintPQrec(
unsigned ulRec,
LPQREC lpQrec,
PRINTPROC lpfnPrintProc
)
/*++
Routine Description:
Parameters:
Return Value:
Notes:
--*/
{
int iRet=0;
if (lpfnPrintProc)
{
iRet += wsprintfA(vchPrintBuff+iRet,"rec=%xh: Srvr=%xh dir=%xh shd=%xh prev=%xh next=%xh Stts=%xh, RfPr=%d PnCnt=%x PnFlgs=%xh DrEntr=%d\r\n"
,ulRec
, lpQrec->ulidShare
, lpQrec->ulidDir
, lpQrec->ulidShadow
, lpQrec->ulrecPrev
, lpQrec->ulrecNext
, (unsigned long)(lpQrec->usStatus)
, (unsigned long)(lpQrec->uchRefPri)
, (unsigned long)(lpQrec->uchHintPri)
, (unsigned long)(lpQrec->uchHintFlags)
, lpQrec->ulrecDirEntry
);
(lpfnPrintProc)(vchPrintBuff);
}
}
VOID PrintShareRec(
unsigned ulRec,
LPSHAREREC lpSR,
PRINTPROC lpfnPrintProc
)
/*++
Routine Description:
Parameters:
Return Value:
Notes:
--*/
{
int iRet=0;
if (lpfnPrintProc)
{
iRet += wsprintfA(vchPrintBuff+iRet,"Type=%c Flags=%xh hShare=%lxh Root=%0lxh status=%xh Share=%s \r\n"
, lpSR->uchType, (unsigned)lpSR->uchFlags, ulRec, lpSR->ulidShadow
, lpSR->uStatus, lpSR->rgPath);
iRet += wsprintfA(vchPrintBuff+iRet,"Hint: HintFlags=%xh, HintPri=%d, IHPri=%d\r\n",
(unsigned)(lpSR->uchHintFlags)
, (int)(lpSR->uchHintPri)
, (int)(lpSR->uchIHPri));
iRet += wsprintfA(vchPrintBuff+iRet,"\r\n");
(lpfnPrintProc)(vchPrintBuff+iRet);
}
}
VOID PrintFilerec(
unsigned ulRec,
LPFILERECEXT lpFR,
unsigned ulSpaces,
PRINTPROC lpfnPrintProc
)
/*++
Routine Description:
Parameters:
Return Value:
Notes:
--*/
{
int i;
int iRet=0;
if (lpfnPrintProc)
{
iRet += PrintSpaces(vchPrintBuff+iRet, ulSpaces);
iRet += wsprintfA(vchPrintBuff+iRet,"Type=%c Flags=%xh Inode=%0lxh status=%xh 83Name=%ls size=%ld attrib=%lxh \r\n",
lpFR->sFR.uchType, (unsigned)lpFR->sFR.uchFlags, lpFR->sFR.ulidShadow,
lpFR->sFR.uStatus, lpFR->sFR.rgw83Name, lpFR->sFR.ulFileSize, lpFR->sFR.dwFileAttrib);
iRet += PrintSpaces(vchPrintBuff+iRet, ulSpaces);
iRet += wsprintfA(vchPrintBuff+iRet,"time: hi=%lxh lo=%lxh orgtime: hi=%lxh lo=%lxh\r\n"
, lpFR->sFR.ftLastWriteTime.dwHighDateTime,lpFR->sFR.ftLastWriteTime.dwLowDateTime
, lpFR->sFR.ftOrgTime.dwHighDateTime,lpFR->sFR.ftOrgTime.dwLowDateTime);
iRet += PrintSpaces(vchPrintBuff+iRet, ulSpaces);
iRet += wsprintfA(vchPrintBuff+iRet,"Hint: HintFlags=%xh, RefPri=%d, HintPri=%d AliasInode=%0lxh \r\n",
(unsigned)(lpFR->sFR.uchHintFlags)
, (int)(lpFR->sFR.uchRefPri)
, (int)(lpFR->sFR.uchHintPri)
, lpFR->sFR.ulidShadowFrom);
iRet += PrintSpaces(vchPrintBuff+iRet, ulSpaces);
iRet += wsprintfA(vchPrintBuff+iRet,"LFN=%-14ls", lpFR->sFR.rgwName);
for(i = 0; i < OvfCount(lpFR); ++i)
{
iRet += wsprintfA(vchPrintBuff+iRet,"%-74s", &(lpFR->sFR.ulidShadow));
}
iRet += wsprintfA(vchPrintBuff+iRet,"\r\n");
(lpfnPrintProc)(vchPrintBuff);
}
}
int
PrintSpaces(
LPSTR lpBuff,
unsigned ulSpaces
)
/*++
Routine Description:
Parameters:
Return Value:
Notes:
--*/
{
unsigned i;
int iRet=0;
for (i=0; i< ulSpaces; ++i)
{
iRet += wsprintfA(lpBuff+iRet," ");
}
return iRet;
}
#endif
#endif