Windows NT 4.0 source code leak
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.
 
 
 
 
 
 

730 lines
13 KiB

// MrImpl.h
#if !defined(_mrimpl_h)
#define _mrimpl_h
#define MR_ENGINE_IMPL
#include <MrEngine.h>
#include <time.h>
#pragma warning(disable:4200) /* disable the zero-sized array in struct */
enum {
sigMagic = ' SRD',
sigFileStream = ' srd',
cbitsName = 256,
cbMapInit = 4096,
cbFileInfoInit = 4096,
sgnLess = -1,
sgnEqual = 0,
sgnGreater = 1,
ctchMrePathMax = _MAX_PATH + 40,
cbStreamPage = 4096,
};
// must use a unsigned long instead of TI, since we store it and we don't
// want to worry about any alignment/packing problems.
typedef unsigned long STI;
//
// fwd declarations, helpers
//
class MREF;
typedef MREF * PMREF;
class MREB;
typedef MREB * PMREB;
class MRE;
typedef MRE * PMRE;
#include "Stack.h"
#include "SSBuf.h"
#include "MreUtil.h"
#include "ClasInfo.h"
#include "FileInfo.h"
#include "MreLog.h"
#include "MreType.h"
#include "MreLine.h"
#define cbExtra 12
struct FIExtra {
time_t tt;
BldId cBuilds;
SIG sigMatchingPdbFile;
};
typedef FIExtra * PFIExtra;
//
// static data
//
const int cbTypeName = 256;
const TI tiMin = 0x1000;
const unsigned cbExtraFI = sizeof(FIExtra);
struct TagNi { // NI tagged with a build id
NI ni;
BldId bldid;
TagNi() {
ni = niNil;
bldid = 0;
}
TagNi ( NI _ni, BldId _bldid ) {
ni = _ni;
bldid = _bldid;
}
BldId
BuildId() const {
return bldid;
}
NI
Ni() const {
return ni;
}
};
typedef MapVer<NI,FI,HcNi,cbExtraFI> MapNiFileInfo;
typedef MapVer<NI,ClassInfo,HcNi,cbExtra> MapNiClassInfo;
typedef EnumMap<NI,FI,HcNi> EnumMapNiFi;
typedef EnumMap<NI,ClassInfo,HcNi> EnumMapNiCi;
typedef ArrayVer<TagClsDep,cbExtra> ArrayTagClsDep;
typedef ArrayVer<TagNi,cbExtra> ArrayTagNi;
struct NIList {
NI * pniMac;
NI rgni[];
};
inline DWORD
RoundUp ( DWORD dw, DWORD dwRoundTo ) {
return dwRoundTo * ((dw + dwRoundTo - 1) / dwRoundTo);
}
inline BOOL
FStreamToBuffer ( Stream * pstream, Buffer & buf ) {
PB pb = NULL;
CB cb = pstream->QueryCb();
BOOL fRet = fFalse;
if ( cb > 0 ) {
if ( buf.Size() > cb ) {
buf.Truncate ( cb );
pb = buf.Start();
}
else {
buf.Reserve ( cb - buf.Size(), &pb );
}
fRet = pb && pstream->Read2 ( 0, pb, cb );
}
return fRet;
}
inline BOOL
FBufferAppendToStream ( Buffer & buf, Stream * pstream ) {
return pstream->Append ( buf.Start(), buf.Size() );
}
inline void
CloseStream ( Stream * & pstream ) {
if ( pstream ) {
verify ( pstream->Release() );
pstream = NULL;
}
}
//
// MRE, implementation of MREngine interface
//
class MRE :
public MREngine,
public MREDrv,
public MRECmp,
public MREUtil
{ // see MREngine.h declaration for api notes.
enum {
verMapNiFi = -4,
verMapNiCi = -1,
verArrayClsdep = -1,
verArrayFileMods = -1,
dsecRefresh = 2
};
// data members
BOOL m_fWrite;
BOOL m_fClosePdb;
PPDB m_ppdb;
Stream * m_pstreamFileInfo;
Stream * m_pstreamClassInfo;
Stream * m_pstreamClassMods;
Stream * m_pstreamFileMods;
Stream * m_pstreamRudeFiles;
NameMap * m_pnamemap;
TPI * m_ptpi;
// work and current object buffers
MapNiFileInfo m_mpnifi;
MapNiClassInfo m_mpnici;
ArrayTagClsDep m_rgtagclsdep;
ArrayTagNi m_rgtagniPending;
ArrayTagNi m_rgtagniRude;
// Line change record handler
LCRecHandler m_lcrechandler;
// cache sizes to see if we have to write them back out
unsigned m_itagclsdepSav;
BOOL m_ftagniPendingDirty;
unsigned m_itagniRudeSav;
MRFIBuf m_mrfibufRoot;
PMREF m_pmrefRoot;
//
// Miscellaneous
//
// the logger
MreLog m_mrelog;
// the time when this session started
MREFT m_mreftSessionStart;
//
// Thread handling types and data
//
struct ThreadData {
BOOL fThreadDone;
};
typedef ThreadData * PThreadData;
typedef void (MRE::* MrePmfn)(PThreadData);
struct TEI { // Thread Entry Interface
PMRE pmre;
PThreadData pthreaddata;
MrePmfn pmfn;
BOOL fSnarfed;
};
ThreadData m_threaddata;
// stream names
static const _TCHAR c_szMreFileInfo[];
static const _TCHAR c_szMreClassInfo[];
static const _TCHAR c_szMreFileFmt[];
static const _TCHAR c_szMreClassMods[];
static const _TCHAR c_szMreFileMods[];
static const _TCHAR c_szMreRudeFiles[];
// string to check each header for to ignore deps on that file.
// resource.h from appwiz projects...
static const _TCHAR c_szNoDepHeader[22];
public:
SZC
SzFromNi ( NI ni ) {
precondition ( m_pnamemap );
SZC szRet;
if ( !m_pnamemap->getName ( ni, &szRet ) ) {
szRet = NULL;
}
return szRet;
}
BOOL
FLogging() const {
return m_mrelog.FLogging();
}
MreLog &
MreLog() {
return m_mrelog;
}
SZ
SzFullCanonFilename ( SZC szFile, SZ szCanonFile, size_t cch );
protected:
friend BOOL MREngine::FOpen ( PMREngine*, PPDB, PNMP, BOOL, BOOL );
friend BOOL MREngine::FOpen ( PMREngine *, SZC, EC &, _TCHAR szErr[cbErrMax], BOOL, BOOL );
friend BOOL MREngine::FOpen ( PMREngine *, PMreToPdb, BOOL, BOOL );
friend class MREB;
friend class MREF;
friend class MRFIBuf;
friend class MreLog;
MRE() :
m_mpnifi(verMapNiFi),
m_mpnici(verMapNiCi),
m_rgtagclsdep(verArrayClsdep),
m_rgtagniPending(verArrayFileMods),
m_rgtagniRude(verArrayFileMods)
{
m_fWrite = fFalse;
m_fClosePdb = fFalse;
m_ppdb = NULL;
m_pstreamFileInfo = NULL;
m_pstreamFileMods = NULL;
m_pstreamClassMods = NULL;
m_pstreamFileMods = NULL;
m_pstreamRudeFiles = NULL;
m_pnamemap = NULL;
m_pmrefRoot = NULL;
m_mrfibufRoot.SetPmre ( this );
SYSTEMTIME st;
GetSystemTime ( &st );
if ( !SystemTimeToFileTime ( &st, &m_mreftSessionStart.ft ) ) {
m_mreftSessionStart.qwft = 0;
}
}
~MRE() { }
BOOL
FInit ( PMreToPdb, BOOL fWrite, BOOL fClosePdb );
NI
NiFromName ( SZC sz ) {
precondition ( m_pnamemap );
NI niRet;
if ( !m_pnamemap->getNi ( SZ(sz), &niRet ) ) {
niRet = niNil;
}
return niRet;
}
BOOL
FFileInfoFromNi ( NI ni, PFI * ppfi ) {
PFI pfiRet;
if ( m_mpnifi.map ( ni, &pfiRet ) ) {
if ( ppfi ) {
*ppfi = pfiRet;
}
return fTrue;
}
return fFalse;
}
BOOL
FInsertFileInfo ( FI & fi ) {
return m_mpnifi.add ( fi.niFile, fi );
}
BOOL
FClassInfoFromNi ( NI ni, PCI * ppci ) {
PCI pciRet;
if ( m_mpnici.map ( ni, &pciRet ) ) {
if ( ppci ) {
*ppci = pciRet;
}
return fTrue;
}
return fFalse;
}
BOOL
FInsertClassInfo ( ClassInfo & ci ) {
return m_mpnici.add ( ci.ni, ci );
}
BOOL
FNiUsesNiClass ( NI niFile, NI niClass, const CLASSDEP ** ppcd = NULL );
BOOL
FNiDependsOnNiFile ( NI niSrc, NI niDep );
void
FillEnumFile ( EnumFile &, PFI );
void
FillEnumFile ( EnumFile &, NI );
BOOL
FClassIsBoring ( NI ni ) {
PCI pci;
if ( m_mpnici.map ( ni, &pci ) ) {
return pci && pci->FClassIsBoring();
}
return fFalse;
}
BOOL
FAddClassDep (
NI niDep,
TI tiDep,
DWORD dwLine,
SZC szMemberName,
DEPON deponHow
);
BOOL
FLoadMrfi ( NI niFile = niNil );
static void __cdecl
ThreadEntry ( PV pvTei );
void
ThreadPropagateChanges ( PThreadData );
void
UpdateFilesAndChangeInfo ( BOOL fSkipFileStats );
BOOL
FIsFileOutOfDate ( PFI pfi );
void
CheckIgnoreFile ( FI &, HANDLE );
void
CheckForClassChange ( PCI, NI, TI );
void
GenerateClassChangeFromTypes ( CLASSDEP *, TI tiPrev, TI tiCur );
void
PrepClassData ( PlfClass plf, DWORD & cbClass, _TCHAR szName[ cbTypeName ] );
void
NoteRudeNestedClasses ( TI tiClass );
BOOL
FBuildMbrList ( PlfClass, SZC szClass, MapNiClsData & );
void
SetNestedClassesRude ( MapNiClsData & );
unsigned
CbDoNestedType ( PlfNestType, SZC szClass, MapNiClsData & );
void
CrackMethodList ( TI tiMethList, ClsData & clsdata );
void
CrackOneMethod ( PlfOneMethod plf, ClsData & clsdata, CB cb );
BOOL
FDoFieldList (
TI tiFieldList,
SZC szClass,
MapNiClsData &,
BOOL fNestedTypesOnly =fFalse
);
BldId
BuildId() {
return PFIExtra(m_mpnifi.PbUserData())->cBuilds;
}
SIG &
SigMatchingPdbFile() {
return PFIExtra(m_mpnifi.PbUserData())->sigMatchingPdbFile;
}
void
IncBuildId() {
PFIExtra(m_mpnifi.PbUserData())->cBuilds++;
}
void
UpdateFileInfoTimeStamp() {
PFIExtra pfiex = PFIExtra(m_mpnifi.PbUserData());
time ( &pfiex->tt );
}
void
NoteRudeClass ( NI niFile, NI niClass );
void
PromoteFileToRude ( NI niFile );
void
GenerateClassMod ( NI niClass, SZC szMember );
void
CheckSrcTarg ( PFI pfiSrc, NI niTarg, NI niOptions );
BOOL
FCheckVisitedDeps ( PFI pfiSrc, BOOL fUsingPch );
BOOL
FVisitedRecently ( PFI pfi ) {
precondition ( pfi );
return pfi->FIsFsmSet ( fsmVisited );
}
void
UpdateVisited ( PFI pfi ) {
precondition ( pfi );
pfi->SetFstatus ( fsmVisited );
}
BOOL
FUpdateFileInfo ( PFI pfi, HANDLE hFile =INVALID_HANDLE_VALUE );
public:
// MREngine interface methods
virtual BOOL
FRelease();
virtual BOOL
FDelete();
virtual BOOL
FClose ( BOOL fCommit );
virtual void
QueryPdbApi ( PDB *& rppdb, NameMap *& rpnamemap );
virtual void
QueryMreLog ( PMRELog & rpmrelog );
virtual void
QueryMreDrv ( PMREDrv & rpmredrv );
virtual void
QueryMreCmp ( PMRECmp & rpmrecmp, TPI * );
virtual void
QueryMreUtil ( PMREUtil & rpmreutil );
virtual BOOL
FCommit();
// MREDrv interface methods
virtual BOOL
FRefreshFileSysInfo();
virtual BOOL
FSuccessfulCompile ( BOOL fOk, SZC szFileSrc, SZC szFileTarg );
virtual YNM
YnmFileOutOfDate ( SRCTARG & );
virtual BOOL
FFilesOutOfDate ( PCAList pcalist );
virtual BOOL
FUpdateTargetFile ( SZC szTarget, TrgType );
virtual void
OneTimeInit();
// MRECmp interface methods
virtual BOOL
FOpenCompiland (
OUT PMREFile * ppmrefile,
SZC szFileSrc,
SZC szFileTarg
);
virtual BOOL
FCloseCompiland ( PMREFile pmrefile, BOOL fCommit );
virtual BOOL
FPushFile (
PMREFile * ppmrefile,
SZC szFile,
HANDLE hfile =INVALID_HANDLE_VALUE
);
virtual PMREFile
PmrefilePopFile();
virtual BOOL
FStoreDepData ( PDepData );
virtual BOOL
FRestoreDepData ( PDepData );
virtual void
ClassIsBoring ( NI niClass );
// MREUtil interface methods
virtual void
EnumSrcFiles ( PfnFEFSrcCallBack, SZC szFileSrc = NULL );
virtual void
EnumDepFiles ( EnumFile &, PfnFEFDepCallBack );
virtual void
EnumAllFiles ( PfnFEFAllCallBack, SZC szFileSrc = NULL );
virtual void
EnumClasses ( PfnFEClassCallBack, SZC szFileSrc );
virtual void
SummaryStats ( MreStats & );
};
//
// implementation class for MREFile
//
class MREF : public MREFile {
enum { iFileNoBoring = 0 };
public:
MREF ( MRE * pmre, NI ni )
: m_pmre(pmre) {
assert ( m_pmre );
assert ( ni != niNil );
m_stackNi.FPush ( ni );
m_fAllCodeCompiled = fFalse;
m_iFileBoring = iFileNoBoring;
debug ( SZC szFileName = SzFileName() );
}
~MREF() {
debug ( SZC szFileName = SzFileName() );
}
void
Push ( NI ni ) {
debug ( SZC szName = SzFileName() );
m_stackNi.FPush ( ni );
SetBoring();
}
NI
Pop() {
assert ( m_stackNi.Count() );
if ( m_iFileBoring == m_stackNi.Count() ) {
m_iFileBoring = iFileNoBoring;
}
return m_stackNi.Pop();
}
NI
Ni() const {
return m_stackNi.Top();
}
SZC
SzFileName() const {
return m_pmre->SzFromNi ( Ni() );
}
BOOL
FIsTopLevelFile() const {
return m_stackNi.Count() == 1;
}
BOOL
FAllCodeCompiled() const {
return m_fAllCodeCompiled;
}
void
NoteActualClassChange ( NI );
Array<NI> &
RgNiClassesChanged() {
return m_rgniClassesChanged;
}
public:
// interface from MREFile
virtual BOOL
FOpenBag ( OUT PMREBag * ppmrebag, NI niNameBag );
virtual BOOL
FnoteEndInclude ( DWORD dwFlags );
virtual BOOL
FnoteClassMod ( NI niClass, DWORD dwFlags );
virtual BOOL
FnoteInlineMethodMod (
NI niClass,
SZC szMember,
DWORD dwFlags
);
virtual BOOL
FnoteLineDelta ( DWORD dwLineBase, INT delta );
virtual void
EnumerateChangedClasses ( PfnEnumClassChange );
virtual BOOL
FnoteClassTI ( NI, TI );
virtual BOOL
FIsBoring();
virtual BOOL
FnotePchCreateUse ( SZC szPchCreate, SZC szPchUse );
private:
friend class MREB;
MRE * m_pmre;
Stack<NI, 64> m_stackNi;
BOOL m_fAllCodeCompiled;
Array<NI> m_rgniClassesChanged;
unsigned m_iFileBoring;
// hard-coded filenames to imply boring classes
static const _TCHAR * c_rgszBoringFiles[];
void
SetBoring();
};
//
// implementation class for MREBag
//
class MREB : public MREBag {
MREF * m_pmref;
NI m_ni;
MRE *
Pmre() const {
assert ( m_pmref );
assert ( m_pmref->m_pmre );
return m_pmref->m_pmre;
}
public:
MREB( PMREF pmref, NI niName )
: m_pmref(pmref), m_ni(niName) {
assert ( m_pmref );
assert ( m_ni != niNil );
debug ( SZC szName = SzName() );
}
// interface from MREBag
virtual BOOL
FAddDep (
NI niDep,
TI tiDep,
SZC szMemberName,
DEPON deponHow,
DWORD dwLine =0
);
virtual BOOL
FClose();
SZC
SzName() const {
return Pmre()->SzFromNi ( m_ni );
}
};
#endif