windows-nt/Source/XPSP1/NT/inetsrv/iis/svcs/cmp/asp/applmgr.h

682 lines
18 KiB
C
Raw Normal View History

2020-09-26 03:20:57 -05:00
/*===================================================================
Microsoft Denali
Microsoft Confidential.
Copyright 1996 Microsoft Corporation. All Rights Reserved.
Component: Appln Manager
File: Applmgr.h
Owner: PramodD
This is the application manager header file.
===================================================================*/
#ifndef APPLMGR_H
#define APPLMGR_H
#include "debug.h"
#include "hashing.h"
#include "cachemgr.h"
#include "appcnfg.h"
#include "compcol.h"
#include "fileapp.h"
#include "idhash.h"
#include "memcls.h"
#include "ftm.h"
#include "disptch2.h"
/*===================================================================
#defines
===================================================================*/
#define NUM_APPLMGR_HASHING_BUCKETS 17
#define NOTIFICATION_BUFFER_SIZE 4096
#define INVALID_THREADID 0xFFFFFFFF
#include "asptlb.h"
// 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
/*===================================================================
Forward declarations
===================================================================*/
class CComponentCollection;
class CSessionMgr;
class CViperActivity;
class CActiveScriptEngine;
struct IDebugApplication;
struct IDebugApplicationNode;
/*===================================================================
C A p p l n V a r i a n t s
===================================================================*/
class CApplnVariants : public IVariantDictionaryImpl
{
private:
ULONG m_cRefs; // ref count
CAppln * m_pAppln; // pointer to parent object
CompType m_ctColType; // type of components in collection
CSupportErrorInfo m_ISupportErrImp; // implementation of ISupportErr
HRESULT ObjectNameFromVariant(VARIANT &vKey, WCHAR **ppwszName,
BOOL fVerify = FALSE);
public:
CApplnVariants();
~CApplnVariants();
HRESULT Init(CAppln *pAppln, CompType ctColType);
HRESULT UnInit();
// The Big Three
STDMETHODIMP QueryInterface(const GUID &, void **);
STDMETHODIMP_(ULONG) AddRef();
STDMETHODIMP_(ULONG) Release();
// OLE Automation Interface
STDMETHODIMP get_Item(VARIANT Var, VARIANT *pvar);
STDMETHODIMP put_Item(VARIANT varKey, VARIANT var);
STDMETHODIMP putref_Item(VARIANT varKey, VARIANT var);
STDMETHODIMP get_Key(VARIANT Var, VARIANT *pvar);
STDMETHODIMP get__NewEnum(IUnknown **ppEnumReturn);
STDMETHODIMP get_Count(int *pcValues);
STDMETHODIMP Remove(VARIANT VarKey);
STDMETHODIMP RemoveAll();
// Cache on per-class basis
ACACHE_INCLASS_DEFINITIONS()
};
/*===================================================================
C A p p l n
===================================================================*/
class CAppln : public IApplicationObjectImpl, public CLinkElem, public CFTMImplementation
{
friend class CApplnMgr;
friend class CApplnCleanupMgr;
friend class CDirMonitorEntry;
friend class CApplnVariants;
private:
//========= Misc flags
DWORD m_fInited : 1; // Are we initialized?
DWORD m_fFirstRequestRan : 1; // 1st request for this app ran?
DWORD m_fGlobalChanged : 1; // Global.asa has changed?
DWORD m_fDeleteInProgress : 1; // Delete event posted?
DWORD m_fTombstone : 1; // ASP is done with the app?
DWORD m_fDebuggable : 1; // Debugging enabled for this app?
//========= Notification flags
// ReadDirectoryChangesW done?
DWORD m_fNotificationAdded : 1;
// change notification should use impersonation?
DWORD m_fUseImpersonationHandle : 1;
//========= Ref counts
DWORD m_cRefs;
DWORD m_cRequests; // Active requests count
DWORD m_cSessions; // Session count
//========= Application's key, path, global.asa
// metabase key (unique app id)
TCHAR *m_pszMetabaseKey;
// physical application directory path
TCHAR *m_pszApplnPath;
// virtual application directory path
TCHAR *m_pszApplnVRoot;
// Path to global.asa for application
TCHAR *m_pszGlobalAsa;
// Pointer to compliled template for global.asa
CTemplate *m_pGlobalTemplate;
//========= Application's Session Manager
CSessionMgr *m_pSessionMgr; // Session manager for this app
//========= Application's Configuration Settings
CAppConfig *m_pAppConfig; // Application Configuration object
//========= Application's Component Collection
CComponentCollection *m_pApplCompCol; // Application scope objects
//========= Application's dictionaries for presenting component collection
CApplnVariants *m_pProperties;
CApplnVariants *m_pTaggedObjects;
//========= Viper Activity
// Application's activity (for thread-locked appls)
CViperActivity *m_pActivity;
// ======== COM+ Services Config Object
IUnknown *m_pServicesConfig;
//========= Critical section for internal lock
CRITICAL_SECTION m_csInternalLock;
//========= External lock support
CRITICAL_SECTION m_csApplnLock;
DWORD m_dwLockThreadID; // thread which locked
DWORD m_cLockRefCount; // lock count
//========= Notification support
// Identifiers stored by notification system
CPtrArray m_rgpvDME; // list of directory monitor entries
CPtrArray m_rgpvFileAppln; // list of entries relating files to applications
// User impersonation handle for UNC change notification
HANDLE m_hUserImpersonation;
//========= Type Library wrapper from GLOBAL.ASA
IDispatch *m_pdispGlobTypeLibWrapper;
//========= SupportErrorInfo
// Interface to indicate that we support ErrorInfo reporting
CSupportErrorInfo m_ISuppErrImp;
//========= Debugging Support
// root node for browsing of running documents
IDebugApplicationNode *m_pAppRoot;
HRESULT InitServicesConfig();
// proc used to asynchronously cleanup the app
static DWORD __stdcall ApplnCleanupProc(VOID *pArg);
public:
CAppln();
~CAppln();
HRESULT Init
(
TCHAR *pszApplnKey,
TCHAR *pszApplnPath,
CIsapiReqInfo *pIReq,
HANDLE hUserImpersonation
);
// cnvert to tombstone state
HRESULT UnInit();
// create application's activity as clone of param
HRESULT BindToActivity(CViperActivity *pActivity = NULL);
// set (and remember) global.asa for this app
HRESULT SetGlobalAsa(const TCHAR *pszGlobalAsa);
// make sure script didn't leave locks
HRESULT UnLockAfterRequest();
// Non-delegating object IUnknown
STDMETHODIMP QueryInterface(REFIID, void **);
STDMETHODIMP_(ULONG) AddRef();
STDMETHODIMP_(ULONG) Release();
// Tombstone stub
HRESULT CheckForTombstone();
// Restart an application (such as when global.asa changes)
HRESULT Restart(BOOL fForceRestart = FALSE);
// IApplicationObject functions
STDMETHODIMP Lock();
STDMETHODIMP UnLock();
STDMETHODIMP get_Value(BSTR bstr, VARIANT *pvar);
STDMETHODIMP put_Value(BSTR bstr, VARIANT var);
STDMETHODIMP putref_Value(BSTR bstr, VARIANT var);
STDMETHODIMP get_Contents(IVariantDictionary **ppDictReturn);
STDMETHODIMP get_StaticObjects(IVariantDictionary **ppDictReturn);
// Application config related methods
CAppConfig *QueryAppConfig();
BOOL FConfigNeedsUpdate();
HRESULT UpdateConfig(CIsapiReqInfo *pIReq, BOOL *pfRestart = NULL, BOOL *pfFlushAll = NULL);
// inline methods to access member properties
CSessionMgr *PSessionMgr();
CComponentCollection *PCompCol();
CViperActivity *PActivity();
IDebugApplicationNode *PAppRoot();
CTemplate *PGlobalTemplate();
void SetGlobalTemplate(CTemplate *);
TCHAR *GetMetabaseKey();
TCHAR *GetApplnPath(SOURCEPATHTYPE = SOURCEPATHTYPE_PHYSICAL);
TCHAR *GetGlobalAsa();
DWORD GetNumSessions();
DWORD GetNumRequests();
BOOL FGlobalChanged();
BOOL FDebuggable();
BOOL FTombstone();
BOOL FHasGlobalAsa();
BOOL FFirstRequestRun();
IDispatch *PGlobTypeLibWrapper();
IUnknown *PServicesConfig();
void SetFirstRequestRan();
void SetGlobTypeLibWrapper(IDispatch *);
HRESULT AddDirMonitorEntry(CDirMonitorEntry *);
HRESULT AddFileApplnEntry(CFileApplnList *pFileAppln);
CASPDirMonitorEntry *FPathMonitored(LPCTSTR pszPath);
// Misc inline methods
void InternalLock();
void InternalUnLock();
void IncrementSessionCount();
void DecrementSessionCount();
void IncrementRequestCount();
void DecrementRequestCount();
// AssertValid()
public:
#ifdef DBG
virtual void AssertValid() const;
#else
virtual void AssertValid() const {}
#endif
// Cache on per-class basis
ACACHE_INCLASS_DEFINITIONS()
// Trace Log info -- keep in both free & checked builds so that ntsd extension will work for both builds
// for FREE build, trace log is always NULL. Checked builds, it must be enabled.
static PTRACE_LOG gm_pTraceLog;
};
/*===================================================================
C A p p l n inlines
===================================================================*/
inline CSessionMgr *CAppln::PSessionMgr()
{
return m_pSessionMgr;
}
inline CComponentCollection *CAppln::PCompCol()
{
return m_pApplCompCol;
}
inline CViperActivity *CAppln::PActivity()
{
return m_pActivity;
}
inline IDebugApplicationNode *CAppln::PAppRoot()
{
return m_pAppRoot;
}
inline TCHAR *CAppln::GetMetabaseKey()
{
return m_pszMetabaseKey;
}
inline TCHAR *CAppln::GetApplnPath(SOURCEPATHTYPE pathtype)
{
return (pathtype == SOURCEPATHTYPE_VIRTUAL? m_pszApplnVRoot :
(pathtype == SOURCEPATHTYPE_PHYSICAL? m_pszApplnPath : NULL));
}
inline CTemplate *CAppln::PGlobalTemplate()
{
return m_pGlobalTemplate;
}
inline void CAppln::SetGlobalTemplate(CTemplate *pTemplate)
{
pTemplate->AddRef();
m_pGlobalTemplate = pTemplate;
}
inline TCHAR *CAppln::GetGlobalAsa()
{
return m_pszGlobalAsa;
}
inline DWORD CAppln::GetNumSessions()
{
return m_cSessions;
}
inline DWORD CAppln::GetNumRequests()
{
return m_cRequests;
}
inline BOOL CAppln::FGlobalChanged()
{
return m_fGlobalChanged;
}
inline BOOL CAppln::FDebuggable()
{
return m_fDebuggable;
}
inline BOOL CAppln::FTombstone()
{
return m_fTombstone;
}
inline BOOL CAppln::FHasGlobalAsa()
{
return (m_pszGlobalAsa != NULL);
}
inline BOOL CAppln::FFirstRequestRun()
{
return m_fFirstRequestRan;
}
inline void CAppln::SetFirstRequestRan()
{
Assert(m_fInited);
m_fFirstRequestRan = TRUE;
}
inline IDispatch *CAppln::PGlobTypeLibWrapper()
{
return m_pdispGlobTypeLibWrapper;
}
inline IUnknown *CAppln::PServicesConfig() {
return m_pServicesConfig;
}
inline void CAppln::SetGlobTypeLibWrapper(IDispatch *pdisp)
{
if (m_pdispGlobTypeLibWrapper)
m_pdispGlobTypeLibWrapper->Release();
m_pdispGlobTypeLibWrapper = pdisp;
if (m_pdispGlobTypeLibWrapper)
m_pdispGlobTypeLibWrapper->AddRef();
}
inline void CAppln::IncrementSessionCount()
{
Assert(m_fInited);
InterlockedIncrement((LPLONG)&m_cSessions);
}
inline void CAppln::DecrementSessionCount()
{
Assert(m_fInited);
InterlockedDecrement((LPLONG)&m_cSessions);
}
inline void CAppln::IncrementRequestCount()
{
Assert(m_fInited);
InterlockedIncrement((LPLONG)&m_cRequests);
}
inline void CAppln::DecrementRequestCount()
{
Assert(m_fInited);
InterlockedDecrement((LPLONG)&m_cRequests);
}
inline void CAppln::InternalLock()
{
Assert(m_fInited);
EnterCriticalSection(&m_csInternalLock);
}
inline void CAppln::InternalUnLock()
{
Assert(m_fInited);
LeaveCriticalSection(&m_csInternalLock);
}
inline CAppConfig * CAppln::QueryAppConfig()
{
return m_pAppConfig;
}
inline BOOL CAppln::FConfigNeedsUpdate()
{
return m_pAppConfig->fNeedUpdate();
}
/*===================================================================
C A p p l n M g r
===================================================================*/
class CApplnMgr : public CHashTable
{
private:
// Flags
DWORD m_fInited : 1; // Are we initialized?
DWORD m_fHashTableInited : 1; // Need to UnInit hash table?
DWORD m_fCriticalSectionInited : 1; // Need to delete CS?
// Critical section for locking
CRITICAL_SECTION m_csLock;
// List of script engines that need to be closed on next request.
// (See comments in code, esp. CApplnMgr::AddEngine)
CDblLink m_listEngineCleanup;
public:
CApplnMgr();
~CApplnMgr();
HRESULT Init();
HRESULT UnInit();
// CAppln manipulations
HRESULT AddAppln
(
TCHAR *pszApplnKey,
TCHAR *pszApplnPath,
CIsapiReqInfo *pIReq,
HANDLE hUserImpersonation,
CAppln **ppAppln
);
HRESULT FindAppln
(
TCHAR *pszApplnKey,
CAppln **ppAppln
);
HRESULT DeleteApplicationIfExpired(CAppln *pAppln);
HRESULT DeleteAllApplications();
HRESULT RestartApplications(BOOL fRestartAllApplications = FALSE);
// Add an engine to the deferred cleanup list/release engines in the list
HRESULT AddEngine(CActiveScriptEngine *pEng);
void CleanupEngines();
// inlines
void Lock();
void UnLock();
HANDLE HDeleteEvent();
void SetDeleteEvent(void);
};
/*===================================================================
C A p p l n M g r inlines
===================================================================*/
inline void CApplnMgr::Lock()
{
Assert(m_fInited);
EnterCriticalSection(&m_csLock);
}
inline void CApplnMgr::UnLock()
{
Assert(m_fInited);
LeaveCriticalSection( &m_csLock );
}
/*===================================================================
C A p p l n C l e a n u p M g r
===================================================================*/
class CApplnCleanupMgr
{
private:
// Flags
DWORD m_fInited : 1; // Are we initialized?
DWORD m_fCriticalSectionInited : 1; // Need to delete CS?
DWORD m_fThreadAlive : 1; // worker thread alive?
// Critical section for locking
CRITICAL_SECTION m_csLock;
HANDLE m_hAppToCleanup; // event to signal when there is an app to cleanup
CLinkElem m_List;
CAppln *Head();
void AddElem(CAppln *pAppln);
void RemoveElem(CAppln *pAppln);
public:
CApplnCleanupMgr();
~CApplnCleanupMgr();
HRESULT Init();
HRESULT UnInit();
// CAppln manipulations
HRESULT AddAppln
(
CAppln *ppAppln
);
void Wakeup();
private:
// inlines
void Lock();
void UnLock();
// thread proc used to cleanup deleted applications
static DWORD __stdcall ApplnCleanupThread(VOID *pArg);
void ApplnCleanupDoWork();
};
/*===================================================================
C A p p l n C l e a n u p M g r inlines
===================================================================*/
inline void CApplnCleanupMgr::Lock()
{
Assert(m_fCriticalSectionInited);
EnterCriticalSection(&m_csLock);
}
inline void CApplnCleanupMgr::UnLock()
{
Assert(m_fCriticalSectionInited);
LeaveCriticalSection( &m_csLock );
}
inline CAppln *CApplnCleanupMgr::Head()
{
return ((m_List.m_pNext == &m_List) ? NULL : (CAppln *)m_List.m_pNext);
}
inline void CApplnCleanupMgr::AddElem(CAppln *pAppln)
{
pAppln->m_pNext = &m_List;
pAppln->m_pPrev = m_List.m_pPrev;
m_List.m_pPrev->m_pNext = pAppln;
m_List.m_pPrev = pAppln;
}
inline void CApplnCleanupMgr::RemoveElem(CAppln *pAppln)
{
pAppln->m_pPrev->m_pNext = pAppln->m_pNext;
pAppln->m_pNext->m_pPrev = pAppln->m_pPrev;
}
inline void CApplnCleanupMgr::Wakeup()
{
SetEvent(m_hAppToCleanup);
}
/*===================================================================
C A p p l n M g r thread proc prototype
===================================================================*/
void __cdecl RestartAppsThreadProc(VOID *arg);
/*===================================================================
Globals
===================================================================*/
extern CApplnMgr g_ApplnMgr;
extern DWORD g_nApplications;
extern DWORD g_nApplicationsRestarting;
/*===================================================================
C A p p l n I t e r a t o r
===================================================================*/
class CApplnIterator
{
private:
CApplnMgr *m_pApplnMgr;
CAppln *m_pCurr;
BOOL m_fEnded; // iterator ended
public:
CApplnIterator(void);
virtual ~CApplnIterator(void);
public:
HRESULT Start(CApplnMgr *pApplnMgr = NULL);
HRESULT Stop(void);
CAppln * Next(void);
};
#endif // APPLMGR_H