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.
1319 lines
41 KiB
1319 lines
41 KiB
// --------------------------------------------------------------------------------
|
|
// propfind.cpp
|
|
// Copyright (c)1998 Microsoft Corporation, All Rights Reserved
|
|
// Greg Friedman
|
|
// --------------------------------------------------------------------------------
|
|
|
|
#include <pch.hxx>
|
|
#include "propfind.h"
|
|
#include "strconst.h"
|
|
#include "davstrs.h"
|
|
#include <shlwapi.h>
|
|
|
|
#define FAIL_EXIT_STREAM_WRITE(stream, psz) \
|
|
if (FAILED(hr = stream.Write(psz, lstrlen(psz), NULL))) \
|
|
goto exit; \
|
|
else
|
|
|
|
#define FAIL_EXIT(hr) \
|
|
if (FAILED(hr)) \
|
|
goto exit; \
|
|
else
|
|
|
|
const ULONG c_ulGrowSize = 4;
|
|
|
|
static const char *g_rgszNamespaces[] =
|
|
{
|
|
c_szDAVDavNamespace,
|
|
c_szDAVHotMailNamespace,
|
|
c_szDAVHTTPMailNamespace,
|
|
c_szDAVMailNamespace,
|
|
c_szDAVContactsNamespace
|
|
};
|
|
|
|
// predefine the first 10 namespace prefixes. if custom namespaces
|
|
// exceed the predefined set, additional prefixes are generated on
|
|
// the fly.
|
|
|
|
static const char *g_rgszNamespacePrefixes[] =
|
|
{
|
|
c_szDavNamespacePrefix,
|
|
c_szHotMailNamespacePrefix,
|
|
c_szHTTPMailNamespacePrefix,
|
|
c_szMailNamespacePrefix,
|
|
c_szContactsNamespacePrefix,
|
|
"_5",
|
|
"_6",
|
|
"_7",
|
|
"_8",
|
|
"_9"
|
|
};
|
|
|
|
const DWORD c_dwMaxDefinedNamespacePrefix = 10;
|
|
|
|
CStringArray::CStringArray(void) :
|
|
m_rgpszValues(NULL),
|
|
m_ulLength(0),
|
|
m_ulCapacity(0)
|
|
{
|
|
}
|
|
|
|
|
|
CStringArray::~CStringArray(void)
|
|
{
|
|
for (ULONG i = 0; i < m_ulLength; ++i)
|
|
{
|
|
if (NULL != m_rgpszValues[i])
|
|
MemFree((void *)m_rgpszValues[i]);
|
|
}
|
|
|
|
SafeMemFree(m_rgpszValues);
|
|
}
|
|
|
|
HRESULT CStringArray::Add(LPCSTR psz)
|
|
{
|
|
if (NULL == psz)
|
|
return E_INVALIDARG;
|
|
|
|
if (m_ulLength == m_ulCapacity && !Expand())
|
|
return E_OUTOFMEMORY;
|
|
|
|
m_rgpszValues[m_ulLength] = PszDupA(psz);
|
|
if (NULL == m_rgpszValues)
|
|
return E_OUTOFMEMORY;
|
|
|
|
++m_ulLength;
|
|
return S_OK;
|
|
}
|
|
|
|
HRESULT CStringArray::Adopt(LPCSTR psz)
|
|
{
|
|
if (NULL == psz)
|
|
return E_INVALIDARG;
|
|
|
|
if (m_ulLength == m_ulCapacity && !Expand())
|
|
return E_OUTOFMEMORY;
|
|
|
|
m_rgpszValues[m_ulLength] = psz;
|
|
++m_ulLength;
|
|
return S_OK;
|
|
}
|
|
|
|
LPCSTR CStringArray::GetByIndex(ULONG ulIndex)
|
|
{
|
|
if (0 == m_ulLength || (ulIndex > m_ulLength - 1))
|
|
return NULL;
|
|
|
|
return m_rgpszValues[ulIndex];
|
|
}
|
|
|
|
// --------------------------------------------------------------------------------
|
|
// CStringArray::RemoveByIndex
|
|
// --------------------------------------------------------------------------------
|
|
HRESULT CStringArray::RemoveByIndex(ULONG ulIndex)
|
|
{
|
|
if (ulIndex > m_ulLength - 1)
|
|
return E_INVALIDARG;
|
|
|
|
if (NULL != m_rgpszValues[ulIndex])
|
|
{
|
|
MemFree(const_cast<char *>(m_rgpszValues[ulIndex]));
|
|
m_rgpszValues[ulIndex] = NULL;
|
|
}
|
|
|
|
// shift down
|
|
CopyMemory(&m_rgpszValues[ulIndex], m_rgpszValues[ulIndex + 1], (m_ulLength - ulIndex) * sizeof(LPSTR));
|
|
--m_ulLength;
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
// --------------------------------------------------------------------------------
|
|
// CStringArray::Expand
|
|
// --------------------------------------------------------------------------------
|
|
BOOL CStringArray::Expand(void)
|
|
{
|
|
LPCSTR *rgpszNewValues = NULL;
|
|
if (!MemAlloc((void **)&rgpszNewValues, sizeof(LPSTR) * (m_ulCapacity + c_ulGrowSize)))
|
|
return FALSE;
|
|
|
|
// clear the new slots
|
|
ZeroMemory(rgpszNewValues,sizeof(LPSTR) * (m_ulCapacity + c_ulGrowSize));
|
|
|
|
// copy the old values over and swap in the new buffer
|
|
CopyMemory(rgpszNewValues, m_rgpszValues, sizeof(LPSTR) * m_ulCapacity);
|
|
SafeMemFree(m_rgpszValues);
|
|
|
|
m_rgpszValues = rgpszNewValues;
|
|
m_ulCapacity += c_ulGrowSize;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
// --------------------------------------------------------------------------------
|
|
// CStringHash::~CStringHash
|
|
// --------------------------------------------------------------------------------
|
|
CStringHash::~CStringHash(void)
|
|
{
|
|
PHASHENTRY phe;
|
|
|
|
// data stored in the hash table
|
|
// are strings that can need to
|
|
// be deallocated.
|
|
for (DWORD dw = 0; dw < m_cBins; dw++)
|
|
{
|
|
SafeMemFree(m_rgBins[dw].pv);
|
|
|
|
phe = m_rgBins[dw].pheNext;
|
|
while (phe)
|
|
{
|
|
SafeMemFree(phe->pv);
|
|
phe = phe->pheNext;
|
|
}
|
|
}
|
|
}
|
|
|
|
// --------------------------------------------------------------------------------
|
|
// CDAVNamespaceArbiterImp::CDAVNamespaceArbiterImp
|
|
// --------------------------------------------------------------------------------
|
|
CDAVNamespaceArbiterImp::CDAVNamespaceArbiterImp(void)
|
|
{
|
|
for (ULONG i = 0; i <= c_dwMaxNamespaceID; ++i)
|
|
m_rgbNsUsed[i] = FALSE;
|
|
|
|
// the DAV namespace is always included
|
|
m_rgbNsUsed[DAVNAMESPACE_DAV] = TRUE;
|
|
}
|
|
|
|
// --------------------------------------------------------------------------------
|
|
// CDAVNamespaceArbiterImp::~CDAVNamespaceArbiterImp
|
|
// --------------------------------------------------------------------------------
|
|
CDAVNamespaceArbiterImp::~CDAVNamespaceArbiterImp(void)
|
|
{
|
|
// nothing to do
|
|
}
|
|
|
|
// --------------------------------------------------------------------------------
|
|
// CDAVNamespaceArbiterImp::AddNamespace
|
|
// --------------------------------------------------------------------------------
|
|
HRESULT CDAVNamespaceArbiterImp::AddNamespace(LPCSTR pszNamespace, DWORD *pdwNamespaceID)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
if (NULL == pszNamespace || NULL == pdwNamespaceID)
|
|
{
|
|
hr = E_INVALIDARG;
|
|
goto exit;
|
|
}
|
|
|
|
if (FAILED(hr = m_saNamespaces.Add(pszNamespace)))
|
|
goto exit;
|
|
|
|
*pdwNamespaceID = m_saNamespaces.Length() + c_dwMaxNamespaceID;
|
|
|
|
exit:
|
|
return hr;
|
|
}
|
|
|
|
// --------------------------------------------------------------------------------
|
|
// CDAVNamespaceArbiterImp::GetNamespaceID
|
|
// --------------------------------------------------------------------------------
|
|
HRESULT CDAVNamespaceArbiterImp::GetNamespaceID(LPCSTR pszNamespace, DWORD *pdwNamespaceID)
|
|
{
|
|
DWORD dwIndex;
|
|
DWORD dwEntries;
|
|
|
|
if (NULL == pszNamespace || NULL == pdwNamespaceID)
|
|
return E_INVALIDARG;
|
|
|
|
// look for a predefined namespace
|
|
for (dwIndex = 0; dwIndex < c_dwMaxNamespaceID; ++dwIndex)
|
|
{
|
|
if (!lstrcmp(pszNamespace, g_rgszNamespaces[dwIndex]))
|
|
{
|
|
*pdwNamespaceID = dwIndex;
|
|
return S_OK;
|
|
}
|
|
}
|
|
|
|
// look for a user-defined prefix
|
|
dwEntries = m_saNamespaces.Length();
|
|
for (dwIndex = 0; dwIndex < dwEntries; ++dwIndex)
|
|
{
|
|
if (!lstrcmp(pszNamespace, m_saNamespaces.GetByIndex(dwIndex)))
|
|
{
|
|
*pdwNamespaceID = (dwIndex + (c_dwMaxNamespaceID + 1));
|
|
return S_OK;
|
|
}
|
|
}
|
|
|
|
// if it wasn't found, the namespace doesn't exist
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
// --------------------------------------------------------------------------------
|
|
// CDAVNamespaceArbiterImp::GetNamespacePrefix
|
|
// --------------------------------------------------------------------------------
|
|
HRESULT CDAVNamespaceArbiterImp::GetNamespacePrefix(DWORD dwNamespaceID, LPSTR *ppszNamespacePrefix)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
LPSTR pszTemp = NULL;
|
|
|
|
if (NULL == ppszNamespacePrefix)
|
|
return E_INVALIDARG;
|
|
|
|
if (dwNamespaceID <= c_dwMaxDefinedNamespacePrefix)
|
|
*ppszNamespacePrefix = PszDupA(g_rgszNamespacePrefixes[dwNamespaceID]);
|
|
else
|
|
{
|
|
char szBuffer[12];
|
|
wnsprintf(szBuffer, ARRAYSIZE(szBuffer), "_%d", dwNamespaceID);
|
|
*ppszNamespacePrefix = PszDupA(szBuffer);
|
|
}
|
|
|
|
if (NULL == *ppszNamespacePrefix)
|
|
hr = E_OUTOFMEMORY;
|
|
|
|
return hr;
|
|
}
|
|
|
|
// --------------------------------------------------------------------------------
|
|
// CDAVNamespaceArbiterImp::AllocExpandedName
|
|
// --------------------------------------------------------------------------------
|
|
LPSTR CDAVNamespaceArbiterImp::AllocExpandedName(DWORD dwNamespaceID, LPCSTR pszPropertyName)
|
|
{
|
|
LPSTR pszPrefixedName = NULL;
|
|
const DWORD c_dwMaxIntLength = 10;
|
|
|
|
if (dwNamespaceID < c_dwMaxDefinedNamespacePrefix)
|
|
{
|
|
// allocate a buffer to hold the prefixed name.
|
|
DWORD cchSize = (lstrlen(pszPropertyName) + lstrlen(g_rgszNamespacePrefixes[dwNamespaceID]) + 2);
|
|
if (!MemAlloc((void **)&pszPrefixedName, cchSize * sizeof(pszPrefixedName[0])))
|
|
return NULL;
|
|
|
|
// generate the prefixed name
|
|
wnsprintf(pszPrefixedName, cchSize, "%s:%s", g_rgszNamespacePrefixes[dwNamespaceID], pszPropertyName);
|
|
}
|
|
else
|
|
{
|
|
// allocate a buffer to hold the prefixed name. the "2" is for the prefix char '_" , the delimiting
|
|
// colon and the eos.
|
|
|
|
DWORD cchSize = (lstrlen(pszPropertyName) + c_dwMaxIntLength + 3);
|
|
if (!MemAlloc((void **)&pszPrefixedName, cchSize * sizeof(pszPrefixedName[0])))
|
|
return NULL;
|
|
|
|
|
|
// generate the prefixed name. use an underscore as the first char, because
|
|
// DAV explicitly disallows digits for the first char.
|
|
wnsprintf(pszPrefixedName, cchSize, "_%d:%s", dwNamespaceID, pszPropertyName);
|
|
}
|
|
|
|
return pszPrefixedName;
|
|
}
|
|
|
|
// --------------------------------------------------------------------------------
|
|
// CDAVNamespaceArbiterImp::WriteNamespaces
|
|
// --------------------------------------------------------------------------------
|
|
HRESULT CDAVNamespaceArbiterImp::WriteNamespaces(IStream *pStream)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
ULONG i;
|
|
ULONG cEntries;
|
|
BOOL fNeedSpacePrefix = FALSE;
|
|
|
|
// write out the intrinsic namespaces
|
|
for (i = 0; i <= c_dwMaxNamespaceID; ++i)
|
|
{
|
|
if (m_rgbNsUsed[i])
|
|
{
|
|
if (FAILED(hr = _AppendXMLNamespace(pStream, g_rgszNamespaces[i], i, fNeedSpacePrefix)))
|
|
goto exit;
|
|
fNeedSpacePrefix = TRUE;
|
|
}
|
|
}
|
|
|
|
// write out the installed namespaces
|
|
cEntries = m_saNamespaces.Length();
|
|
for (i = 0; i < cEntries; ++i)
|
|
{
|
|
if (FAILED(hr = _AppendXMLNamespace(pStream, m_saNamespaces.GetByIndex(i), i + i + c_dwMaxNamespaceID + 1, fNeedSpacePrefix)))
|
|
goto exit;
|
|
|
|
fNeedSpacePrefix = TRUE;
|
|
}
|
|
|
|
exit:
|
|
return hr;
|
|
}
|
|
|
|
// --------------------------------------------------------------------------------
|
|
// CDAVNamespaceArbiterImp::_AppendXMLNamespace
|
|
// --------------------------------------------------------------------------------
|
|
HRESULT CDAVNamespaceArbiterImp::_AppendXMLNamespace(IStream *pStream,
|
|
LPCSTR pszNamespace,
|
|
DWORD dwNamespaceID,
|
|
BOOL fWhitespacePrefix)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
TCHAR szPrefix[12];
|
|
|
|
if (fWhitespacePrefix)
|
|
{
|
|
IxpAssert(1 == lstrlen(c_szEqual));
|
|
if (FAILED(hr = pStream->Write(g_szSpace, 1, NULL)))
|
|
goto exit;
|
|
}
|
|
|
|
if (FAILED(hr = pStream->Write(c_szXMLNsColon, lstrlen(c_szXMLNsColon), NULL)))
|
|
goto exit;
|
|
|
|
if (dwNamespaceID < c_dwMaxDefinedNamespacePrefix)
|
|
{
|
|
if (FAILED(hr = pStream->Write(g_rgszNamespacePrefixes[dwNamespaceID], lstrlen(g_rgszNamespacePrefixes[dwNamespaceID]), NULL)))
|
|
goto exit;
|
|
}
|
|
else
|
|
{
|
|
wnsprintf(szPrefix, ARRAYSIZE(szPrefix), "_%d", dwNamespaceID);
|
|
|
|
if (FAILED(hr = pStream->Write(szPrefix, lstrlen(szPrefix), NULL)))
|
|
goto exit;
|
|
}
|
|
|
|
IxpAssert(1 == lstrlen(c_szEqual));
|
|
IxpAssert(1 == lstrlen(c_szDoubleQuote));
|
|
|
|
if (FAILED(hr = pStream->Write(c_szEqual, 1, NULL)))
|
|
goto exit;
|
|
|
|
if (FAILED(hr = pStream->Write(c_szDoubleQuote, 1, NULL)))
|
|
goto exit;
|
|
|
|
if (FAILED(hr = pStream->Write(pszNamespace, lstrlen(pszNamespace), NULL)))
|
|
goto exit;
|
|
|
|
hr = pStream->Write(c_szDoubleQuote, 1, NULL);
|
|
|
|
exit:
|
|
return hr;
|
|
}
|
|
|
|
// --------------------------------------------------------------------------------
|
|
// CPropPatchRequest::CPropPatchRequest
|
|
// --------------------------------------------------------------------------------
|
|
CPropPatchRequest::CPropPatchRequest(void) :
|
|
m_fSpecify1252(FALSE),
|
|
m_cRef(1)
|
|
{
|
|
// nothing to do
|
|
}
|
|
|
|
// --------------------------------------------------------------------------------
|
|
// IUnknown Methods
|
|
// --------------------------------------------------------------------------------
|
|
|
|
// --------------------------------------------------------------------------------
|
|
// CPropPatchRequest::QueryInterface
|
|
// --------------------------------------------------------------------------------
|
|
STDMETHODIMP CPropPatchRequest::QueryInterface(REFIID riid, LPVOID *ppv)
|
|
{
|
|
// Locals
|
|
HRESULT hr = S_OK;
|
|
|
|
// Validate params
|
|
if (NULL == ppv)
|
|
{
|
|
hr = TrapError(E_INVALIDARG);
|
|
goto exit;
|
|
}
|
|
|
|
// Initialize params
|
|
*ppv = NULL;
|
|
|
|
// IID_IUnknown
|
|
if (IID_IUnknown == riid)
|
|
*ppv = ((IUnknown *)(IPropFindRequest *)this);
|
|
else if (IID_IPropPatchRequest == riid)
|
|
*ppv = ((IPropPatchRequest *)this);
|
|
|
|
if (NULL != *ppv)
|
|
{
|
|
((LPUNKNOWN)*ppv)->AddRef();
|
|
goto exit;
|
|
}
|
|
|
|
hr = TrapError(E_NOINTERFACE);
|
|
|
|
exit:
|
|
// Done
|
|
return hr;
|
|
}
|
|
|
|
// --------------------------------------------------------------------------------
|
|
// CPropPatchRequest::AddRef
|
|
// --------------------------------------------------------------------------------
|
|
STDMETHODIMP_(ULONG) CPropPatchRequest::AddRef(void)
|
|
{
|
|
return ++m_cRef;
|
|
}
|
|
|
|
// --------------------------------------------------------------------------------
|
|
// CPropPatchRequest::Release
|
|
// --------------------------------------------------------------------------------
|
|
STDMETHODIMP_(ULONG) CPropPatchRequest::Release(void)
|
|
{
|
|
if (0 != --m_cRef)
|
|
return m_cRef;
|
|
delete this;
|
|
return 0;
|
|
}
|
|
|
|
// ----------------------------------------------------------------------------
|
|
// IDAVNamespaceArbiter methods
|
|
// ----------------------------------------------------------------------------
|
|
|
|
// --------------------------------------------------------------------------------
|
|
// CPropPatchRequest::CPropPatchRequest::AddNamespace
|
|
// --------------------------------------------------------------------------------
|
|
STDMETHODIMP CPropPatchRequest::AddNamespace(LPCSTR pszNamespace, DWORD *pdwNamespaceID)
|
|
{
|
|
return m_dna.AddNamespace(pszNamespace, pdwNamespaceID);
|
|
}
|
|
|
|
// --------------------------------------------------------------------------------
|
|
// CPropPatchRequest::GetNamespaceID
|
|
// --------------------------------------------------------------------------------
|
|
STDMETHODIMP CPropPatchRequest::GetNamespaceID(LPCSTR pszNamespace, DWORD *pdwNamespaceID)
|
|
{
|
|
return m_dna.GetNamespaceID(pszNamespace, pdwNamespaceID);
|
|
}
|
|
|
|
// --------------------------------------------------------------------------------
|
|
// CPropPatchRequest::GetNamespacePrefix
|
|
// --------------------------------------------------------------------------------
|
|
STDMETHODIMP CPropPatchRequest::GetNamespacePrefix(DWORD dwNamespaceID, LPSTR *ppszNamespacePrefix)
|
|
{
|
|
return m_dna.GetNamespacePrefix(dwNamespaceID, ppszNamespacePrefix);
|
|
}
|
|
|
|
// --------------------------------------------------------------------------------
|
|
// IPropPatchRequest Methods
|
|
// --------------------------------------------------------------------------------
|
|
// --------------------------------------------------------------------------------
|
|
// CPropPatchRequest::SetProperty
|
|
// --------------------------------------------------------------------------------
|
|
STDMETHODIMP CPropPatchRequest::SetProperty(
|
|
DWORD dwNamespaceID,
|
|
LPCSTR pszPropertyName,
|
|
LPCSTR pszNewValue)
|
|
{
|
|
LPSTR pszPrefixedName = NULL;
|
|
HRESULT hr = S_OK;
|
|
|
|
// Validate params
|
|
if (NULL == pszPropertyName || NULL == pszNewValue || dwNamespaceID > c_dwMaxNamespaceID + m_dna.m_saNamespaces.Length())
|
|
{
|
|
hr = E_INVALIDARG;
|
|
goto exit;
|
|
}
|
|
|
|
pszPrefixedName = m_dna.AllocExpandedName(dwNamespaceID, pszPropertyName);
|
|
if (NULL == pszPrefixedName)
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
goto exit;
|
|
}
|
|
|
|
// if the namespace is one of the known namespaces, mark it in
|
|
// the array so that we can include the namespace directive in
|
|
// the generated xml
|
|
if (dwNamespaceID <= c_dwMaxNamespaceID)
|
|
m_dna.m_rgbNsUsed[dwNamespaceID] = TRUE;
|
|
|
|
if (FAILED(hr = m_saPropValues.Add(pszNewValue)))
|
|
goto exit;
|
|
|
|
if (FAILED(hr = m_saPropNames.Adopt(pszPrefixedName)))
|
|
{
|
|
MemFree(pszPrefixedName);
|
|
m_saPropValues.RemoveByIndex(m_saPropValues.Length() - 1);
|
|
}
|
|
|
|
exit:
|
|
return hr;
|
|
}
|
|
|
|
// --------------------------------------------------------------------------------
|
|
// CPropPatchRequest::RemoveProperty
|
|
// --------------------------------------------------------------------------------
|
|
STDMETHODIMP CPropPatchRequest::RemoveProperty(
|
|
DWORD dwNamespaceID,
|
|
LPCSTR pszPropertyName)
|
|
{
|
|
LPSTR pszPrefixedName = NULL;
|
|
HRESULT hr = S_OK;
|
|
|
|
if (NULL == pszPropertyName || dwNamespaceID > c_dwMaxNamespaceID + m_dna.m_saNamespaces.Length())
|
|
{
|
|
hr = E_INVALIDARG;
|
|
goto exit;
|
|
}
|
|
|
|
pszPrefixedName = m_dna.AllocExpandedName(dwNamespaceID, pszPropertyName);
|
|
if (NULL == pszPrefixedName)
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
goto exit;
|
|
}
|
|
|
|
// if the namespace is one of the known namespaces, mark it in
|
|
// the array so that we can include the namespace directive in the
|
|
// generated xml
|
|
if (dwNamespaceID <= c_dwMaxNamespaceID)
|
|
m_dna.m_rgbNsUsed[dwNamespaceID] = TRUE;
|
|
|
|
hr = m_saRemovePropNames.Adopt(pszPrefixedName);
|
|
|
|
exit:
|
|
return hr;
|
|
}
|
|
|
|
// --------------------------------------------------------------------------------
|
|
// CPropPatchRequest::GenerateXML
|
|
// --------------------------------------------------------------------------------
|
|
STDMETHODIMP CPropPatchRequest::GenerateXML(LPSTR *ppszXML)
|
|
{
|
|
return GenerateXML(NULL, ppszXML);
|
|
}
|
|
|
|
// --------------------------------------------------------------------------------
|
|
// CPropPatchRequest::GenerateXML
|
|
// --------------------------------------------------------------------------------
|
|
STDMETHODIMP CPropPatchRequest::GenerateXML(LPHTTPTARGETLIST pTargets, LPSTR *ppszXML)
|
|
{
|
|
const DWORD c_dwLocalBufferSize = 256;
|
|
|
|
HRESULT hr = S_OK;
|
|
CByteStream stream;
|
|
ULONG cEntries;
|
|
LPCSTR pszName = NULL;
|
|
LPCSTR pszValue = NULL;
|
|
ULONG i;
|
|
DWORD dwIndex;
|
|
DWORD cbStr1, cbStr2;
|
|
|
|
if (NULL == ppszXML)
|
|
return E_INVALIDARG;
|
|
|
|
*ppszXML= NULL;
|
|
|
|
// write the DAV header
|
|
if (m_fSpecify1252)
|
|
FAIL_EXIT_STREAM_WRITE(stream, c_szXML1252Head);
|
|
else
|
|
FAIL_EXIT_STREAM_WRITE(stream, c_szXMLHead);
|
|
|
|
// write out the proppatch header
|
|
FAIL_EXIT_STREAM_WRITE(stream, c_szPropPatchHead);
|
|
|
|
// write out namespace directives using the new form
|
|
FAIL_EXIT(hr = m_dna.WriteNamespaces(&stream));
|
|
|
|
FAIL_EXIT_STREAM_WRITE(stream, c_szXMLCloseElement);
|
|
|
|
// write out the targets
|
|
if (NULL != pTargets && pTargets->cTarget > 0)
|
|
{
|
|
cbStr1 = lstrlen(c_szHrefHead);
|
|
cbStr2 = lstrlen(c_szHrefTail);
|
|
|
|
FAIL_EXIT_STREAM_WRITE(stream, c_szTargetHead);
|
|
|
|
// write out the targets
|
|
for (dwIndex = 0; dwIndex < pTargets->cTarget; dwIndex++)
|
|
{
|
|
FAIL_EXIT(hr = stream.Write(c_szHrefHead, cbStr1, NULL));
|
|
|
|
FAIL_EXIT_STREAM_WRITE(stream, pTargets->prgTarget[dwIndex]);
|
|
|
|
FAIL_EXIT(hr = stream.Write(c_szHrefTail, cbStr2, NULL));
|
|
}
|
|
FAIL_EXIT_STREAM_WRITE(stream, c_szTargetTail);
|
|
}
|
|
|
|
// write out the "set" properties
|
|
cEntries = m_saPropNames.Length();
|
|
if (cEntries > 0)
|
|
{
|
|
// write the set header
|
|
FAIL_EXIT_STREAM_WRITE(stream, c_szPropPatchSetHead);
|
|
|
|
for (i = 0; i < cEntries; ++i)
|
|
{
|
|
FAIL_EXIT_STREAM_WRITE(stream, c_szCRLFTabTabTabOpenElement);
|
|
|
|
pszName = m_saPropNames.GetByIndex(i);
|
|
if (NULL == pszName)
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
goto exit;
|
|
}
|
|
|
|
FAIL_EXIT_STREAM_WRITE(stream, pszName);
|
|
|
|
FAIL_EXIT_STREAM_WRITE(stream, c_szXMLCloseElement);
|
|
|
|
pszValue = m_saPropValues.GetByIndex(i);
|
|
if (NULL == pszValue)
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
goto exit;
|
|
}
|
|
|
|
FAIL_EXIT_STREAM_WRITE(stream, pszValue);
|
|
|
|
FAIL_EXIT_STREAM_WRITE(stream, c_szXMLOpenTermElement);
|
|
FAIL_EXIT_STREAM_WRITE(stream, pszName);
|
|
|
|
FAIL_EXIT_STREAM_WRITE(stream, c_szXMLCloseElement);
|
|
}
|
|
|
|
FAIL_EXIT_STREAM_WRITE(stream, c_szPropPatchSetTail);
|
|
}
|
|
|
|
// write out the remove properties
|
|
cEntries = m_saRemovePropNames.Length();
|
|
if (cEntries > 0)
|
|
{
|
|
// write the remove header
|
|
FAIL_EXIT_STREAM_WRITE(stream, c_szPropPatchRemoveHead);
|
|
|
|
for (i = 0; i < cEntries; ++i)
|
|
{
|
|
FAIL_EXIT_STREAM_WRITE(stream, c_szCRLFTabTabTabOpenElement);
|
|
|
|
pszName = m_saRemovePropNames.GetByIndex(i);
|
|
if (NULL == pszName)
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
goto exit;
|
|
}
|
|
|
|
FAIL_EXIT_STREAM_WRITE(stream, pszName);
|
|
|
|
FAIL_EXIT_STREAM_WRITE(stream, c_szXMLCloseTermElement);
|
|
}
|
|
|
|
FAIL_EXIT_STREAM_WRITE(stream, c_szPropPatchRemoveTail);
|
|
}
|
|
|
|
FAIL_EXIT_STREAM_WRITE(stream, c_szPropPatchTailCRLF);
|
|
|
|
hr = stream.HrAcquireStringA(NULL, ppszXML, ACQ_DISPLACE);
|
|
|
|
exit:
|
|
return hr;
|
|
}
|
|
|
|
// --------------------------------------------------------------------------------
|
|
// CPropFindRequest::CPropFindRequest
|
|
// --------------------------------------------------------------------------------
|
|
CPropFindRequest::CPropFindRequest(void) :
|
|
m_cRef(1)
|
|
{
|
|
}
|
|
|
|
// --------------------------------------------------------------------------------
|
|
// IUnknown Methods
|
|
// --------------------------------------------------------------------------------
|
|
|
|
// --------------------------------------------------------------------------------
|
|
// CPropFindRequest::QueryInterface
|
|
// --------------------------------------------------------------------------------
|
|
STDMETHODIMP CPropFindRequest::QueryInterface(REFIID riid, LPVOID *ppv)
|
|
{
|
|
// Locals
|
|
HRESULT hr = S_OK;
|
|
|
|
// Validate params
|
|
if (NULL == ppv)
|
|
{
|
|
hr = TrapError(E_INVALIDARG);
|
|
goto exit;
|
|
}
|
|
|
|
// Initialize params
|
|
*ppv = NULL;
|
|
|
|
// IID_IUnknown
|
|
if (IID_IUnknown == riid)
|
|
*ppv = ((IUnknown *)(IPropFindRequest *)this);
|
|
else if (IID_IPropFindRequest == riid)
|
|
*ppv = ((IPropFindRequest *)this);
|
|
|
|
if (NULL != *ppv)
|
|
{
|
|
((LPUNKNOWN)*ppv)->AddRef();
|
|
goto exit;
|
|
}
|
|
|
|
hr = TrapError(E_NOINTERFACE);
|
|
|
|
exit:
|
|
// Done
|
|
return hr;
|
|
}
|
|
|
|
// --------------------------------------------------------------------------------
|
|
// CPropFindRequest::AddRef
|
|
// --------------------------------------------------------------------------------
|
|
STDMETHODIMP_(ULONG) CPropFindRequest::AddRef(void)
|
|
{
|
|
return ++m_cRef;
|
|
}
|
|
|
|
// --------------------------------------------------------------------------------
|
|
// CPropFindRequest::Release
|
|
// --------------------------------------------------------------------------------
|
|
STDMETHODIMP_(ULONG) CPropFindRequest::Release(void)
|
|
{
|
|
if (0 != --m_cRef)
|
|
return m_cRef;
|
|
delete this;
|
|
return 0;
|
|
}
|
|
|
|
// ----------------------------------------------------------------------------
|
|
// IDAVNamespaceArbiter methods
|
|
// ----------------------------------------------------------------------------
|
|
|
|
// --------------------------------------------------------------------------------
|
|
// CPropFindRequest::CPropPatchRequest::AddNamespace
|
|
// --------------------------------------------------------------------------------
|
|
STDMETHODIMP CPropFindRequest::AddNamespace(LPCSTR pszNamespace, DWORD *pdwNamespaceID)
|
|
{
|
|
return m_dna.AddNamespace(pszNamespace, pdwNamespaceID);
|
|
}
|
|
|
|
// --------------------------------------------------------------------------------
|
|
// CPropFindRequest::GetNamespaceID
|
|
// --------------------------------------------------------------------------------
|
|
STDMETHODIMP CPropFindRequest::GetNamespaceID(LPCSTR pszNamespace, DWORD *pdwNamespaceID)
|
|
{
|
|
return m_dna.GetNamespaceID(pszNamespace, pdwNamespaceID);
|
|
}
|
|
|
|
// --------------------------------------------------------------------------------
|
|
// CPropFindRequest::GetNamespacePrefix
|
|
// --------------------------------------------------------------------------------
|
|
STDMETHODIMP CPropFindRequest::GetNamespacePrefix(DWORD dwNamespaceID, LPSTR *ppszNamespacePrefix)
|
|
{
|
|
return m_dna.GetNamespacePrefix(dwNamespaceID, ppszNamespacePrefix);
|
|
}
|
|
|
|
// --------------------------------------------------------------------------------
|
|
// IPropFindRequest Methods
|
|
// --------------------------------------------------------------------------------
|
|
|
|
// --------------------------------------------------------------------------------
|
|
// CPropFindRequest::AddProperty
|
|
// --------------------------------------------------------------------------------
|
|
STDMETHODIMP CPropFindRequest::AddProperty(DWORD dwNamespaceID, LPCSTR pszPropertyName)
|
|
{
|
|
const DWORD c_dwMaxIntLength = 10;
|
|
LPSTR pszPrefixedName = NULL;
|
|
|
|
// Validate Params
|
|
if (NULL == pszPropertyName || dwNamespaceID > c_dwMaxNamespaceID + m_dna.m_saNamespaces.Length())
|
|
return E_INVALIDARG;
|
|
|
|
pszPrefixedName = m_dna.AllocExpandedName(dwNamespaceID, pszPropertyName);
|
|
if (NULL == pszPrefixedName)
|
|
return E_OUTOFMEMORY;
|
|
|
|
// if the namespace is one of the known namespaces, mark
|
|
// the array so that we can include the namespace directive
|
|
// in the generated xml.
|
|
if (dwNamespaceID <= c_dwMaxNamespaceID)
|
|
m_dna.m_rgbNsUsed[dwNamespaceID] = TRUE;
|
|
|
|
m_saProperties.Adopt(pszPrefixedName);
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
// --------------------------------------------------------------------------------
|
|
// CPropFindRequest::GenerateXML
|
|
// --------------------------------------------------------------------------------
|
|
STDMETHODIMP CPropFindRequest::GenerateXML(LPSTR *ppszXML)
|
|
{
|
|
const DWORD c_dwLocalBufferSize = 256;
|
|
|
|
HRESULT hr = S_OK;
|
|
CByteStream stream;
|
|
ULONG cbLength = 0;
|
|
ULONG cEntries;
|
|
ULONG i;
|
|
LPCSTR pszProperty;
|
|
|
|
if (NULL == ppszXML)
|
|
return E_INVALIDARG;
|
|
|
|
*ppszXML = NULL;
|
|
|
|
// write the DAV header
|
|
if (FAILED(hr = stream.Write(c_szXMLHead, lstrlen(c_szXMLHead), NULL)))
|
|
goto exit;
|
|
|
|
// write out the propfind header
|
|
if (FAILED(hr = stream.Write(c_szPropFindHead1, lstrlen(c_szPropFindHead1), NULL)))
|
|
goto exit;
|
|
|
|
// write out namespaces using the new form
|
|
if (FAILED(hr = m_dna.WriteNamespaces(&stream)))
|
|
goto exit;
|
|
|
|
if (FAILED(hr = stream.Write(c_szPropFindHead2, lstrlen(c_szPropFindHead2), NULL)))
|
|
goto exit;
|
|
|
|
// write out the properties
|
|
cEntries = m_saProperties.Length();
|
|
for (i = 0; i < cEntries; ++i)
|
|
{
|
|
if (FAILED(hr = stream.Write(c_szCRLFTabTabOpenElement, lstrlen(c_szCRLFTabTabOpenElement), NULL)))
|
|
goto exit;
|
|
|
|
// properties are prefixed when they are added to the collection
|
|
pszProperty = m_saProperties.GetByIndex(i);
|
|
if (!pszProperty)
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
goto exit;
|
|
}
|
|
|
|
if (FAILED(hr = stream.Write(pszProperty, lstrlen(pszProperty), NULL)))
|
|
goto exit;
|
|
|
|
if (FAILED(hr = stream.Write(c_szXMLCloseTermElement, lstrlen(c_szXMLCloseTermElement), NULL)))
|
|
goto exit;
|
|
}
|
|
|
|
if (FAILED(hr = stream.Write(c_szPropFindTail, lstrlen(c_szPropFindTail), NULL)))
|
|
goto exit;
|
|
|
|
hr = stream.HrAcquireStringA(NULL, ppszXML, ACQ_DISPLACE);
|
|
|
|
exit:
|
|
return hr;
|
|
}
|
|
|
|
|
|
// --------------------------------------------------------------------------------
|
|
// class CPropFindMultiResponse
|
|
// --------------------------------------------------------------------------------
|
|
|
|
// --------------------------------------------------------------------------------
|
|
// CPropFindMultiResponse::CPropFindMultiResponse
|
|
// --------------------------------------------------------------------------------
|
|
CPropFindMultiResponse::CPropFindMultiResponse(void) :
|
|
m_cRef(1),
|
|
m_bDone(FALSE),
|
|
m_ulResponseCapacity(0),
|
|
m_ulResponseLength(0),
|
|
m_rgResponses(NULL)
|
|
{
|
|
}
|
|
|
|
// --------------------------------------------------------------------------------
|
|
// CPropFindMultiResponse::~CPropFindMultiResponse
|
|
// --------------------------------------------------------------------------------
|
|
CPropFindMultiResponse::~CPropFindMultiResponse(void)
|
|
{
|
|
for (ULONG i = 0; i < m_ulResponseLength; i++)
|
|
SafeRelease(m_rgResponses[i]);
|
|
|
|
SafeMemFree(m_rgResponses);
|
|
}
|
|
|
|
// --------------------------------------------------------------------------------
|
|
// CPropFindMultiResponse::QueryInterface
|
|
// --------------------------------------------------------------------------------
|
|
STDMETHODIMP CPropFindMultiResponse::QueryInterface(REFIID riid, LPVOID *ppv)
|
|
{
|
|
// Locals
|
|
HRESULT hr = S_OK;
|
|
|
|
// Validate params
|
|
if (NULL == ppv)
|
|
{
|
|
hr = TrapError(E_INVALIDARG);
|
|
goto exit;
|
|
}
|
|
|
|
// Initialize params
|
|
*ppv = NULL;
|
|
|
|
// IID_IUnknown
|
|
if (IID_IUnknown == riid)
|
|
*ppv = ((IUnknown *)(IPropFindRequest *)this);
|
|
else if (IID_IPropFindMultiResponse == riid)
|
|
*ppv = ((IPropFindMultiResponse *)this);
|
|
|
|
if (NULL != *ppv)
|
|
{
|
|
((LPUNKNOWN)*ppv)->AddRef();
|
|
goto exit;
|
|
}
|
|
|
|
hr = TrapError(E_NOINTERFACE);
|
|
|
|
exit:
|
|
// Done
|
|
return hr;
|
|
}
|
|
|
|
// --------------------------------------------------------------------------------
|
|
// CPropFindMultiResponse::AddRef
|
|
// --------------------------------------------------------------------------------
|
|
STDMETHODIMP_(ULONG) CPropFindMultiResponse::AddRef(void)
|
|
{
|
|
return ++m_cRef;
|
|
}
|
|
|
|
// --------------------------------------------------------------------------------
|
|
// CPropFindMultiResponse::Release
|
|
// --------------------------------------------------------------------------------
|
|
STDMETHODIMP_(ULONG) CPropFindMultiResponse::Release(void)
|
|
{
|
|
if (0 != --m_cRef)
|
|
return m_cRef;
|
|
delete this;
|
|
return 0;
|
|
}
|
|
|
|
// --------------------------------------------------------------------------------
|
|
// CPropFindMultiResponse::IsComplete
|
|
// --------------------------------------------------------------------------------
|
|
STDMETHODIMP_(BOOL) CPropFindMultiResponse::IsComplete(void)
|
|
{
|
|
return m_bDone;
|
|
}
|
|
|
|
// --------------------------------------------------------------------------------
|
|
// CPropFindMultiResponse::GetLength
|
|
// --------------------------------------------------------------------------------
|
|
STDMETHODIMP CPropFindMultiResponse::GetLength(ULONG *pulLength)
|
|
{
|
|
if (NULL == pulLength)
|
|
return E_INVALIDARG;
|
|
|
|
*pulLength = m_ulResponseLength;
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
// --------------------------------------------------------------------------------
|
|
// CPropFindMultiResponse::GetResponse
|
|
// --------------------------------------------------------------------------------
|
|
STDMETHODIMP CPropFindMultiResponse::GetResponse(ULONG ulIndex,
|
|
IPropFindResponse **ppResponse)
|
|
{
|
|
if (ulIndex >= m_ulResponseLength || !ppResponse)
|
|
return E_INVALIDARG;
|
|
|
|
*ppResponse = m_rgResponses[ulIndex];
|
|
(*ppResponse)->AddRef();
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
// --------------------------------------------------------------------------------
|
|
// CPropFindMultiResponse::HrAddResponse
|
|
// --------------------------------------------------------------------------------
|
|
HRESULT CPropFindMultiResponse::HrAddResponse(IPropFindResponse *pResponse)
|
|
{
|
|
const ULONG c_dwInitialCapacity = 4;
|
|
|
|
HRESULT hr = S_OK;
|
|
IPropFindResponse **ppNewResponses = NULL;
|
|
DWORD dwNewCapacity;
|
|
|
|
if (!pResponse)
|
|
return E_INVALIDARG;
|
|
|
|
|
|
if (m_ulResponseLength == m_ulResponseCapacity)
|
|
{
|
|
dwNewCapacity = !m_ulResponseCapacity ? c_dwInitialCapacity : (m_ulResponseCapacity * 2);
|
|
|
|
if (!MemAlloc((void **)&ppNewResponses, dwNewCapacity * sizeof(IPropFindResponse *)))
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
goto exit;
|
|
}
|
|
|
|
ZeroMemory(ppNewResponses, dwNewCapacity * sizeof(IPropFindResponse *));
|
|
|
|
// copy the old values over
|
|
if (m_ulResponseCapacity)
|
|
CopyMemory(ppNewResponses, m_rgResponses, min(dwNewCapacity, m_ulResponseCapacity) * sizeof(IPropFindResponse *));
|
|
|
|
// free the old buffer
|
|
SafeMemFree(m_rgResponses);
|
|
|
|
m_rgResponses = ppNewResponses;
|
|
m_ulResponseCapacity = dwNewCapacity;
|
|
}
|
|
|
|
m_rgResponses[m_ulResponseLength++] = pResponse;
|
|
pResponse->AddRef();
|
|
|
|
exit:
|
|
return hr;
|
|
}
|
|
|
|
// --------------------------------------------------------------------------------
|
|
// Class CPropFindResponse
|
|
// --------------------------------------------------------------------------------
|
|
|
|
// --------------------------------------------------------------------------------
|
|
// CPropFindResponse::CPropFindResponse
|
|
// --------------------------------------------------------------------------------
|
|
CPropFindResponse::CPropFindResponse(void) :
|
|
m_cRef(1),
|
|
m_bDone(FALSE),
|
|
m_pszHref(NULL),
|
|
m_pRequest(NULL),
|
|
m_shProperties(),
|
|
m_dwCachedNamespaceID(0),
|
|
m_pszCachedNamespacePrefix(NULL)
|
|
{
|
|
|
|
}
|
|
|
|
// --------------------------------------------------------------------------------
|
|
// CPropFindResponse::~CPropFindResponse
|
|
// --------------------------------------------------------------------------------
|
|
CPropFindResponse::~CPropFindResponse(void)
|
|
{
|
|
if (NULL != m_pszHref)
|
|
MemFree(const_cast<char*>(m_pszHref));
|
|
SafeRelease(m_pRequest);
|
|
SafeMemFree(m_pszCachedNamespacePrefix);
|
|
}
|
|
|
|
// --------------------------------------------------------------------------------
|
|
// CPropFindResponse::QueryInterface
|
|
// --------------------------------------------------------------------------------
|
|
STDMETHODIMP CPropFindResponse::QueryInterface(REFIID riid, LPVOID *ppv)
|
|
{
|
|
// Locals
|
|
HRESULT hr = S_OK;
|
|
|
|
// Validate params
|
|
if (NULL == ppv)
|
|
{
|
|
hr = TrapError(E_INVALIDARG);
|
|
goto exit;
|
|
}
|
|
|
|
// Initialize params
|
|
*ppv = NULL;
|
|
|
|
// IID_IUnknown
|
|
if (IID_IUnknown == riid)
|
|
*ppv = ((IUnknown *)(IPropFindResponse *)this);
|
|
else if (IID_IPropFindResponse == riid)
|
|
*ppv = ((IPropFindResponse *)this);
|
|
|
|
if (NULL != *ppv)
|
|
{
|
|
((LPUNKNOWN)*ppv)->AddRef();
|
|
goto exit;
|
|
}
|
|
|
|
hr = TrapError(E_NOINTERFACE);
|
|
|
|
exit:
|
|
// Done
|
|
return hr;
|
|
}
|
|
|
|
// --------------------------------------------------------------------------------
|
|
// CPropFindResponse::AddRef
|
|
// --------------------------------------------------------------------------------
|
|
STDMETHODIMP_(ULONG) CPropFindResponse::AddRef(void)
|
|
{
|
|
return ++m_cRef;
|
|
}
|
|
|
|
// --------------------------------------------------------------------------------
|
|
// CPropFindResponse::Release
|
|
// --------------------------------------------------------------------------------
|
|
STDMETHODIMP_(ULONG) CPropFindResponse::Release(void)
|
|
{
|
|
if (0 != --m_cRef)
|
|
return m_cRef;
|
|
delete this;
|
|
return 0;
|
|
}
|
|
|
|
// --------------------------------------------------------------------------------
|
|
// CPropFindResponse::IsComplete
|
|
// --------------------------------------------------------------------------------
|
|
STDMETHODIMP_(BOOL) CPropFindResponse::IsComplete(void)
|
|
{
|
|
return m_bDone;
|
|
}
|
|
|
|
// --------------------------------------------------------------------------------
|
|
// CPropFindResponse::GetHref
|
|
// --------------------------------------------------------------------------------
|
|
STDMETHODIMP CPropFindResponse::GetHref(LPSTR *pszHref)
|
|
{
|
|
if (NULL == pszHref)
|
|
return E_INVALIDARG;
|
|
|
|
*pszHref = NULL;
|
|
|
|
if (NULL == m_pszHref)
|
|
return E_FAIL;
|
|
|
|
*pszHref = PszDupA(m_pszHref);
|
|
if (!*pszHref)
|
|
return E_OUTOFMEMORY;
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
// --------------------------------------------------------------------------------
|
|
// CPropFindResponse::GetProperty
|
|
// --------------------------------------------------------------------------------
|
|
STDMETHODIMP CPropFindResponse::GetProperty(
|
|
DWORD dwNamespaceID,
|
|
LPSTR pszPropertyName,
|
|
LPSTR *ppszPropertyValue)
|
|
{
|
|
char szLocalPropBuffer[256];
|
|
LPSTR pszPropBuffer = NULL;
|
|
BOOL bFreePropBuffer = FALSE;
|
|
LPSTR pszPrefix = NULL;
|
|
HRESULT hr = S_OK;
|
|
ULONG ulPrefixLength;
|
|
ULONG ulPropertyLength;
|
|
LPSTR pszFoundValue = NULL;
|
|
|
|
if (!pszPropertyName)
|
|
return E_INVALIDARG;
|
|
|
|
*ppszPropertyValue = NULL;
|
|
|
|
// first convert the namespace id into a prefix.
|
|
// to facilitate fast lookups, we cache the most recently
|
|
// seen custom namespace
|
|
|
|
if (dwNamespaceID < c_dwMaxDefinedNamespacePrefix)
|
|
pszPrefix = const_cast<char *>(g_rgszNamespacePrefixes[dwNamespaceID]);
|
|
else if (dwNamespaceID == m_dwCachedNamespaceID)
|
|
pszPrefix = m_pszCachedNamespacePrefix;
|
|
else if (m_pRequest)
|
|
{
|
|
if (FAILED(hr = m_pRequest->GetNamespacePrefix(dwNamespaceID, &pszPrefix)))
|
|
goto exit;
|
|
|
|
// free the one-deep cache and store the new
|
|
// prefix and ID.
|
|
SafeMemFree(m_pszCachedNamespacePrefix);
|
|
m_dwCachedNamespaceID = dwNamespaceID;
|
|
m_pszCachedNamespacePrefix = pszPrefix;
|
|
}
|
|
|
|
ulPrefixLength = lstrlen(pszPrefix);
|
|
ulPropertyLength = lstrlen(pszPropertyName);
|
|
|
|
DWORD cchSize = ARRAYSIZE(szLocalPropBuffer);
|
|
if ((ulPrefixLength + ulPropertyLength + (2 * sizeof(TCHAR))) < 256)
|
|
{
|
|
// the combined length is small enough to use
|
|
// the stack-based buffer
|
|
pszPropBuffer = szLocalPropBuffer;
|
|
}
|
|
else
|
|
{
|
|
cchSize = (ulPrefixLength + ulPropertyLength + 2);
|
|
if (!MemAlloc((void **)&pszPropBuffer, cchSize * sizeof(pszPropBuffer[0])))
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
goto exit;
|
|
}
|
|
|
|
bFreePropBuffer = TRUE;
|
|
}
|
|
|
|
wnsprintf(pszPropBuffer, cchSize, "%s:%s", pszPrefix, pszPropertyName);
|
|
|
|
// XML parser uppercases everything
|
|
CharUpper(pszPropBuffer);
|
|
|
|
// now that the property name has been created, look for the
|
|
// value in the property hash table
|
|
if (FAILED(hr = m_shProperties.Find(pszPropBuffer, FALSE, (void **)&pszFoundValue)))
|
|
goto exit;
|
|
|
|
*ppszPropertyValue = PszDupA(pszFoundValue);
|
|
if (NULL == *ppszPropertyValue)
|
|
hr = E_OUTOFMEMORY;
|
|
|
|
exit:
|
|
if (bFreePropBuffer)
|
|
SafeMemFree(pszPropBuffer);
|
|
|
|
return hr;
|
|
}
|
|
|
|
// --------------------------------------------------------------------------------
|
|
// CPropFindResponse::HrInitPropFindResponse
|
|
// --------------------------------------------------------------------------------
|
|
HRESULT CPropFindResponse::HrInitPropFindResponse(IPropFindRequest *pRequest)
|
|
{
|
|
if (NULL == pRequest)
|
|
return E_INVALIDARG;
|
|
|
|
IxpAssert(!m_pRequest);
|
|
|
|
HRESULT hr = S_OK;
|
|
|
|
m_pRequest = pRequest;
|
|
m_pRequest->AddRef();
|
|
|
|
hr = m_shProperties.Init(17, TRUE);
|
|
|
|
return hr;
|
|
}
|
|
|
|
// --------------------------------------------------------------------------------
|
|
// CPropFindResponse::HrAdoptHref
|
|
// --------------------------------------------------------------------------------
|
|
HRESULT CPropFindResponse::HrAdoptHref(LPCSTR pszHref)
|
|
{
|
|
if (NULL == pszHref)
|
|
return E_INVALIDARG;
|
|
|
|
IxpAssert(!m_pszHref);
|
|
m_pszHref = pszHref;
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
// --------------------------------------------------------------------------------
|
|
// CPropFindResponse::HrAdoptProperty
|
|
// --------------------------------------------------------------------------------
|
|
HRESULT CPropFindResponse::HrAdoptProperty(LPCSTR pszKey, LPCSTR pszValue)
|
|
{
|
|
if (!pszKey || !pszValue)
|
|
return E_INVALIDARG;
|
|
|
|
return m_shProperties.Insert(const_cast<char *>(pszKey), const_cast<char *>(pszValue), NOFLAGS);
|
|
}
|