/* * V R E N U M . C P P * * Virtual root enumeration * * Copyright 1986-1997 Microsoft Corporation, All Rights Reserved */ #include "_vroot.h" LPCWSTR __fastcall PwszStripMetaPrefix (LPCWSTR pwszUrl) { // All metabase virtual roots are identified by the // metabase path, minus a given prefix. // // These paths uniformly look like: // // '/lm/w3svc/' '/root' // // Since the is an unnamed integer, the trick to // skipping this stuff is to search for '/root' in the string // and then bump ahead 5 characters. // Assert (pwszUrl); if (NULL == (pwszUrl = wcsstr(pwszUrl, L"/root"))) return NULL; return pwszUrl + 5; } // CVRootCache --------------------------------------------------------------- // VOID CChildVRCache::OnNotify (DWORD dwElements, MD_CHANGE_OBJECT_W pcoList[]) { // Go through the list of changes and see if any scriptmap/vrpath/bindings // changes have been made to the metabase. If any have changed, then we // want to invalidate the cache. // for (UINT ice = 0; ice < dwElements; ice++) { for (UINT ico = 0; ico < pcoList[ice].dwMDNumDataIDs; ico++) { // Only invalidate if the stuff that we use to compute our // values changes changes. // if ((pcoList[ice].pdwMDDataIDs[ico] == MD_SERVER_BINDINGS) || (pcoList[ice].pdwMDDataIDs[ico] == MD_VR_PATH)) { DebugTrace ("Dav: CVRoot: invalidating cache\n"); Invalidate(); return; } } } } VOID CChildVRCache::RefreshOp(const IEcb& ecb) { // Out with the old... // m_cache.Clear(); m_sb.Clear(); // ... and in with the new! // (void) ScCacheVroots(ecb); } // Cache construction -------------------------------------------------------- // // class CVirtualRootMetaOp -------------------------------------------------- // class CVirtualRootMetaOp : public CMetaOp { enum { DONT_INHERIT = 0 }; CVRCache& m_cache; ChainedStringBuffer& m_sb; LPCWSTR m_pwszServerDefault; UINT m_cchServerDefault; // non-implemented // CVirtualRootMetaOp& operator=( const CVirtualRootMetaOp& ); CVirtualRootMetaOp( const CVirtualRootMetaOp& ); // Subclass' operation to perform for each node where // a value is explicitly set. // virtual SCODE __fastcall ScOp(LPCWSTR pwszMbPath, UINT cch); public: virtual ~CVirtualRootMetaOp() {} CVirtualRootMetaOp (const IEcb * pecb, LPCWSTR pwszPath, UINT cchServerDefault, LPCWSTR pwszServerDefault, ChainedStringBuffer& sb, CVRCache& cache) : CMetaOp (pecb, pwszPath, MD_VR_PATH, STRING_METADATA, FALSE), m_pwszServerDefault(pwszServerDefault), m_cchServerDefault(cchServerDefault), m_cache(cache), m_sb(sb) { } }; DEC_CONST WCHAR gc_wszLmW3svc[] = L"/lm/w3svc"; DEC_CONST UINT gc_cchLmW3svc = CchConstString(gc_wszLmW3svc); SCODE __fastcall CVirtualRootMetaOp::ScOp(LPCWSTR pwszMbPath, UINT cch) { CStackBuffer wszBuf; LPWSTR pwsz; LPCWSTR pwszUrl; SCODE sc = S_OK; auto_ref_ptr pvr; auto_ref_ptr pMDData; Assert (MD_VR_PATH == m_dwId); Assert (STRING_METADATA == m_dwType); // If the url ends in a trailing slash, snip it... // if (cch && (L'/' == pwszMbPath[cch - 1])) cch -= 1; // Construct the full metabase path // if (NULL == wszBuf.resize(CbSizeWsz(gc_cchLmW3svc + cch))) return E_OUTOFMEMORY; memcpy (wszBuf.get(), gc_wszLmW3svc, gc_cchLmW3svc * sizeof(WCHAR)); memcpy (wszBuf.get() + gc_cchLmW3svc, pwszMbPath, cch * sizeof(WCHAR)); wszBuf[gc_cchLmW3svc + cch] = L'\0'; // Make a copy of the meta path for use as the cache // key and for use by the CVRoot object. // _wcslwr (wszBuf.get()); pwsz = m_sb.Append (CbSizeWsz(gc_cchLmW3svc + cch), wszBuf.get()); // Create a CVRoot object and cache it. First get the metadata // associated with this path and then construct the CVRoot out // of that. // sc = HrMDGetData (*m_pecb, pwsz, pwsz, pMDData.load()); if (FAILED (sc)) goto ret; if (NULL != (pwszUrl = PwszStripMetaPrefix (pwsz))) { //$ RAID:304272: There is a stress app/case where roots // are being created that have no vrpath. // if (NULL != pMDData->PwszVRPath()) { // Construct the virtual root object // pvr = new CVRoot (pwsz, static_cast(pwszUrl - pwsz), m_cchServerDefault, m_pwszServerDefault, pMDData.get()); DebugTrace ("Dav: CVRoot: caching vroot\n" " MetaPath: %S\n" " VrPath: %S\n" " Bindings: %S\n", pwsz, pMDData->PwszVRPath(), pMDData->PwszBindings()); m_cache.FSet (CRCWsz(pwsz), pvr); } // //$ RAID:304272: end } ret: return sc; } SCODE CChildVRCache::ScCacheVroots (const IEcb& ecb) { SCODE sc = S_OK; CVirtualRootMetaOp vrmo(&ecb, gc_wszLmW3svc, m_cchServerDefault, m_wszServerDefault, m_sb, m_cache); // Gather all the virtual root information // sc = vrmo.ScMetaOp(); if (FAILED (sc)) goto ret; ret: return sc; } // CFindChildren ------------------------------------------------------------- // BOOL CChildVRCache::CFindChildren::operator()( /* [in] */ const CRCWsz& crcwsz, /* [in] */ const auto_ref_ptr& arpRoot) { // If the root we are checking is a proper ancestor to the // vroot we are checking, then we will want to push it onto // the stack. // if (!_wcsnicmp (crcwsz.m_pwsz, m_pwsz, m_cch)) { LPCWSTR pwsz = crcwsz.m_pwsz; // There are two interesting cases here. // // - The child vroot has a physical path that has // diverged from the parent's. // // - The child vroot has a physical path that aligns // perfectly with the parent. // // ie. "/fs" has a VrPath of "f:\fs" and "/fs/bvt" has // a VrPath of "f:\fs\bvt" // // In this latter case, needs to be handled by the // piece of code that is doing the traversing. In // most cases, this done by seeing if we traverse // down into a vroot, etc. // Assert (L'\0' == m_pwsz[m_cch]); if ((L'/' == pwsz[m_cch]) || (L'/' == pwsz[m_cch - 1])) { // Push it on the stack // m_vrl.push_back (CSortableStrings(m_sb.AppendWithNull(pwsz))); } } return TRUE; }