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.
541 lines
13 KiB
541 lines
13 KiB
/*
|
|
* D A V M B . H
|
|
*
|
|
* DAV metabase
|
|
*
|
|
* Copyright 1986-1997 Microsoft Corporation, All Rights Reserved
|
|
*/
|
|
|
|
#ifndef _DAVMB_H_
|
|
#define _DAVMB_H_
|
|
|
|
#include <initguid.h>
|
|
#include <exguid.h>
|
|
#include <iadmw.h>
|
|
#include <iwamreg.h>
|
|
#include <iiscnfg.h>
|
|
#include <autoptr.h>
|
|
#include <exo.h>
|
|
#include <malloc.h>
|
|
#include <szsrc.h>
|
|
#include <ex\refcnt.h>
|
|
|
|
// Advising the notification sink --------------------------------------------
|
|
//
|
|
HRESULT
|
|
HrAdviseSink( IMSAdminBase& msAdminBase,
|
|
IMSAdminBaseSink * pMSAdminBaseSink,
|
|
DWORD * pdwCookie );
|
|
|
|
// Unadvising the notification sink ------------------------------------------
|
|
//
|
|
VOID
|
|
UnadviseSink( IMSAdminBase& msAdminBase,
|
|
DWORD dwCookie );
|
|
|
|
// Constructing metabase change object ---------------------------------
|
|
//
|
|
inline
|
|
SCODE ScBuildChangeObject(LPCWSTR pwszBase,
|
|
UINT cchBase,
|
|
LPCWSTR pwszPath,
|
|
UINT cchPath,
|
|
DWORD dwMDChangeType,
|
|
const DWORD * pdwMDDataId,
|
|
LPWSTR pwszBuf,
|
|
UINT * pcchBuf,
|
|
PMD_CHANGE_OBJECT_W pMdChObjW)
|
|
{
|
|
SCODE sc = S_OK;
|
|
UINT cchT;
|
|
|
|
Assert(0 == cchBase || pwszBase);
|
|
Assert(0 == cchPath || pwszPath);
|
|
Assert(pdwMDDataId);
|
|
Assert(pcchBuf);
|
|
Assert(0 == *pcchBuf || pwszBuf);
|
|
Assert(pMdChObjW);
|
|
|
|
// Ambiguous trace. I am comenting it out...
|
|
//
|
|
/* DebugTrace( "ScBuildChangeObject() called:\n"
|
|
" Base path: '%S'\n"
|
|
" Remaining path: '%S'\n"
|
|
" Change type: 0x%08lX\n"
|
|
" Data ID: 0x%08lX\n",
|
|
pwszBase ? pwszBase : L"NONE",
|
|
pwszPath ? pwszPath : L"NONE",
|
|
dwMDChangeType,
|
|
*pdwMDDataId );*/
|
|
|
|
// Construct the path change is occuring on.
|
|
//
|
|
BOOL fNeedSeparator = FALSE;
|
|
BOOL fNeedTerminator = FALSE;
|
|
|
|
// Make sure that we do not assemble the path with
|
|
// double '/' in the middle.
|
|
//
|
|
if (cchBase &&
|
|
cchPath &&
|
|
L'/' == pwszBase[cchBase - 1] &&
|
|
L'/' == pwszPath[0])
|
|
{
|
|
// Get rid of one '/'
|
|
//
|
|
cchBase--;
|
|
}
|
|
else if ((0 == cchBase || L'/' != pwszBase[cchBase - 1]) &&
|
|
(0 == cchPath || L'/' != pwszPath[0]))
|
|
{
|
|
// We need a separator
|
|
//
|
|
fNeedSeparator = TRUE;
|
|
}
|
|
|
|
// Check out if we need terminating '/' at the end.
|
|
//
|
|
if (cchPath && L'/' != pwszPath[cchPath - 1])
|
|
{
|
|
fNeedTerminator = TRUE;
|
|
}
|
|
|
|
cchT = cchBase + cchPath + 1;
|
|
if (fNeedSeparator)
|
|
{
|
|
cchT++;
|
|
}
|
|
if (fNeedTerminator)
|
|
{
|
|
cchT++;
|
|
}
|
|
|
|
if (*pcchBuf < cchT)
|
|
{
|
|
*pcchBuf = cchT;
|
|
sc = S_FALSE;
|
|
}
|
|
else
|
|
{
|
|
cchT = 0;
|
|
if (cchBase)
|
|
{
|
|
memcpy(pwszBuf, pwszBase, cchBase * sizeof(WCHAR));
|
|
cchT += cchBase;
|
|
}
|
|
if (fNeedSeparator)
|
|
{
|
|
pwszBuf[cchT] = L'/';
|
|
cchT++;
|
|
}
|
|
if (cchPath)
|
|
{
|
|
memcpy(pwszBuf + cchT, pwszPath, cchPath * sizeof(WCHAR));
|
|
cchT += cchPath;
|
|
}
|
|
if (fNeedTerminator)
|
|
{
|
|
pwszBuf[cchT] = L'/';
|
|
cchT++;
|
|
}
|
|
pwszBuf[cchT] = L'\0';
|
|
|
|
pMdChObjW->pszMDPath = pwszBuf;
|
|
pMdChObjW->dwMDChangeType = dwMDChangeType;
|
|
pMdChObjW->dwMDNumDataIDs = 1;
|
|
pMdChObjW->pdwMDDataIDs = const_cast<DWORD *>(pdwMDDataId);
|
|
}
|
|
|
|
return sc;
|
|
}
|
|
|
|
class LFUData
|
|
{
|
|
// Approximate number of hits via Touch()
|
|
//
|
|
DWORD m_dwcHits;
|
|
|
|
// NOT IMPLEMENTED
|
|
//
|
|
LFUData& operator=(const LFUData&);
|
|
LFUData(const LFUData&);
|
|
|
|
public:
|
|
// CREATORS
|
|
//
|
|
LFUData() : m_dwcHits(0) {}
|
|
|
|
// MANIPULATORS
|
|
//
|
|
|
|
// --------------------------------------------------------------------
|
|
//
|
|
// Touch()
|
|
//
|
|
// Increments the hit count. Note that this is done without an
|
|
// interlocked operation. The expectation is that the actual count
|
|
// value is just a hint and as such, it is not critical that it be
|
|
// exactly accurate.
|
|
//
|
|
VOID Touch()
|
|
{
|
|
++m_dwcHits;
|
|
}
|
|
|
|
// --------------------------------------------------------------------
|
|
//
|
|
// DwGatherAndResetHitCount()
|
|
//
|
|
// Fetches and resets the hit count. Again, the actual value is
|
|
// unimportant, so there is no interlocked operation.
|
|
//
|
|
DWORD DwGatherAndResetHitCount()
|
|
{
|
|
DWORD dwcHits = m_dwcHits;
|
|
|
|
m_dwcHits = 0;
|
|
|
|
return dwcHits;
|
|
}
|
|
};
|
|
|
|
class IContentTypeMap;
|
|
class ICustomErrorMap;
|
|
class IScriptMap;
|
|
class IMDData : public IRefCounted
|
|
{
|
|
// LFU data
|
|
//
|
|
LFUData m_lfudata;
|
|
|
|
// NOT IMPLEMENTED
|
|
//
|
|
IMDData& operator=(const IMDData&);
|
|
IMDData(const IMDData&);
|
|
|
|
protected:
|
|
// CREATORS
|
|
// Only create this object through it's descendents!
|
|
//
|
|
IMDData() {}
|
|
|
|
public:
|
|
// CREATORS
|
|
//
|
|
virtual ~IMDData() {}
|
|
|
|
// MANIPULATORS
|
|
//
|
|
LFUData& LFUData() { return m_lfudata; }
|
|
|
|
// ACCESSORS
|
|
//
|
|
virtual LPCWSTR PwszMDPathDataSet() const = 0;
|
|
virtual IContentTypeMap * GetContentTypeMap() const = 0;
|
|
virtual const ICustomErrorMap * GetCustomErrorMap() const = 0;
|
|
virtual const IScriptMap * GetScriptMap() const = 0;
|
|
virtual LPCWSTR PwszDefaultDocList() const = 0;
|
|
virtual LPCWSTR PwszVRUserName() const = 0;
|
|
virtual LPCWSTR PwszVRPassword() const = 0;
|
|
virtual LPCWSTR PwszExpires() const = 0;
|
|
virtual LPCWSTR PwszBindings() const = 0;
|
|
virtual LPCWSTR PwszVRPath() const = 0;
|
|
virtual DWORD DwDirBrowsing() const = 0;
|
|
virtual DWORD DwAccessPerms() const = 0;
|
|
virtual BOOL FAuthorViaFrontPage() const = 0;
|
|
virtual BOOL FHasIPRestriction() const = 0;
|
|
virtual BOOL FSameIPRestriction(const IMDData* prhs) const = 0;
|
|
virtual BOOL FHasApp() const = 0;
|
|
virtual DWORD DwAuthorization() const = 0;
|
|
virtual BOOL FIsIndexed() const = 0;
|
|
virtual BOOL FSameStarScriptmapping(const IMDData* prhs) const = 0;
|
|
|
|
//
|
|
// Any new metadata accessor should be added here and
|
|
// an implementation provided in \cal\src\_davprs\davmb.cpp.
|
|
//
|
|
};
|
|
|
|
class IEcb;
|
|
|
|
// ========================================================================
|
|
//
|
|
// CLASS CMDObjectHandle
|
|
//
|
|
// Encapsulates access to a metabase object through an open handle,
|
|
// ensuring that the handle is always propery closed.
|
|
//
|
|
class CMDObjectHandle
|
|
{
|
|
enum { METADATA_TIMEOUT = 5000 };
|
|
|
|
//
|
|
// Reference to ECB for security switching
|
|
//
|
|
const IEcb& m_ecb;
|
|
|
|
//
|
|
// COM interface to the metabase
|
|
//
|
|
IMSAdminBase * m_pMSAdminBase;
|
|
|
|
//
|
|
// Raw metabase handle
|
|
//
|
|
METADATA_HANDLE m_hMDObject;
|
|
|
|
//
|
|
// The path for which the handle was opened
|
|
//
|
|
LPCWSTR m_pwszPath;
|
|
|
|
// NOT IMPLEMENTED
|
|
//
|
|
CMDObjectHandle(const CMDObjectHandle&);
|
|
CMDObjectHandle& operator=(CMDObjectHandle&);
|
|
|
|
public:
|
|
|
|
// CREATORS
|
|
//
|
|
CMDObjectHandle(const IEcb& ecb, IMSAdminBase * pMSAdminBase = NULL) :
|
|
m_ecb(ecb),
|
|
m_pMSAdminBase(pMSAdminBase),
|
|
m_hMDObject(METADATA_MASTER_ROOT_HANDLE),
|
|
m_pwszPath(NULL)
|
|
{
|
|
}
|
|
|
|
~CMDObjectHandle();
|
|
|
|
// MANIPULATORS
|
|
//
|
|
HRESULT HrOpen( IMSAdminBase * pMSAdminBase,
|
|
LPCWSTR pwszPath,
|
|
DWORD dwAccess,
|
|
DWORD dwMsecTimeout );
|
|
|
|
HRESULT HrOpenLowestNode( IMSAdminBase * pMSAdminBase,
|
|
LPWSTR pwszPath,
|
|
DWORD dwAccess,
|
|
LPWSTR * ppwszPath );
|
|
|
|
HRESULT HrEnumKeys( LPCWSTR pwszPath,
|
|
LPWSTR pwszChild,
|
|
DWORD dwIndex ) const;
|
|
|
|
HRESULT HrGetDataPaths( LPCWSTR pwszPath,
|
|
DWORD dwPropID,
|
|
DWORD dwDataType,
|
|
LPWSTR pwszDataPaths,
|
|
DWORD * pcchDataPaths ) const;
|
|
|
|
HRESULT HrGetMetaData( LPCWSTR pwszPath,
|
|
METADATA_RECORD * pmdrec,
|
|
DWORD * pcbBufRequired ) const;
|
|
|
|
HRESULT HrGetAllMetaData( LPCWSTR pwszPath,
|
|
DWORD dwAttributes,
|
|
DWORD dwUserType,
|
|
DWORD dwDataType,
|
|
DWORD * pdwcRecords,
|
|
DWORD * pdwDataSet,
|
|
DWORD cbBuf,
|
|
LPBYTE pbBuf,
|
|
DWORD * pcbBufRequired ) const;
|
|
|
|
HRESULT HrSetMetaData( LPCWSTR pwszPath,
|
|
const METADATA_RECORD * pmdrec ) const;
|
|
|
|
HRESULT HrDeleteMetaData( LPCWSTR pwszPath,
|
|
DWORD dwPropID,
|
|
DWORD dwDataType ) const;
|
|
|
|
VOID Close();
|
|
};
|
|
|
|
// Initialize the metabase
|
|
//
|
|
BOOL FMDInitialize();
|
|
|
|
// Deinit the metabase
|
|
//
|
|
VOID MDDeinitialize();
|
|
|
|
// Fetch the metadata for a specific URI.
|
|
//
|
|
// Note: If you need data for the request URI you
|
|
// should use the MetaData() accessor on the IEcb
|
|
// instead of this function.
|
|
//
|
|
HRESULT HrMDGetData( const IEcb& ecb,
|
|
LPCWSTR pwszURI,
|
|
IMDData ** ppMDData );
|
|
|
|
// Fetch the metadata for a specific metabase path
|
|
// which may not exist -- e.g. paths to objects
|
|
// whose metadata is entirely inherited.
|
|
//
|
|
// When fetching metadata for a path that may not
|
|
// exist pszMDPathOpen must be set to a path that
|
|
// is known to exist and is a proper prefix of
|
|
// the desired access path -- typically the path
|
|
// to the vroot.
|
|
//
|
|
HRESULT HrMDGetData( const IEcb& ecb,
|
|
LPCWSTR pwszMDPathAccess,
|
|
LPCWSTR pwszMDPathOpen,
|
|
IMDData ** ppMDData );
|
|
|
|
// Get metabase change number
|
|
//
|
|
DWORD DwMDChangeNumber(const IEcb * pecb);
|
|
|
|
// Open a metadata handle
|
|
//
|
|
HRESULT HrMDOpenMetaObject( LPCWSTR pwszMDPath,
|
|
DWORD dwAccess,
|
|
DWORD dwMsecTimeout,
|
|
CMDObjectHandle * pmdoh );
|
|
|
|
HRESULT HrMDOpenLowestNodeMetaObject( LPWSTR pwszMDPath,
|
|
DWORD dwAccess,
|
|
LPWSTR * ppwszMDPath,
|
|
CMDObjectHandle * pmdoh );
|
|
|
|
HRESULT
|
|
HrMDIsAuthorViaFrontPageNeeded(const IEcb& ecb,
|
|
LPCWSTR pwszURI,
|
|
BOOL * pfFrontPageWeb);
|
|
|
|
// ------------------------------------------------------------------------
|
|
//
|
|
// FParseMDData()
|
|
//
|
|
// Parses a comma-delimited metadata string into fields. Any whitespace
|
|
// around the delimiters is considered insignificant and removed.
|
|
//
|
|
// Returns TRUE if the data parsed into the expected number of fields
|
|
// and FALSE otherwise.
|
|
//
|
|
// Pointers to the parsed are returned in rgpszFields. If a string
|
|
// parses into fewer than the expected number of fields, NULLs are
|
|
// returned for all of the fields beyond the last one parsed.
|
|
//
|
|
// If a string parses into the expected number of fields then
|
|
// the last field is always just the remainder of the string beyond
|
|
// the second to last field, regardless whether the string could be
|
|
// parsed into additional fields. For example " foo , bar , baz "
|
|
// parses into three fields as "foo", "bar" and "baz", but parses
|
|
// into two fields as "foo" and "bar , baz"
|
|
//
|
|
// The total number of characters in pszData, including the null
|
|
// terminator, is also returned in *pcchzData.
|
|
//
|
|
// Note: this function MODIFIES pszData.
|
|
//
|
|
BOOL
|
|
FParseMDData( LPWSTR pwszData,
|
|
LPWSTR rgpwszFields[],
|
|
UINT cFields,
|
|
UINT * pcchData );
|
|
|
|
// ------------------------------------------------------------------------
|
|
//
|
|
// FCopyStringToBuf()
|
|
//
|
|
// Copies a string (pszSource) to a buffer (pszBuf) if the size of the
|
|
// buffer is large enough to hold the string. The size of the string is
|
|
// returned in *pchBuf. A return value of TRUE indicates that the buffer
|
|
// was large enough and string was successfully copied.
|
|
//
|
|
// This function is primarily intended for use in copying string return
|
|
// values from IMDData accessors into buffers so that they can be used
|
|
// after the IMDData object from which they were obtained is gone.
|
|
//
|
|
inline BOOL
|
|
FCopyStringToBuf( LPCWSTR pwszSrc,
|
|
LPWSTR pwszBuf,
|
|
UINT * pcchBuf )
|
|
{
|
|
Assert( pwszSrc );
|
|
Assert( pwszBuf );
|
|
Assert( pcchBuf );
|
|
|
|
UINT cchSrc = static_cast<UINT>(wcslen(pwszSrc) + 1);
|
|
|
|
//
|
|
// If the supplied buffer isn't big enough to copy the
|
|
// string type into, then fill in the required size and
|
|
// return an error.
|
|
//
|
|
if ( *pcchBuf < cchSrc )
|
|
{
|
|
*pcchBuf = cchSrc;
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// The buffer was large enough so copy the string.
|
|
//
|
|
memcpy( pwszBuf, pwszSrc, cchSrc * sizeof(WCHAR) );
|
|
*pcchBuf = cchSrc;
|
|
return TRUE;
|
|
}
|
|
|
|
// Metabase operations -------------------------------------------------------
|
|
//
|
|
// class CMetaOp -------------------------------------------------------------
|
|
//
|
|
class CMetaOp
|
|
{
|
|
// Enumeration of metabase nodes
|
|
//
|
|
enum { CCH_BUFFER_SIZE = 4096 };
|
|
SCODE __fastcall ScEnumOp (LPWSTR pwszMetaPath, UINT cch);
|
|
|
|
// non-implemented
|
|
//
|
|
CMetaOp& operator=(const CMetaOp&);
|
|
CMetaOp(const CMetaOp&);
|
|
|
|
protected:
|
|
|
|
const IEcb * m_pecb;
|
|
CMDObjectHandle m_mdoh;
|
|
DWORD m_dwId;
|
|
DWORD m_dwType;
|
|
LPCWSTR m_pwszMetaPath;
|
|
BOOL m_fWrite;
|
|
|
|
// Subclass' operation to perform for each node where
|
|
// a value is explicitly set.
|
|
//
|
|
virtual SCODE __fastcall ScOp(LPCWSTR pwszMbPath, UINT cch) = 0;
|
|
|
|
public:
|
|
|
|
virtual ~CMetaOp() {}
|
|
|
|
CMetaOp ( const IEcb * pecb, LPCWSTR pwszPath, DWORD dwID, DWORD dwType, BOOL fWrite)
|
|
: m_pecb(pecb),
|
|
m_mdoh(*pecb),
|
|
m_dwId(dwID),
|
|
m_dwType(dwType),
|
|
m_pwszMetaPath(pwszPath),
|
|
m_fWrite(fWrite)
|
|
{
|
|
}
|
|
|
|
// Interface use by MOVE/COPY, etc.
|
|
//
|
|
// NOTE: these operations do not go through the metabase cache
|
|
// for a very specific reason -- the resource is either being
|
|
// moved, copied or deleted. Just because an item was a part
|
|
// of a large tree operation, does not mean it needs to be added
|
|
// into the cache.
|
|
//
|
|
SCODE __fastcall ScMetaOp();
|
|
};
|
|
|
|
#endif // _DAVMB_H
|