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.
 
 
 
 
 
 

508 lines
12 KiB

// Copyright (c) 1998 - 1999 Microsoft Corporation. All Rights Reserved.
BSTR FindAttribute(IXMLElement *p, LPWSTR name);
DWORD ParseNum(LPWSTR p);
LONG ReadNumAttribute(IXMLElement *p, LPWSTR attrName, LONG lDefault = 0);
LONGLONG ParseTime(LPWSTR p);
LONGLONG ReadTimeAttribute(IXMLElement *p, LPWSTR attrName, LONGLONG llDefault = 0);
BOOL ReadBoolAttribute(IXMLElement *p, LPWSTR attrName, BOOL bDefault);
class CFakePropertyBag : public IPropertyBag, public CUnknown
{
public:
DECLARE_IUNKNOWN
CGenericList<WCHAR> m_listNames;
CGenericList<WCHAR> m_listValues;
CFakePropertyBag() :
CUnknown(NAME("property bag"), NULL),
m_listNames(NAME("names")), m_listValues(NAME("values"))
{ }
~CFakePropertyBag() { EmptyBag(); };
// override this to publicise our interfaces
STDMETHODIMP NonDelegatingQueryInterface(REFIID riid, void **ppv) {
if (riid == IID_IPropertyBag) {
return GetInterface((IPropertyBag *) this, ppv);
} else {
return CUnknown::NonDelegatingQueryInterface(riid, ppv);
}
};
STDMETHOD(Read)(LPCOLESTR pszPropName, VARIANT *pvar, IErrorLog* pErrorLog);
STDMETHOD(Write)(LPCOLESTR pszPropName, VARIANT *pVar);
void EmptyBag() {
// delete the stored strings....
BSTR p;
do {
p = m_listValues.RemoveHead();
if (p)
SysFreeString(p);
} while (p);
do {
p = m_listNames.RemoveHead();
if (p)
SysFreeString(p);
} while (p);
}
};
HRESULT HandleParamTags(IXMLElement *p, IUnknown *punk);
HRESULT GetFilterFromCategory(REFCLSID clsidCategory, WCHAR *lpwInstance, IBaseFilter **ppf);
#ifndef NO_QXMLHELP_IMPL
BSTR FindAttribute(IXMLElement *p, LPWSTR name)
{
VARIANT v;
VariantInit(&v);
HRESULT hr = p->getAttribute(name, &v);
if (FAILED(hr))
return NULL;
return V_BSTR(&v);
}
DWORD ParseNum(LPWSTR p)
{
DWORD dwRet = 0;
WCHAR c;
while (((c = *p++) >= L'0') && (c <= L'9') )
dwRet = (dwRet * 10) + (c - L'0');
return dwRet;
}
LONG ReadNumAttribute(IXMLElement *p, LPWSTR attrName, LONG lDefault /* = 0 */)
{
BSTR val = FindAttribute(p, attrName);
LONG lRet = lDefault;
if (val) {
lRet = ParseNum(val);
SysFreeString(val);
}
return lRet;
}
LONGLONG ParseTime(LPWSTR p)
{
DbgLog((LOG_TRACE, 4, TEXT("ParseTime: parsing '%hs'"), p));
WCHAR c = *p++;
// !!! could handle SMPTE frames here?
DWORD dwSec = 0;
DWORD dwMin = 0;
DWORD dwFrac = 0;
int iFracPlaces = -1;
while (c != L'\0') {
if (c >= L'0' && c <= L'9') {
if (iFracPlaces >= 0) {
++iFracPlaces;
dwFrac = dwFrac * 10 + (c - L'0');
} else {
dwSec = dwSec * 10 + (c - L'0');
}
} else if (iFracPlaces >= 0) {
break;
} else if (c == L':') {
dwMin = dwMin * 60 + dwSec;
dwSec = 0;
} else if (c == L'.') {
iFracPlaces = 0;
} else
break; // !!! allow for skipping whitespace?
c = *p++;
}
LONGLONG llRet = (LONGLONG) dwFrac * UNITS;
while (iFracPlaces-- > 0) {
llRet /= 10;
}
llRet += (LONGLONG) dwMin * 60 * UNITS + (LONGLONG) dwSec * UNITS;
DbgLog((LOG_TRACE, 4, TEXT("ParseTime: returning %d ms"), (DWORD) (llRet / 10000)));
return llRet;
}
LONGLONG ReadTimeAttribute(IXMLElement *p, LPWSTR attrName, LONGLONG llDefault /* = 0 */)
{
BSTR val = FindAttribute(p, attrName);
LONGLONG llRet = llDefault;
if (val) {
llRet = ParseTime(val);
SysFreeString(val);
}
return llRet;
}
BOOL ReadBoolAttribute(IXMLElement *p, LPWSTR attrName, BOOL bDefault)
{
BSTR val = FindAttribute(p, attrName);
if (val) {
WCHAR c = *val;
if (c == L'y' || c == L'Y' || c == L't' || c == L'T' || c == L'1')
bDefault = TRUE;
else if (c == L'n' || c == L'N' || c == L'f' || c == L'F' || c == L'0')
bDefault = FALSE;
else {
DbgLog((LOG_ERROR, 1, TEXT("Looking for yes/no value, found '%ls'"), val));
}
SysFreeString(val);
}
return bDefault;
}
STDMETHODIMP CFakePropertyBag::Read(LPCOLESTR pszPropName, VARIANT *pvar,
IErrorLog* pErrorLog)
{
USES_CONVERSION;
if(pvar && pvar->vt != VT_EMPTY && pvar->vt != VT_BSTR)
return E_INVALIDARG;
HRESULT hr = HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
POSITION pos1, pos2;
for(pos1 = m_listNames.GetHeadPosition(),
pos2 = m_listValues.GetHeadPosition();
pos1;
pos1 = m_listNames.Next(pos1),
pos2 = m_listValues.Next(pos2))
{
WCHAR *pName = m_listNames.Get(pos1);
if (lstrcmpW(pName, pszPropName) == 0)
{
WCHAR *pValue = m_listValues.Get(pos2);
hr = S_OK;
if(pvar)
{
V_VT(pvar) = VT_BSTR;
V_BSTR(pvar) = ::SysAllocString(pValue);
if (!V_BSTR(pvar))
hr = E_OUTOFMEMORY;
return hr;
}
}
}
if(pos1 == 0)
{
ASSERT(hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND));
}
return hr;
};
STDMETHODIMP CFakePropertyBag::Write(LPCOLESTR pszPropName, VARIANT *pvar)
{
// !!! look in list of values to see if it's already there?
BSTR bstrName = SysAllocString(pszPropName);
if (!bstrName)
return E_OUTOFMEMORY;
BSTR bstrValue;
if (V_VT(pvar) == VT_BSTR) {
bstrValue = SysAllocString(V_BSTR(pvar));
if (!bstrValue)
return E_OUTOFMEMORY;
} else {
VARIANT v;
V_VT(&v) = VT_EMPTY;
HRESULT hr = VariantChangeType(&v, pvar, 0, VT_BSTR);
if (FAILED(hr))
return hr;
bstrValue = V_BSTR(&v);
}
m_listNames.AddTail(bstrName);
m_listValues.AddTail(bstrValue);
return S_OK;
}
HRESULT HandleParamTags(IXMLElement *p, IUnknown *punk)
{
HRESULT hr = S_OK;
CFakePropertyBag bag;
IXMLElementCollection *pcoll;
hr = p->get_children(&pcoll);
if (hr == S_FALSE)
return S_OK; // nothing to do
long lChildren;
hr = pcoll->get_length(&lChildren);
int iParamsFound = 0;
VARIANT var;
var.vt = VT_I4;
var.lVal = 0;
for (SUCCEEDED(hr); var.lVal < lChildren; (var.lVal)++) {
IDispatch *pDisp;
hr = pcoll->item(var, var, &pDisp);
if (SUCCEEDED(hr) && pDisp) {
IXMLElement *pelem;
hr = pDisp->QueryInterface(__uuidof(IXMLElement), (void **) &pelem);
if (SUCCEEDED(hr)) {
bool fAdded = false;
BSTR bstrTagName;
hr = pelem->get_tagName(&bstrTagName);
if (SUCCEEDED(hr)) {
if (!lstrcmpiW(bstrTagName, L"param")) {
BSTR bstrName = FindAttribute(pelem, L"name");
if (bstrName) {
BSTR bstrValue = FindAttribute(pelem, L"value");
if (!bstrValue) {
hr = pelem->get_text(&bstrValue);
}
if (bstrValue) {
// add this name/value pair to bag
if(bag.m_listNames.AddTail(bstrName))
{
if(bag.m_listValues.AddTail(bstrValue)) {
fAdded = true;
++iParamsFound;
}
else
{
bag.m_listNames.RemoveTail();
}
}
if(!fAdded) {
SysFreeString(bstrValue);
}
}
if(!fAdded) {
SysFreeString(bstrName);
}
} else {
hr = VFW_E_INVALID_FILE_FORMAT;
}
} else {
// !!! unknown other subtag?
}
SysFreeString(bstrTagName);
}
pelem->Release();
}
pDisp->Release();
}
}
pcoll->Release();
if (SUCCEEDED(hr) && iParamsFound) {
// load properties from the bag
IPersistPropertyBag *pPPB;
HRESULT hr2 = punk->QueryInterface(IID_IPersistPropertyBag,
(void **) &pPPB);
if (SUCCEEDED(hr2)) {
if (iParamsFound == 1 && !lstrcmpW(L"data", bag.m_listNames.GetHead())) {
DbgLog((LOG_TRACE, 1, TEXT("Using IPersistStream instead of IPersistPropertyBag")));
hr2 = E_NOINTERFACE;
} else {
hr2 = pPPB->Load(&bag, NULL);
if (FAILED(hr2)) {
DbgLog((LOG_ERROR, 1, TEXT("Error %x loading parameters"), hr2));
}
}
pPPB->Release();
}
if (FAILED(hr2)) {
DbgLog((LOG_ERROR, 1, TEXT("Filter doesn't take parameters?")));
// !!! loop through properties handling special cases?
// if there's an "src" param, send it to IFileSource/Sink
VARIANT v;
v.vt = VT_BSTR;
hr2 = bag.Read(L"src", &v, NULL);
if (SUCCEEDED(hr2)) {
IFileSourceFilter *pFSF;
hr2 = punk->QueryInterface(IID_IFileSourceFilter,
(void **) &pFSF);
if (SUCCEEDED(hr2)) {
hr = pFSF->Load(V_BSTR(&v), NULL);
pFSF->Release();
} else {
IFileSinkFilter *pFSF;
hr2 = punk->QueryInterface(IID_IFileSinkFilter,
(void **) &pFSF);
if (SUCCEEDED(hr2)) {
hr = pFSF->SetFileName(V_BSTR(&v), NULL);
pFSF->Release();
}
}
SysFreeString(V_BSTR(&v));
}
v.vt = VT_BSTR;
hr2 = bag.Read(L"data", &v, NULL);
if (SUCCEEDED(hr2)) {
BSTR bstr = V_BSTR(&v);
IPersistStream *pPS;
hr2 = punk->QueryInterface(IID_IPersistStream,
(void **) &pPS);
if (SUCCEEDED(hr2)) {
// convert hex data into an IStream....
UINT dwLen = SysStringLen(bstr);
HGLOBAL h = GlobalAlloc(GHND, dwLen + 1);
if (h) {
LPBYTE p = (LPBYTE) GlobalLock(h);
for (UINT i = 0; i < dwLen / 2; i++) {
WCHAR wch = bstr[i * 2];
if (wch >= L'0' && wch <= L'9')
p[i] = (BYTE) (wch - L'0') * 16;
else if (wch >= L'A' && wch <= L'F')
p[i] = (BYTE) (wch - L'A' + 10) * 16;
wch = bstr[i * 2 + 1];
if (wch >= L'0' && wch <= L'9')
p[i] += (BYTE) (wch - L'0');
else if (wch >= L'A' && wch <= L'F')
p[i] += (BYTE) (wch - L'A' + 10);
}
IStream *ps;
hr2 = CreateStreamOnHGlobal(h, TRUE, &ps);
if (SUCCEEDED(hr2)) {
hr2 = pPS->Load(ps);
ps->Release();
}
}
pPS->Release();
}
SysFreeString(bstr);
}
}
}
return hr;
}
HRESULT GetFilterFromCategory(REFCLSID clsidCategory, WCHAR *lpwInstance, IBaseFilter **ppf)
{
ICreateDevEnum *pCreateDevEnum;
HRESULT hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC_SERVER,
IID_ICreateDevEnum, (void**)&pCreateDevEnum);
if (hr != NOERROR)
return hr;
IEnumMoniker *pEm;
hr = pCreateDevEnum->CreateClassEnumerator(clsidCategory, &pEm, 0);
pCreateDevEnum->Release();
if (hr != NOERROR)
return hr;
pEm->Reset(); // !!! needed?
ULONG cFetched;
IMoniker *pM;
while(hr = pEm->Next(1, &pM, &cFetched), hr==S_OK)
{
if (lpwInstance) {
IPropertyBag *pBag;
hr = pM->BindToStorage(0, 0, IID_IPropertyBag, (void **)&pBag);
if(SUCCEEDED(hr)) {
VARIANT var;
var.vt = VT_BSTR;
hr = pBag->Read(L"FriendlyName", &var, NULL);
pBag->Release();
if (hr == NOERROR) {
if (lstrcmpiW(var.bstrVal, lpwInstance) != 0) {
SysFreeString(var.bstrVal);
pM->Release();
continue;
}
SysFreeString(var.bstrVal);
} else
continue;
}
}
hr = pM->BindToObject(0, 0, IID_IBaseFilter, (void**)ppf);
pM->Release();
break;
}
pEm->Release();
return hr;
}
#endif