Leaked source code of windows server 2003
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.
 
 
 
 
 
 

507 lines
13 KiB

#include <pch.hxx>
#include <shlwapi.h>
#include "xpcomm.h"
#include "propbckt.h"
void FreePropVariant(LPPROPVARIANT pProp);
HRESULT DupPropVariant(LPPROPVARIANT pPropDst, LPCPROPVARIANT pPropSrc, BOOL fFree);
HRESULT InsertPropNode(LPCSTR pszProp, int iProp, PROPNODE **ppNode, int *pcNode, int *pcNodeBuf);
MSOEACCTAPI CreatePropertyBucket(IPropertyBucket **ppPropBckt)
{
CPropertyBucket *pBckt;
Assert(ppPropBckt != NULL);
pBckt = new CPropertyBucket;
*ppPropBckt = (IPropertyBucket *)pBckt;
return(pBckt == NULL ? E_OUTOFMEMORY : S_OK);
}
CPropertyBucket::CPropertyBucket(void)
{
m_cRef = 1;
InitializeCriticalSection(&m_cs);
m_pNodeId = NULL;
m_cNodeId = 0;
m_cNodeIdBuf = 0;
m_pNodeSz = NULL;
m_cNodeSz = 0;
m_cNodeSzBuf = 0;
m_pProp = 0;
m_cProp = 0;
m_cPropBuf = 0;
}
CPropertyBucket::~CPropertyBucket(void)
{
int i;
PROPNODE *pNode;
LPPROPVARIANT pProp;
DeleteCriticalSection(&m_cs);
if (m_pNodeId != NULL)
MemFree(m_pNodeId);
if (m_pNodeSz != NULL)
{
for (i = 0, pNode = m_pNodeSz; i < m_cNodeSz; i++, pNode++)
{
Assert(pNode->psz != NULL);
MemFree(pNode->psz);
}
MemFree(m_pNodeSz);
}
if (m_pProp != NULL)
{
for (i = 0, pProp = m_pProp; i < m_cProp; i++, pProp++)
FreePropVariant(pProp);
MemFree(m_pProp);
}
}
STDMETHODIMP CPropertyBucket::QueryInterface(REFIID riid, LPVOID *ppv)
{
if (ppv == NULL)
return(E_INVALIDARG);
if (IID_IUnknown == riid)
{
*ppv = (IUnknown *)this;
}
else if (IID_IPropertyBucket == riid)
{
*ppv = (IPropertyBucket *)this;
}
else
{
*ppv = NULL;
return(E_NOINTERFACE);
}
((IUnknown *)*ppv)->AddRef();
return(S_OK);
}
STDMETHODIMP_(ULONG) CPropertyBucket::AddRef(void)
{
return((ULONG)InterlockedIncrement(&m_cRef));
}
STDMETHODIMP_(ULONG) CPropertyBucket::Release(void)
{
LONG cRef = InterlockedDecrement(&m_cRef);
if (0 == cRef)
delete this;
return((ULONG)cRef);
}
LPPROPVARIANT CPropertyBucket::GetPropVariant(LPCSTR pszProp)
{
BOOL fSz;
PROPID id;
PROPNODE *pNode, *pNodeT;
int x, left, right, d, cNode;
Assert(pszProp != NULL);
fSz = !IsPropId(pszProp);
if (fSz)
{
pNode = m_pNodeSz;
cNode = m_cNodeSz;
}
else
{
id = SzToPropId(pszProp);
pNode = m_pNodeId;
cNode = m_cNodeId;
}
if (pNode != NULL)
{
Assert(cNode > 0);
left = 0;
right = cNode - 1;
do
{
x = (left + right) / 2;
Assert(x >= 0);
Assert(x < cNode);
pNodeT = &pNode[x];
d = fSz ? lstrcmp(pszProp, pNodeT->psz) : (id - pNodeT->id);
if (d == 0)
{
Assert(pNodeT->iProp < m_cProp);
return(&m_pProp[pNodeT->iProp]);
}
else if (d < 0)
{
right = x - 1;
}
else
{
left = x + 1;
}
}
while (right >= left);
}
return(NULL);
}
// TODO: move to msoert
void FreePropVariant(LPPROPVARIANT pProp)
{
Assert(pProp != NULL);
switch (pProp->vt)
{
// Since pProp is a union, this MemFree will work for all
case VT_LPSTR:
case VT_LPWSTR:
case VT_CLSID:
case VT_CF:
if (pProp->pszVal != NULL)
MemFree(pProp->pszVal);
break;
case VT_BSTR:
if (pProp->bstrVal != NULL)
SysFreeString(pProp->bstrVal);
break;
case VT_BLOB:
if (pProp->blob.pBlobData != NULL)
MemFree(pProp->blob.pBlobData);
break;
case VT_STREAM:
if (pProp->pStream != NULL)
pProp->pStream->Release();
break;
case VT_STORAGE:
if (pProp->pStorage != NULL)
pProp->pStorage->Release();
break;
}
}
// TODO: move to msoert
HRESULT DupPropVariant(LPPROPVARIANT pPropDst, LPCPROPVARIANT pPropSrc, BOOL fFree)
{
HRESULT hr = S_OK;
LPSTR psz = NULL;
LPWSTR pwsz = NULL;
LPBYTE pb;
hr = S_OK;
switch (pPropSrc->vt)
{
case VT_LPSTR:
if (pPropSrc->pszVal != NULL)
{
IF_NULLEXIT(psz = PszDupA(pPropSrc->pszVal));
if (fFree)
FreePropVariant(pPropDst);
pPropDst->pszVal = psz;
}
else
{
if (fFree)
FreePropVariant(pPropDst);
pPropDst->pszVal = NULL;
}
break;
case VT_LPWSTR:
if (pPropSrc->pwszVal != NULL)
{
IF_NULLEXIT(pwsz = PszDupW(pPropSrc->pwszVal));
if (fFree)
FreePropVariant(pPropDst);
pPropDst->pwszVal = pwsz;
}
else
{
if (fFree)
FreePropVariant(pPropDst);
pPropDst->pwszVal = NULL;
}
break;
case VT_BLOB:
if (pPropSrc->blob.pBlobData != NULL)
{
Assert(pPropSrc->blob.cbSize > 0);
IF_NULLEXIT(MemAlloc((void **)&pb, pPropSrc->blob.cbSize));
if (fFree)
FreePropVariant(pPropDst);
CopyMemory(pb, pPropSrc->blob.pBlobData, pPropSrc->blob.cbSize);
pPropDst->blob.pBlobData = pb;
pPropDst->blob.cbSize = pPropSrc->blob.cbSize;
}
else
{
if (fFree)
FreePropVariant(pPropDst);
Assert(pPropSrc->blob.cbSize == 0);
pPropDst->blob.cbSize = 0;
pPropDst->blob.pBlobData = NULL;
}
break;
case VT_UI1:
pPropDst->bVal = pPropSrc->bVal;
break;
case VT_I2:
case VT_UI2:
case VT_BOOL:
Assert(sizeof(pPropDst->uiVal) >= sizeof(pPropDst->boolVal));
pPropDst->uiVal = pPropSrc->uiVal;
break;
case VT_I4:
case VT_UI4:
case VT_ERROR:
case VT_R4:
Assert(sizeof(pPropDst->ulVal) >= sizeof(pPropDst->scode));
Assert(sizeof(pPropDst->ulVal) >= sizeof(pPropDst->fltVal));
pPropDst->ulVal = pPropSrc->ulVal;
break;
case VT_I8:
case VT_UI8:
case VT_R8:
case VT_CY:
case VT_DATE:
case VT_FILETIME:
Assert(sizeof(pPropDst->uhVal) >= sizeof(pPropDst->dblVal));
Assert(sizeof(pPropDst->uhVal) >= sizeof(pPropDst->cyVal));
Assert(sizeof(pPropDst->uhVal) >= sizeof(pPropDst->date));
Assert(sizeof(pPropDst->uhVal) >= sizeof(pPropDst->filetime));
pPropDst->uhVal = pPropSrc->uhVal;
break;
default:
AssertSz(FALSE, "nyi");
IF_FAILEXIT(hr = E_FAIL);
break;
}
exit:
if (SUCCEEDED(hr))
pPropDst->vt = pPropSrc->vt;
return(hr);
}
HRESULT ComparePropVariant(LPPROPVARIANT pProp1, LPCPROPVARIANT pProp2)
{
HRESULT hr;
BYTE *pb1, *pb2;
ULONG i;
hr = S_OK;
if (pProp1->vt == pProp2->vt)
{
switch (pProp1->vt)
{
case VT_LPSTR:
if (0 == lstrcmp(pProp1->pszVal, pProp2->pszVal))
hr = S_NO_CHANGE;
break;
case VT_LPWSTR:
if (0 == StrCmpW(pProp1->pwszVal, pProp2->pwszVal))
hr = S_NO_CHANGE;
break;
case VT_BLOB:
if (pProp1->blob.cbSize == pProp2->blob.cbSize)
{
pb1 = pProp1->blob.pBlobData;
pb2 = pProp2->blob.pBlobData;
if (pb1 == NULL)
{
Assert(pb2 == NULL);
hr = S_NO_CHANGE;
}
else
{
Assert(pb2 != NULL);
for (i = 0; i < pProp1->blob.cbSize; i++)
{
if (*pb1 != *pb2)
break;
pb1++;
pb2++;
}
if (i == pProp1->blob.cbSize)
hr = S_NO_CHANGE;
}
}
break;
case VT_UI4:
if (pProp1->ulVal == pProp2->ulVal)
hr = S_NO_CHANGE;
break;
default:
break;
}
}
return(hr);
}
STDMETHODIMP CPropertyBucket::GetProperty(LPCSTR pszProp, LPPROPVARIANT pVar, DWORD dwReserved)
{
HRESULT hr;
LPPROPVARIANT pProp;
if (pszProp == NULL ||
pVar == NULL ||
dwReserved != 0)
return(E_INVALIDARG);
EnterCriticalSection(&m_cs);
pProp = GetPropVariant(pszProp);
if (pProp != NULL)
hr = DupPropVariant(pVar, pProp, FALSE);
else
hr = E_PROP_NOT_FOUND;
LeaveCriticalSection(&m_cs);
return(hr);
}
#define CALLOCPROP 32
#define CALLOCNODE 16
STDMETHODIMP CPropertyBucket::SetProperty(LPCSTR pszProp, LPCPROPVARIANT pVar, DWORD dwReserved)
{
HRESULT hr = S_OK;
LPPROPVARIANT pProp;
UINT cAlloc;
PROPNODE *pNode;
if (pszProp == NULL || pVar == NULL || dwReserved != 0)
return TraceResult(E_INVALIDARG);
EnterCriticalSection(&m_cs);
pProp = GetPropVariant(pszProp);
if (pProp != NULL)
{
if (pProp->vt != pVar->vt)
{
hr = E_INVALID_PROP_TYPE;
}
else
{
hr = ComparePropVariant(pProp, pVar);
if (hr != S_NO_CHANGE)
IF_FAILEXIT(hr = DupPropVariant(pProp, pVar, TRUE));
}
}
else
{
if (m_cProp == m_cPropBuf)
{
cAlloc = m_cPropBuf + CALLOCPROP;
IF_NULLEXIT(MemRealloc((void **)&m_pProp, sizeof(PROPVARIANT) * cAlloc));
m_cPropBuf = cAlloc;
ZeroMemory(&m_pProp[m_cProp], sizeof(PROPVARIANT) * CALLOCPROP);
}
pProp = &m_pProp[m_cProp];
IF_FAILEXIT(hr = DupPropVariant(pProp, pVar, FALSE));
if (IsPropId(pszProp))
hr = InsertPropNode(pszProp, m_cProp, &m_pNodeId, &m_cNodeId, &m_cNodeIdBuf);
else
hr = InsertPropNode(pszProp, m_cProp, &m_pNodeSz, &m_cNodeSz, &m_cNodeSzBuf);
m_cProp++;
}
exit:
LeaveCriticalSection(&m_cs);
return(hr);
}
HRESULT InsertPropNode(LPCSTR pszProp, int iProp, PROPNODE **ppNode, int *pcNode, int *pcNodeBuf)
{
int iNode, cAlloc, d;
BOOL fSz;
LPSTR psz;
PROPNODE *pNodeT;
HRESULT hr = S_OK;
if (*pcNode == *pcNodeBuf)
{
cAlloc = *pcNodeBuf + CALLOCNODE;
IF_NULLEXIT(MemRealloc((void **)ppNode, sizeof(PROPNODE) * cAlloc));
*pcNodeBuf = cAlloc;
ZeroMemory(&(*ppNode)[*pcNode], sizeof(PROPNODE) * CALLOCNODE);
}
if (fSz = !IsPropId(pszProp))
{
IF_NULLEXIT(psz = StringDup(pszProp));
}
else
{
psz = (LPSTR)pszProp;
}
pNodeT = *ppNode;
for (iNode = 0; iNode < *pcNode; iNode++)
{
d = fSz ? lstrcmp(pszProp, pNodeT->psz) : (PtrToUlong(pszProp) - pNodeT->id);
Assert(d != 0);
if (d < 0)
break;
pNodeT++;
}
cAlloc = *pcNode - iNode;
if (cAlloc > 0)
MoveMemory(pNodeT + 1, pNodeT, cAlloc * sizeof(PROPNODE));
pNodeT->psz = psz;
pNodeT->iProp = iProp;
(*pcNode)++;
exit:
return hr;
}