/*============================================================================== Microsoft Denali Microsoft Confidential. Copyright 1996 Microsoft Corporation. All Rights Reserved. File: template.h Maintained by: DaveK Component: include file for Denali Compiled Template object ==============================================================================*/ #ifndef _TEMPLATE_H #define _TEMPLATE_H #include "vector.h" #include "LinkHash.h" #include "Compcol.h" #include "util.h" #include "activdbg.h" #include "ConnPt.h" #include "DblLink.h" #include "aspdmon.h" #include "ie449.h" #include "memcls.h" #define PER_TEMPLATE_REFLOG 0 /* NOTE we ensure that C_COUNTS_IN_HEADER is a multiple of 4 because the offsets which follow the counts in template header are dword-aligned. It is easiest (and fastest at runtime) to make sure those offsets start on a dword-alignment point; thus no runtime alignment calc is needed in GetAddress(). */ #define C_REAL_COUNTS_IN_HEADER 3 // actual number of count fields in template header #define C_COUNTS_IN_HEADER (C_REAL_COUNTS_IN_HEADER/4 + 1) * 4 // allocated number of count fields in template header #define C_OFFOFFS_IN_HEADER 4 // number of 'ptr-to-ptr' fields in template header #define CB_TEMPLATE_DEFAULT 2500 // default memory allocation for new template #define C_TARGET_LINES_DEFAULT 50 // default count of target script lines per engine #define C_TEMPLATES_PER_INCFILE_DEFAULT 4 // default count of templates per inc-file #define SZ_NULL "\0" #define WSTR_NULL L"\0" #define SZ_NEWLINE "\r\n" const unsigned CB_NEWLINE = strlen(SZ_NEWLINE); const LPSTR g_szWriteBlockOpen = "Response.WriteBlock("; const LPSTR g_szWriteBlockClose = ")"; const LPSTR g_szWriteOpen = "Response.Write("; const LPSTR g_szWriteClose = ")"; // defaults for buffering interim compile results #define C_SCRIPTENGINESDEFAULT 2 // default count of script engines #define C_SCRIPTSEGMENTSDEFAULT 20 // default count of script segments #define C_OBJECTINFOS_DEFAULT 10 // default count of object-infos #define C_HTMLSEGMENTSDEFAULT 20 // default count of HTML segments #define C_INCLUDELINESDEFAULT 5 // default count of include lines #define CB_TOKENS_DEFAULT 400 // default byte count for tokens #define CH_ATTRIBUTE_SEPARATOR '=' // separator for attribute-value pair #define CH_SINGLE_QUOTE '\'' // single-quote character #define CH_DOUBLE_QUOTE '"' // double-quote character #define CH_ESCAPE '\\' // escape character - tells us to ignore following token // ACLs: the following code should in future be shared with IIS (see creatfil.cxx in IIS project) // NOTE we want SECURITY_DESC_DEFAULT_SIZE to be relatively small, since it affects template memory reqt dramatically #define SECURITY_DESC_GRANULARITY 128 // 'chunk' size for re-sizing file security descriptor #define SECURITY_DESC_DEFAULT_SIZE 256 // initial default size of file security descriptor #define SIZE_PRIVILEGE_SET 128 // size of privilege set // macros // use outside of CTokenList class #define SZ_TOKEN(i) (*gm_pTokenList).m_bufTokens.PszLocal(i) #define CCH_TOKEN(i) (*gm_pTokenList)[i]->m_cb #define _TOKEN CTemplate::CTokenList::TOKEN // use within CTokenList class #define CCH_TOKEN_X(i) (*this)[i]->m_cb #define BR_TOKEN_X(i) *((*this)[i]) // Use to specify which source file name you want (pathInfo or pathTranslated) #ifndef _SRCPATHTYPE_DEFINED #define _SRCPATHTYPE_DEFINED enum SOURCEPATHTYPE { SOURCEPATHTYPE_VIRTUAL = 0, SOURCEPATHTYPE_PHYSICAL = 1 }; #endif // CTemplate error codes #define E_COULDNT_OPEN_SOURCE_FILE 0x8000D001L #define E_SOURCE_FILE_IS_EMPTY 0x8000D002L #define E_TEMPLATE_COMPILE_FAILED 0x8000D003L #define E_USER_LACKS_PERMISSIONS 0x8000D004L #define E_TEMPLATE_COMPILE_FAILED_DONT_CACHE 0x8000D005L #define E_TEMPLATE_MAGIC_FAILURE 0x8000D006L inline BOOL FIsPreprocessorError(HRESULT hr) { return ( hr == E_SOURCE_FILE_IS_EMPTY || hr == E_TEMPLATE_COMPILE_FAILED || hr == E_TEMPLATE_COMPILE_FAILED_DONT_CACHE || hr == E_TEMPLATE_MAGIC_FAILURE ); } //Can not use same index as CErrorInfo anymore. //Index for lastErrorInfo in Template #define ILE_szFileName 0 #define ILE_szLineNum 1 #define ILE_szEngine 2 #define ILE_szErrorCode 3 #define ILE_szShortDes 4 #define ILE_szLongDes 5 #define ILE_MAX 6 // forward references class CTemplate; class CTemplateCacheManager; class CHitObj; class CTokenList; class CIncFile; typedef CLSID PROGLANG_ID; // NOTE also defined in scrptmgr.h; we define here to avoid include file circularity /* ============================================================================ Class: CByteRange Synopsis: A range of bytes NOTE fLocal member is only used if the byte range is stored in a CBuffer NOTE 2 m_pfilemap is really a pointer to a CFileMap - however, it's impossible to declare that type here because the CFileMap struct is nested inside CTemplate, and C++ won't let you forward declare nested classes. Since the CTemplate definition depends on CByteRange, properly declaring the type of "m_pfilemap" is impossible. */ class CByteRange { public: BYTE* m_pb; // ptr to bytes ULONG m_cb; // count of bytes ULONG m_fLocal:1; // whether bytes are stored in buffer (TRUE) or elsewhere (FALSE) UINT m_idSequence:31; // byte range's sequence id void* m_pfilemap; // file the byte range comes from CByteRange(): m_pb(NULL), m_cb(0), m_fLocal(FALSE), m_idSequence(0), m_pfilemap(NULL) {} CByteRange(BYTE* pb, ULONG cb): m_fLocal(FALSE), m_idSequence(0) {m_pb = pb; m_cb = cb;} BOOLB IsNull() { return((m_pb == NULL) || (m_cb == 0)) ; } void Nullify() { m_pb = NULL; m_cb = 0; } void operator=(const CByteRange& br) { m_pb = br.m_pb; m_cb = br.m_cb; m_fLocal = br.m_fLocal; m_idSequence = br.m_idSequence; } BOOLB FMatchesSz(LPCSTR psz); void Advance(UINT i); BYTE* PbString(LPSTR psz, LONG lCodePage); BYTE* PbOneOfAspOpenerStringTokens(LPSTR rgszTokens[], UINT rgcchTokens[], UINT nTokens, UINT *pidToken); BOOLB FEarlierInSourceThan(CByteRange& br); }; /* ============================================================================ Enum type: TEMPLATE_COMPONENT Synopsis: A component of a template, e.g. script block, html block, etc. */ enum TEMPLATE_COMPONENT { // NOTE enum values and order are tightly coupled with template layout order // DO NOT CHANGE tcompScriptEngine = 0, tcompScriptBlock, tcompObjectInfo, tcompHTMLBlock, }; /* **************************************************************************** Class: CTemplateConnPt Synopsis: Connection point for IDebugDocumentTextEvents */ class CTemplateConnPt : public CConnectionPoint { public: // ctor CTemplateConnPt(IConnectionPointContainer *pContainer, const GUID &uidConnPt) : CConnectionPoint(pContainer, uidConnPt) {} // IUnknown methods STDMETHOD(QueryInterface)(const GUID &, void **); STDMETHOD_(ULONG, AddRef)(); STDMETHOD_(ULONG, Release)(); }; /* **************************************************************************** Class: CTemplateKey Synopsis: Packaged data to locate template in hash table (instance ID, and template name) */ #define MATCH_ALL_INSTANCE_IDS 0xFFFBAD1D // unlikely instance ID. sort of spells "BAD ID" struct CTemplateKey { const TCHAR * szPathTranslated; DWORD dwInstanceID; CTemplateKey(const TCHAR *_szPathTranslated = NULL, UINT _dwInstanceID = MATCH_ALL_INSTANCE_IDS) : szPathTranslated(_szPathTranslated), dwInstanceID(_dwInstanceID) {} }; /* **************************************************************************** Class: CTemplate Synopsis: A Denali compiled template. NOTE: CTemplate's primary client is CTemplateCacheManager, which maintains a cache of compiled templates. USAGE ----- The CTemplate class must be used as follows: CLASS INIT - InitClass must be called before any CTemplate can be created. NEW TEMPLATE - For each new template the client wants to create, the client must do the following, in order: 1) New a CTemplate 2) Initialize the CTemplate by calling Init, passing a source file name 3) Load the CTemplate by calling Load; when Load returns, the new CTemplate is ready for use. EXISTING TEMPLATE - To use an existing template, the client must: 1) Call Deliver; when Deliver returns, the existing CTemplate is ready for use. CLASS UNINIT - UnInitClass must be called after the last CTemplate has been destroyed. To ensure thread-safety, the client must implement a critical section around the call to Init. Init is designed to be as fast as possible, so the client can quickly learn that it has a pending template for a given source file, and queue up other requests for the same source file. CTemplate provides implementations for Debug documents, namely IDebugDocumentProvider & IDebugDocumentText */ class CActiveScriptEngine; class CTemplate : public CDblLink, public IDebugDocumentProvider, public IDebugDocumentText, public IConnectionPointContainer // Source of IDebugDocumentTextEvents { private: #include "templcap.h" // 'captive' classes, only used internally within CTemplate friend HRESULT InitMemCls(); friend HRESULT UnInitMemCls(); friend class CTemplateCacheManager; // TODO: decouple CTemplate class from it's manager class friend class CFileMap; friend class CIncFile; // IncFiles are privy to debugging data structures // CScriptStore::Init() must access gm_brDefaultScriptLanguage, gm_progLangIdDefault friend HRESULT CTemplate::CScriptStore::Init(LPCSTR szDefaultScriptLanguage, CLSID *pCLSIDDefaultEngine); private: CWorkStore* m_pWorkStore; // ptr to working storage for source segments HANDLE m_hEventReadyForUse; // ready-for-use event handle public: BYTE* m_pbStart; // ptr to start of template memory ULONG m_cbTemplate; // bytes allocated for template LONG m_cRefs; // ref count - NOTE LONG required by InterlockedIncrement private: CTemplateConnPt m_CPTextEvents; // Connection point for IDebugDocumentTextEvents // support for compile-time errors BYTE* m_pbErrorLocation; // ptr to error location in source file UINT m_idErrMsg; // error message id UINT m_cMsgInserts; // count of insert strings for error msg char** m_ppszMsgInserts; // array of ptrs to error msg insert strings // support for run-time errors and debugging UINT m_cScriptEngines; // count of script engines CActiveScriptEngine **m_rgpDebugScripts;// array (indexed by engine) of scripts CURRENTLY BEING DEBUGGED vector *m_rgrgSourceInfos; // array of arrays of script source line infos, one per script engine per target line ULONG m_cbTargetOffsetPrevT; // running total of last source offset processed CRITICAL_SECTION m_csDebuggerDetach; // CS needed to avoid race condition with detaching from debugger CDblLink m_listDocNodes; // list of document nodes we are attached to CFileMap** m_rgpFilemaps; // array of ptrs to filemaps of source files CTemplateKey m_LKHashKey; // bundled info for key (contains copy of m_rgpfilemaps[0] filename to make things simpler UINT m_cFilemaps; // count of filemaps of source files CFileMap** m_rgpSegmentFilemaps; // array of filemap ptrs per source segment UINT m_cSegmentFilemapSlots; // count of per-source-segment filemap ptrs LPSTR m_pszLastErrorInfo[6]; // text of last error - cached for new requests on this template // FileName, LineNum, Engine, ShortDes, LongDes DWORD m_dwLastErrorMask; // cached for new requests on this template DWORD m_hrOnNoCache; // HRESULT when don't cache is set. TCHAR* m_szApplnVirtPath; // application virtual path (substring of Application URL) TCHAR* m_szApplnURL; // application URL (starts with "http://") // for best structure packing we all boleans here as bitfields unsigned m_fGlobalAsa:1; // is template for global.asa file? unsigned m_fIsValid:1; // is template in valid state? unsigned m_fDontCache:1; // don't cache this template unsigned m_fReadyForUse:1; // is template ready for use? unsigned m_fDebuggerDetachCSInited:1;// has debugger attach critical section been initialized? unsigned m_fDontAttach:1; // should not be attached to debugger (not in cache) unsigned m_fSession:1; // does this page require session state unsigned m_fScriptless:1; // doesn't have any scripts unsigned m_fDebuggable:1; // is this page part of at least one debuggable app? unsigned m_fZombie:1; // File template is based on has changed since obtained from cache unsigned m_fCodePageSet:1; // Did template contain a code page directive unsigned m_fLCIDSet:1; // Did template contain an LCID directive unsigned m_fIsPersisted:1; TransType m_ttTransacted; // type of transaction support // class-wide support for compilation static CTokenList* gm_pTokenList; // array of tokens unsigned m_wCodePage; // Compiler Time CodePage long m_lLCID; // Compile Time LCID vector m_rgpTypeLibs; // array of ptrs to typelibs IDispatch* m_pdispTypeLibWrapper; // typelib wrapper object vector m_rgp449; // array of ptrs to 449 requests LPSTR m_szPersistTempName; // filename of persisted template, if any void *m_pHashTable; // CacheMgr hash table that this template is on IUnknown *m_pServicesConfig; static HANDLE sm_hSmallHeap; static HANDLE sm_hLargeHeap; public: /** ** Initialization and destruction public interfaces **/ // Initializes CTemplate static members; must be called on denali.dll load static HRESULT InitClass(); // Un-initilaizes CTemplate static members; must be called on denali.dll unload static void UnInitClass(); // Inits template in preparation for compilation // Called by template cache mgr before calling Load HRESULT Init(CHitObj* pHitObj, BOOL fGlobalAsp, const CTemplateKey &rTemplateKey); // Compiles the template from its main source file (and include files, if any) HRESULT Compile(CHitObj* pHitObj); // Called by requestor of existing template to determine if template is ready for use HRESULT Deliver(CHitObj* pHitObj); // Create this template's CServicesConfig object HRESULT CreateTransServiceConfig(BOOL fEnableTracker); CTemplate(); ~CTemplate(); void RemoveIncFile(CIncFile* pIncFile); // Trace Log info static PTRACE_LOG gm_pTraceLog; public: #if PER_TEMPLATE_REFLOG PTRACE_LOG m_pTraceLog; #endif /* 'Consumer' public interfaces Methods for getting info out of a CTemplate */ // Returns name of source file on which this template is based LPTSTR GetSourceFileName(SOURCEPATHTYPE = SOURCEPATHTYPE_PHYSICAL); // Returns virtual path of the source file LPTSTR GetApplnPath(SOURCEPATHTYPE = SOURCEPATHTYPE_PHYSICAL); // Returns hashing key of the template const CTemplateKey *ExtractHashKey() const; // Returns version stamp of compiler by which this template was compiled LPSTR GetCompilerVersion(); // Component counts USHORT Count(TEMPLATE_COMPONENT tcomp); USHORT CountScriptEngines() { return (USHORT)m_cScriptEngines; } // Returns i-th script block as ptr to prog lang id and ptr to script text void GetScriptBlock(UINT i, LPSTR* pszScriptEngine, PROGLANG_ID** ppProgLangId, LPCOLESTR* pwstrScriptText); // Returns i-th object-info as object name, clsid, scope, model HRESULT GetObjectInfo(UINT i, LPSTR* ppszObjectName, CLSID *pClsid, CompScope *pScope, CompModel *pcmModel); // Returns i-th HTML block as ptr, count of bytes, original offset, incl filename HRESULT GetHTMLBlock(UINT i, LPSTR* pszHTML, ULONG* pcbHTML, ULONG* pcbSrcOffs, LPSTR* pszSrcIncFile); // Returns line number and source file name a given target line in a given script engine. void GetScriptSourceInfo(UINT idEngine, int iTargetLine, LPTSTR* pszPathInfo, LPTSTR* pszPathTranslated, ULONG* piSourceLine, ULONG* pichSourceLine, BOOLB* pfGuessedLine); // Converts a character offset from the target script to the offset in the source void GetSourceOffset(ULONG idEngine, ULONG cchTargetOffset, TCHAR **pszSourceFile, ULONG *pcchSourceOffset, ULONG *pcchSourceText); // Converts a character offset from the source document to the offset in the target BOOL GetTargetOffset(TCHAR *szSourceFile, ULONG cchSourceOffset, ULONG *pidEngine, ULONG *pcchTargetOffset); // Get the character position of a line (directly implements debugging interface) HRESULT GetPositionOfLine(CFileMap *pFilemap, ULONG cLineNumber, ULONG *pcCharacterPosition); // Get the line # of a character position (directly implements debugging interface) HRESULT GetLineOfPosition(CFileMap *pFilemap, ULONG cCharacterPosition, ULONG *pcLineNumber, ULONG *pcCharacterOffsetInLine); // Return a RUNNING script based on the engine, or NULL if code context has never been requested yet CActiveScriptEngine *GetActiveScript(ULONG idEngine); // associate a running script for an engine ID (Use after you get the first code context) HRESULT AddScript(ULONG idEngine, CActiveScriptEngine *pScriptEngine); // attach the CTemplate object to an application (debugger tree view) HRESULT AttachTo(CAppln *pAppln); // detach the CTemplate object from an application (debugger tree view) HRESULT DetachFrom(CAppln *pAppln); // detach the CTemplate object all applications (and release script engines) HRESULT Detach(); // Signifies last use of template as a recylable object. Any outstanding references // should be from currently executing scripts. ULONG End(); // Let debugger know about page start/end HRESULT NotifyDebuggerOnPageEvent(BOOL fStart); // Generate 449 response in cookie negotiations with IE when needed HRESULT Do449Processing(CHitObj *pHitObj); HRESULT PersistData(char *pszTempFilePath); HRESULT UnPersistData(); HRESULT PersistCleanup(); ULONG TemplateSize() { return m_cbTemplate; } BOOL FTransacted(); BOOL FSession(); BOOL FScriptless(); BOOL FDebuggable(); BOOL FIsValid(); // determine if compilation succeeded BOOL FTemplateObsolete(); BOOL FGlobalAsa(); BOOL FIsZombie(); BOOL FDontAttach(); BOOL FIsPersisted(); VOID Zombify(); IUnknown *PServicesConfig() {return m_pServicesConfig;}; IDispatch *PTypeLibWrapper(); void SetHashTablePtr(void *pTable) { m_pHashTable = pTable; } void *GetHashTablePtr() { return m_pHashTable; } public: /* COM public interfaces Implementation of debugging documents. */ // IUnknown methods STDMETHOD(QueryInterface)(const GUID &, void **); STDMETHOD_(ULONG, AddRef)(); STDMETHOD_(ULONG, Release)(); // IDebugDocumentProvider methods STDMETHOD(GetDocument)(/* [out] */ IDebugDocument **ppDebugDoc); // IDebugDocumentInfo (also IDebugDocumentProvider) methods STDMETHOD(GetName)( /* [in] */ DOCUMENTNAMETYPE dnt, /* [out] */ BSTR *pbstrName); STDMETHOD(GetDocumentClassId)(/* [out] */ CLSID *) { return E_NOTIMPL; } // IDebugDocumentText methods STDMETHOD(GetDocumentAttributes)( /* [out] */ TEXT_DOC_ATTR *ptextdocattr); STDMETHOD(GetSize)( /* [out] */ ULONG *pcLines, /* [out] */ ULONG *pcChars); STDMETHOD(GetPositionOfLine)( /* [in] */ ULONG cLineNumber, /* [out] */ ULONG *pcCharacterPosition); STDMETHOD(GetLineOfPosition)( /* [in] */ ULONG cCharacterPosition, /* [out] */ ULONG *pcLineNumber, /* [out] */ ULONG *pcCharacterOffsetInLine); STDMETHOD(GetText)( /* [in] */ ULONG cCharacterPosition, /* [size_is][length_is][out][in] */ WCHAR *pcharText, /* [size_is][length_is][out][in] */ SOURCE_TEXT_ATTR *pstaTextAttr, /* [out][in] */ ULONG *pcChars, /* [in] */ ULONG cMaxChars); STDMETHOD(GetPositionOfContext)( /* [in] */ IDebugDocumentContext *psc, /* [out] */ ULONG *pcCharacterPosition, /* [out] */ ULONG *cNumChars); STDMETHOD(GetContextOfPosition)( /* [in] */ ULONG cCharacterPosition, /* [in] */ ULONG cNumChars, /* [out] */ IDebugDocumentContext **ppsc); // IConnectionPointContainer methods STDMETHOD(EnumConnectionPoints)( /* [out] */ IEnumConnectionPoints __RPC_FAR *__RPC_FAR *ppEnum) { return E_NOTIMPL; // doubt we need this - client is expecting only TextEvents } STDMETHOD(FindConnectionPoint)( /* [in] */ const IID &iid, /* [out] */ IConnectionPoint **ppCP); private: /* NOTE Compile() works by calling GetSegmentsFromFile followed by WriteTemplate Most other private methods support one of these two workhorse functions */ void AppendMapFile(LPCTSTR szFileSpec, CFileMap* pfilemapParent, BOOLB fVirtual, CHitObj* pHitObj, BOOLB fGlobalAsp); void GetSegmentsFromFile(CFileMap& filemap, CWorkStore& WorkStore, CHitObj* pHitObj, BOOL fIsHTML = TRUE); void GetLanguageEquivalents(); void SetLanguageEquivalent(HANDLE hKeyScriptLanguage, LPSTR szLanguageItem, LPSTR* pszOpen, LPSTR* pszClose); void ThrowError(BYTE* pbErrorLocation, UINT idErrMsg); void AppendErrorMessageInsert(BYTE* pbInsert, UINT cbInsert); void ThrowErrorSingleInsert(BYTE* pbErrorLocation, UINT idErrMsg, BYTE* pbInsert, UINT cbInsert); HRESULT ShowErrorInDebugger(CFileMap* pFilemap, UINT cchErrorLocation, char* szDescription, CHitObj* pHitObj, BOOL fAttachDocument); void ProcessSpecificError(CFileMap& filemap, CHitObj* pHitObj); void HandleCTemplateError(CFileMap* pfilemap, BYTE* pbErrorLocation, UINT idErrMsg, UINT cInserts, char** ppszInserts, CHitObj *pHitObj); void FreeGoodTemplateMemory(); void UnmapFiles(); // ExtractAndProcessSegment: gets and processes next source segment in search range void ExtractAndProcessSegment(CByteRange& brSearch, const SOURCE_SEGMENT& ssegLeading, _TOKEN* rgtknOpeners, UINT ctknOpeners, CFileMap* pfilemapCurrent, CWorkStore& WorkStore, CHitObj* pHitObj, BOOL fScriptTagProcessed = FALSE, BOOL fIsHTML = TRUE); // Support methods for ExtractAndProcessSegment() SOURCE_SEGMENT SsegFromHTMLComment(CByteRange& brSegment); void ProcessSegment(SOURCE_SEGMENT sseg, CByteRange& brSegment, CFileMap* pfilemapCurrent, CWorkStore& WorkStore, BOOL fScriptTagProcessed, CHitObj* pHitObj, BOOL fIsHTML); void ProcessHTMLSegment(CByteRange& brHTML, CBuffer& bufHTMLBlocks, UINT idSequence, CFileMap* pfilemapCurrent); void ProcessHTMLCommentSegment(CByteRange& brSegment, CFileMap* pfilemapCurrent, CWorkStore& WorkStore, CHitObj* pHitObj); void ProcessScriptSegment(SOURCE_SEGMENT sseg, CByteRange& brSegment, CFileMap* pfilemapCurrent, CWorkStore& WorkStore, UINT idSequence, BOOLB fScriptTagProcessed, CHitObj* pHitObj); HRESULT ProcessMetadataSegment(const CByteRange& brSegment, UINT *pidError, CHitObj* pHitObj); HRESULT ProcessMetadataTypelibSegment(const CByteRange& brSegment, UINT *pidError, CHitObj* pHitObj); HRESULT ProcessMetadataCookieSegment(const CByteRange& brSegment, UINT *pidError, CHitObj* pHitObj); void GetScriptEngineOfSegment(CByteRange& brSegment, CByteRange& brEngine, CByteRange& brInclude); void ProcessTaggedScriptSegment(CByteRange& brSegment, CFileMap* pfilemapCurrent, CWorkStore& WorkStore, CHitObj* pHitObj); void ProcessObjectSegment(CByteRange& brSegment, CFileMap* pfilemapCurrent, CWorkStore& WorkStore, UINT idSequence); void GetCLSIDFromBrClassIDText(CByteRange& brClassIDText, LPCLSID pclsid); void GetCLSIDFromBrProgIDText(CByteRange& brProgIDText, LPCLSID pclsid); BOOLB FValidObjectName(CByteRange& brName); void ProcessIncludeFile(CByteRange& brSegment, CFileMap* pfilemapCurrent, CWorkStore& WorkStore, UINT idSequence, CHitObj* pHitObj, BOOL fIsHTML); void ProcessIncludeFile2(CHAR* szFileSpec, CByteRange& brFileSpec, CFileMap* pfilemapCurrent, CWorkStore& WorkStore, UINT idSequence, CHitObj* pHitObj, BOOL fIsHTML); BYTE* GetOpenToken(CByteRange brSearch, SOURCE_SEGMENT ssegLeading, _TOKEN* rgtknOpeners, UINT ctknOpeners, _TOKEN* ptknOpen); BYTE* GetCloseToken(CByteRange brSearch, _TOKEN tknClose); _TOKEN GetComplementToken(_TOKEN tkn); SOURCE_SEGMENT GetSegmentOfOpenToken(_TOKEN tknOpen); CByteRange BrTagsFromSegment(CByteRange brSegment, _TOKEN tknClose, BYTE** ppbCloseTag); CByteRange BrValueOfTag(CByteRange brTags, _TOKEN tknTag); BYTE* GetTagName(CByteRange brTags, _TOKEN tknTagName); BOOL GetTag(CByteRange &brTags, int nIndex = 1); BOOL CompTagName(CByteRange &brTags, _TOKEN tknTagName); BOOLB FTagHasValue(const CByteRange& brTags, _TOKEN tknTag, _TOKEN tknValue); void CopySzAdv(char* pchWrite, LPSTR psz); // WriteTemplate: writes the template to a contiguous block of memory void WriteTemplate(CWorkStore& WorkStore, CHitObj* pHitObj); // Support methods for WriteTemplate() // NOTE Adv suffix on some function names == advance ptr after writing void WriteHeader(USHORT cScriptBlocks,USHORT cObjectInfos, USHORT cHTMLBlocks, UINT* pcbHeaderOffset, UINT* pcbOffsetToOffset); void WriteScriptBlockOfEngine(USHORT idEnginePrelim, USHORT idEngine, CWorkStore& WorkStore, UINT* pcbDataOffset, UINT* pcbOffsetToOffset, CHitObj* pHitObj); void WritePrimaryScriptProcedure(USHORT idEngine, CWorkStore& WorkStore, UINT* pcbDataOffset, UINT cbScriptBlockStart); void WriteScriptSegment(USHORT idEngine, CFileMap* pfilemap, CByteRange& brScript, UINT* pcbDataOffset, UINT cbScriptBlockStart, BOOL fAllowExprWrite); void WriteScriptMinusEscapeChars(CByteRange brScript, UINT* pcbDataOffset, UINT* pcbPtrOffset); BOOLB FVbsComment(CByteRange& brLine); BOOLB FExpression(CByteRange& brLine); void WriteOffsetToOffset(USHORT cBlocks, UINT* pcbHeaderOffset, UINT* pcbOffsetToOffset); void WriteSzAsBytesAdv(LPCSTR szSource, UINT* pcbDataOffset); void WriteByteRangeAdv(CByteRange& brSource, BOOLB fWriteAsBsz, UINT* pcbDataOffset, UINT* pcbPtrOffset); void WriteLongAdv(ULONG uSource, UINT* pcbOffset); void WriteShortAdv(USHORT uSource, UINT* pcbOffset); void MemCpyAdv(UINT* pcbOffset, void* pbSource, ULONG cbSource, UINT cbByteAlign = 0); // Memory access primitives // NOTE invalid until WriteTemplate() has succeeded BYTE* GetAddress(TEMPLATE_COMPONENT tcomp, USHORT i); // Debugging methods void AppendSourceInfo(USHORT idEngine, CFileMap* pfilemap, BYTE* pbSource, ULONG cbSourceOffset, ULONG cbScriptBlockOffset, ULONG cbTargetOffset, ULONG cchSourceText, BOOL fIsHTML); UINT SourceLineNumberFromPb(CFileMap* pfilemap, BYTE* pbSource); HRESULT CreateDocumentTree(CFileMap *pfilemapRoot, IDebugApplicationNode **ppDocRoot); BOOLB FIsLangVBScriptOrJScript(USHORT idEngine); #if 0 void OutputDebugTables(); void OutputIncludeHierarchy(CFileMap *pfilemap, int cchIndent); void GetScriptSnippets(ULONG cchSourceOffset, CFileMap *pFilemapSource, ULONG cchTargetOffset, ULONG idTargetEngine, wchar_t wszSourceText[], wchar_t wszTargetText[]); #endif void RemoveFromIncFiles(); void ReleaseTypeLibs(); void WrapTypeLibs(CHitObj *pHitObj); void Release449(); HRESULT BuildPersistedDACL(PACL *ppRetDACL); // Cache on per-class basis ACACHE_INCLASS_DEFINITIONS() public: // memory allocation static void* SmallMalloc(SIZE_T dwBytes); static void* SmallReAlloc(void* pvMem, SIZE_T dwBytes); static void SmallFree(void* pvMem); static void* LargeMalloc(SIZE_T dwBytes); static void* LargeReAlloc(void* pvMem, SIZE_T dwBytes); static void LargeFree(void* pvMem); }; //////////////////////////////////////////////////////////////////////////////// // Inline functions // Write a long or short to memory, then advance target-ptr inline void CTemplate::WriteLongAdv(ULONG uSource, UINT* pcbOffset) { MemCpyAdv(pcbOffset, &uSource, sizeof(ULONG), sizeof(ULONG)); } inline void CTemplate::WriteShortAdv(USHORT uSource, UINT* pcbOffset) { MemCpyAdv(pcbOffset, &uSource, sizeof(USHORT), sizeof(USHORT)); } inline const CTemplateKey * CTemplate::ExtractHashKey() const { return &m_LKHashKey; } inline BOOL CTemplate::FTransacted() { return (m_ttTransacted != ttUndefined); } inline BOOL CTemplate::FDebuggable() { return(m_fDebuggable); } inline BOOL CTemplate::FSession() { return(m_fSession); } inline BOOL CTemplate::FScriptless() { return m_fScriptless; } inline BOOL CTemplate::FIsValid() { return(m_fIsValid); } inline BOOL CTemplate::FGlobalAsa() { return(m_fGlobalAsa); } inline BOOL CTemplate::FIsZombie() { return m_fZombie; } inline VOID CTemplate::Zombify() { m_fZombie = TRUE; } inline BOOL CTemplate::FDontAttach() { return (m_fDontAttach); } inline BOOL CTemplate::FIsPersisted() { return (m_fIsPersisted); } inline LPTSTR CTemplate::GetApplnPath(SOURCEPATHTYPE pathtype) { Assert (pathtype == SOURCEPATHTYPE_VIRTUAL); return m_szApplnVirtPath; } inline IDispatch *CTemplate::PTypeLibWrapper() { return (m_pdispTypeLibWrapper); } /* **************************************************************************** Class: CIncFile Synopsis: A file included by one or more templates. NOTE: We store an incfile-template dependency by storing a template ptr in m_rgpTemplates. This is efficient but ***will break if we ever change Denali to move its memory around*** */ class CIncFile : private CLinkElem, public IDebugDocumentProvider, public IDebugDocumentText, public IConnectionPointContainer // Source of IDebugDocumentTextEvents { // CIncFileMap is a friend so that it can manipulate CLinkElem private members and to access m_ftLastWriteTime friend class CIncFileMap; private: LONG m_cRefs; // ref count - NOTE LONG required by InterlockedIncrement TCHAR * m_szIncFile; // include file name - NOTE we keep this as a stable ptr to hash table key CRITICAL_SECTION m_csUpdate; // CS for updating the template ptrs array vector m_rgpTemplates; // array of ptrs to templates which include this include file CTemplateConnPt m_CPTextEvents; // Connection point for IDebugDocumentTextEvents BOOLB m_fCsInited; // has CS been initialized yet? CTemplate::CFileMap *GetFilemap(); // Return the filemap pointer from a template public: CIncFile(); HRESULT Init(const TCHAR* szIncFile); ~CIncFile(); HRESULT AddTemplate(CTemplate* pTemplate); void RemoveTemplate(CTemplate* pTemplate); CTemplate* GetTemplate(int iTemplate); BOOL FlushTemplates(); TCHAR * GetIncFileName() { return m_szIncFile; } void OnIncFileDecache(); /* COM public interfaces Implementation of debugging documents. */ // IUnknown methods STDMETHOD(QueryInterface)(const GUID &, void **); STDMETHOD_(ULONG, AddRef)(); STDMETHOD_(ULONG, Release)(); // IDebugDocumentProvider methods STDMETHOD(GetDocument)(/* [out] */ IDebugDocument **ppDebugDoc); // IDebugDocumentInfo (also IDebugDocumentProvider) methods STDMETHOD(GetName)( /* [in] */ DOCUMENTNAMETYPE dnt, /* [out] */ BSTR *pbstrName); STDMETHOD(GetDocumentClassId)(/* [out] */ CLSID *) { return E_NOTIMPL; } // IDebugDocumentText methods STDMETHOD(GetDocumentAttributes)( /* [out] */ TEXT_DOC_ATTR *ptextdocattr); STDMETHOD(GetSize)( /* [out] */ ULONG *pcLines, /* [out] */ ULONG *pcChars); STDMETHOD(GetPositionOfLine)( /* [in] */ ULONG cLineNumber, /* [out] */ ULONG *pcCharacterPosition); STDMETHOD(GetLineOfPosition)( /* [in] */ ULONG cCharacterPosition, /* [out] */ ULONG *pcLineNumber, /* [out] */ ULONG *pcCharacterOffsetInLine); STDMETHOD(GetText)( /* [in] */ ULONG cCharacterPosition, /* [size_is][length_is][out][in] */ WCHAR *pcharText, /* [size_is][length_is][out][in] */ SOURCE_TEXT_ATTR *pstaTextAttr, /* [out][in] */ ULONG *pcChars, /* [in] */ ULONG cMaxChars); STDMETHOD(GetPositionOfContext)( /* [in] */ IDebugDocumentContext *psc, /* [out] */ ULONG *pcCharacterPosition, /* [out] */ ULONG *cNumChars); STDMETHOD(GetContextOfPosition)( /* [in] */ ULONG cCharacterPosition, /* [in] */ ULONG cNumChars, /* [out] */ IDebugDocumentContext **ppsc); // IConnectionPointContainer methods STDMETHOD(EnumConnectionPoints)( /* [out] */ IEnumConnectionPoints __RPC_FAR *__RPC_FAR *ppEnum) { return E_NOTIMPL; // doubt we need this - client is expecting only TextEvents } STDMETHOD(FindConnectionPoint)( /* [in] */ const IID &iid, /* [out] */ IConnectionPoint **ppCP); }; #endif /* _TEMPLATE_H */