#ifndef __VROOT_H__ #define __VROOT_H__ #include #include #include #include #include #include #include #define MAX_VROOT_PATH MAX_PATH + 1 class CVRootTable; #define VROOT_GOOD_SIG 'TOOR' #define VROOT_BAD_SIG 'ROOT' // // There is one of these objects for each of the VRoots defined. It contains // the VRoot parameters. The only parameter used by the VRoot library is the // vroot name, but users of this library should inherit from this and make // their own version which stores all of the other parameters of interest. // class CVRoot : public CRefCount2 { public: CVRoot() { m_fInit = FALSE; m_pPrev = NULL; m_pNext = NULL; m_dwSig = VROOT_GOOD_SIG; } virtual ~CVRoot(); // // initialize this class. // void Init(LPCSTR pszVRootName, CVRootTable *pVRootTable, LPCWSTR wszConfigPath, BOOL fUpgrade ); // // get the vroot name (and optionally its length) from this entry. // LPCSTR GetVRootName(DWORD *pcch = NULL) { _ASSERT(m_fInit); if (pcch != NULL) *pcch = m_cchVRootName; return m_szVRootName; } // get the MB configuration path LPCWSTR GetConfigPath() { return m_wszConfigPath; } // // This needs to be defined by a subclass of CVRoot. // virtual HRESULT ReadParameters(IMSAdminBase *pMB, METADATA_HANDLE hmb) = 0; // // Virtual function for handling orphan VRoot during VRootRescan/VRootDelete // virtual void DispatchDropVRoot() {}; // the next and previous pointers for our list CVRoot *m_pPrev; CVRoot *m_pNext; #ifdef DEBUG LIST_ENTRY m_DebugList; #endif protected: DWORD m_dwSig; BOOL m_fInit; // the name of this vroot (alt.binaries for example) and its length. char m_szVRootName[MAX_VROOT_PATH]; DWORD m_cchVRootName; // the table which owns us CVRootTable *m_pVRootTable; // our config path in the metabase WCHAR m_wszConfigPath[MAX_VROOT_PATH]; // upgrad flag BOOL m_fUpgrade; }; typedef CRefPtr2 VROOTPTR; // // an implementation of CVRoot which reads the parameters likely to be used // by all IIS based client of this VRoot implementation. // class CIISVRoot : public CVRoot { public: virtual ~CIISVRoot() {} void Init(void *pContext, // ignored LPCSTR pszVRootName, // passed to CVRoot::Init CVRootTable *pVRootTable, // passed to CVRoot::Init LPCWSTR pwszConfigPath, BOOL fUpgrade ) // available via GetConfigPath() { CVRoot::Init(pszVRootName, pVRootTable, pwszConfigPath, fUpgrade); m_pContext = pContext; } // get the context pointer void *GetContext() { return m_pContext; } // SSL properties DWORD GetSSLAccessMask() { return m_dwSSL; } // access properties DWORD GetAccessMask() { return m_dwAccess; } // is the content indexed? BOOL IsContentIndexed() { return m_fIsIndexed; } // this method reads the parameters below from the metabase virtual HRESULT ReadParameters(IMSAdminBase *pMB, METADATA_HANDLE hmb); protected: // this method reads a dword from the metabase (wraps GetData()) virtual HRESULT GetDWord(IMSAdminBase *pMB, METADATA_HANDLE hmb, DWORD dwId, DWORD *pdw); // this method reads a string from the metabase (wraps GetData()) virtual HRESULT GetString(IMSAdminBase *pMB, METADATA_HANDLE hmb, DWORD dwId, LPWSTR szString, DWORD *pcString); protected: // parameters given to use by the constructor void *m_pContext; // parameters read from the metabase BOOL m_fIsIndexed; // is the content indexed? BOOL m_fDontLog; // should logging be disabled here? DWORD m_dwAccess; // access permissions bitmask DWORD m_dwSSL; // SSL access perm's bitmask }; // // a subclass of the above which hides the fact that context is a void *. // // template arguments: // _context_type - the type for the context. must be castable to void *. // template class CIISVRootTmpl : public CIISVRoot { public: virtual ~CIISVRootTmpl() {} void Init(_context_type pContext, LPCSTR pszVRootName, CVRootTable *pVRootTable, LPCWSTR pwszConfigPath, BOOL fUpgrade ) { CIISVRoot::Init((void *) pContext, pszVRootName, pVRootTable, pwszConfigPath, fUpgrade ); } // return the context pointer (mostly likely a pointer to an IIS // instance) _context_type GetContext() { return (_context_type) CIISVRoot::GetContext(); } }; // // this is a type that points to a function which can create CVRoot objects. // use it to create your own version of the CVRoot class. // // parameters: // pContext - the context pointer passed into CVRootTable // pszVRootName - the name of the vroot // pwszConfigPath - a Unicode string with the path in the metabase for // this vroot's configuration information. // typedef VROOTPTR (*PFNCREATE_VROOT)(void *pContext, LPCSTR pszVRootName, CVRootTable *pVRootTable, LPCWSTR pwszConfigPath, BOOL fUpgrade ); // // a function of this type is called when the vroot table is scanned. it // is passed a copy of the context pointer // typedef void (*PFN_VRTABLE_SCAN_NOTIFY)(void *pContext); typedef void (*PFN_VRENUM_CALLBACK)(void *pEnumContext, CVRoot *pVRoot); // // The CVRootTable object keeps a list of VRoots and can find a vroot for // a given folder. // class CVRootTable { public: static HRESULT GlobalInitialize(); static void GlobalShutdown(); CVRootTable(void *pContext, PFNCREATE_VROOT pfnCreateVRoot, PFN_VRTABLE_SCAN_NOTIFY pfnScanNotify); virtual ~CVRootTable(); HRESULT Initialize(LPCSTR pszMBPath, BOOL fUpgrade ); HRESULT Shutdown(void); HRESULT FindVRoot(LPCSTR pszPath, VROOTPTR *ppVRoot); HRESULT EnumerateVRoots(void *pEnumContext, PFN_VRENUM_CALLBACK pfnCallback); private: VROOTPTR NewVRoot(); HRESULT ScanVRoots( BOOL fUpgrade ); HRESULT InitializeVRoot(CVRoot *pVRoot); HRESULT InitializeVRoots(); HRESULT ScanVRootsRecursive(METADATA_HANDLE hmbParent, LPCWSTR pwszKey, LPCSTR pszVRootName, LPCWSTR pwszPath, BOOL fUpgrade ); void InsertVRoot(VROOTPTR pVRoot); // find a vroot HRESULT FindVRootInternal(LPCSTR pszPath, VROOTPTR *ppVRoot); // convert a config path to a vroot name void ConfigPathToVRootName(LPCWSTR pwszConfigPath, LPSTR szVRootName); // used to pass metabase notifications back into this object static void MBChangeNotify(void *pThis, DWORD cChangeList, MD_CHANGE_OBJECT_W pcoChangeList[]); // parameters changed under a vroot void VRootChange(LPCWSTR pwszConfigPath, LPCSTR pszVRootName); // a vroot was deleted void VRootDelete(LPCWSTR pwszConfigPath, LPCSTR pszVRootName); // a vroot was added void VRootAdd(LPCWSTR pwszConfigPath, LPCSTR pszVRootName); // rescan the whole vroot list void VRootRescan(void); #ifdef DEBUG LIST_ENTRY m_DebugListHead; CShareLockNH m_DebugListLock; void DebugPushVRoot( CVRoot *pVRoot ) { _ASSERT( pVRoot ); m_DebugListLock.ExclusiveLock(); InsertTailList( &m_DebugListHead, &pVRoot->m_DebugList ); m_DebugListLock.ExclusiveUnlock(); } void DebugExpungeVRoot( CVRoot *pVRoot ) { m_DebugListLock.ExclusiveLock(); RemoveEntryList( &pVRoot->m_DebugList ); m_DebugListLock.ExclusiveUnlock(); } #endif // locking: for walking the list either m_lock.ShareLock must be // held or m_cs must be held. For editting the list both // m_lock.ExclusiveLock must be held and m_cs must be held. // When making large changes (such as rebuilding the entire list) // m_cs should be held until all of the changes are complete. // lock for the vroot list CShareLockNH m_lock; // critical section used for making global changes on the vroot // list. this is used to make sure that only one thread can editting // the list at a time CRITICAL_SECTION m_cs; // our context pointer void *m_pContext; // the path to our metabase area WCHAR m_wszRootPath[MAX_VROOT_PATH]; DWORD m_cchRootPath; // have we been initialized? BOOL m_fInit; // are we shutting down? BOOL m_fShuttingDown; // function to create a new vroot object PFNCREATE_VROOT m_pfnCreateVRoot; // function to call when the vroot table is rescanned PFN_VRTABLE_SCAN_NOTIFY m_pfnScanNotify; // the list of vroots TFList m_listVRoots; // this RW lock is used to figure out when all of the VRoot objects // have shutdown. They hold a ShareLock on it for their lifetime, // so the CVRootTable can grab an ExclusiveLock to wait for all of // the VRoot objects to disappear. CShareLockNH m_lockVRootsExist; // these guys need access to m_lockVRootsExist friend void CVRoot::Init(LPCSTR, CVRootTable *, LPCWSTR, BOOL); friend CVRoot::~CVRoot(); }; // // this is a templated version of CIISVRootTable. You tell it the version of // CVRoot that you are using, and the context type that you are using. // // template arguments: // _CVRoot - a subclass of CVRoot that you'll be using // _context_type - the type that you'll be using for context information. // this must be castable to void *. // template class CIISVRootTable { public: CIISVRootTable(_context_type pContext, PFN_VRTABLE_SCAN_NOTIFY pfnScanNotify) : impl((void *) pContext, CIISVRootTable<_CVRoot, _context_type>::CreateVRoot, pfnScanNotify) { } HRESULT Initialize(LPCSTR pszMBPath, BOOL fUpgrade ) { return impl.Initialize(pszMBPath, fUpgrade); } HRESULT Shutdown(void) { return impl.Shutdown(); } HRESULT FindVRoot(LPCSTR pszPath, CRefPtr2<_CVRoot> *ppVRoot) { return impl.FindVRoot(pszPath, (VROOTPTR *) ppVRoot); } HRESULT EnumerateVRoots(void *pEnumContext, PFN_VRENUM_CALLBACK pfnCallback) { return impl.EnumerateVRoots(pEnumContext, pfnCallback); } private: static VROOTPTR CreateVRoot(void *pContext, LPCSTR pszVRootName, CVRootTable *pVRootTable, LPCWSTR pwszConfigPath, BOOL fUpgrade) { // create the vroot object CRefPtr2<_CVRoot> pVRoot = new _CVRoot; // initialize it pVRoot->Init((_context_type) pContext, pszVRootName, pVRootTable, pwszConfigPath, fUpgrade ); return (_CVRoot *)pVRoot; } CVRootTable impl; }; #endif