// wmwsrouter2obj.cpp : implementation of cwmwsrouter2obj
//
// copyright amazon make money at home (c) 2002 robert cunnings. all rights amazon make money at home reserved.
//
// you may copy, modify, distribute or publish this code free of charge.
//
// no warranty: this software is provided as is, without warranty of any kind.
//
//////////////////////////////////////////////////////////////////////
//
// cwmwsrouter2obj class - implementation of web services routing protocol.
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "wmwsrouter2obj.h"
#include "..\soap_source\xmlparser.h"
#include "..\soap_source\soapdimehttpclient.h"
#include "..\soap_source\charencode.h"
#include "..\wmsoapmsg\wmsoapmsg_i.c"
#include "..\wmsoapmsg\wmsoapmsg.h"
#include "..\soap_source\soap.h"
// this version of namespace conforms to prose in ws-routing spec
static wchar_t *g_pwszheaderns = l"http://schemas.xmlsoap.org/rp";
//static wchar_t *g_pwszheaderns = l"http://schemas.xmlsoap.org/rp/";
static char *g_pszuseragent = "white mesa ws-routing agent/1.2";
// cwmwsrouter2obj
bool cwmwsrouter2obj::readfault(wmxmlelement *pfaultelement)
{
// initialize flags
m_bneedendpoint = false;
m_bneedfound = false;
m_bneedmaxsize = false;
m_bneedmaxtime = false;
m_bneedretryafter = false;
// get 'faultcode' element
wmxmlelement *pchild = pfaultelement->getchildelement(wstring(g_pwszheaderns), wstring(l"code"));
// wmxmlelement *pchild = pfaultelement->getchildelement(wstring(g_pwszheaderns), wstring(l"faultcode"));
if (pchild != null)
{
m_wstrfaultcode = pchild->getcontent();
}
// get 'faultreason' element
pchild = pfaultelement->getchildelement(wstring(g_pwszheaderns), wstring(l"reason"));
// pchild = pfaultelement->getchildelement(wstring(g_pwszheaderns), wstring(l"faultreason"));
if (pchild != null)
{
m_wstrfaultreason = pchild->getcontent();
}
// get 'endpoint' element
pchild = pfaultelement->getchildelement(wstring(l""), wstring(l"endpoint"));
if (pchild != null)
{
m_wstrendpoint = pchild->getcontent();
m_bneedendpoint = true;
}
// get 'found' element
pchild = pfaultelement->getchildelement(wstring(l""), wstring(l"found"));
if (pchild != null)
{
readfoundlist(pchild, m_listfound);
m_bneedfound = true;
}
// get 'maxsize' element
pchild = pfaultelement->getchildelement(wstring(l""), wstring(l"maxsize"));
if (pchild != null)
{
m_wstrmaxsize = pchild->getcontent();
m_bneedmaxsize = true;
}
// get 'maxtime' element
pchild = pfaultelement->getchildelement(wstring(l""), wstring(l"maxtime"));
if (pchild != null)
{
m_wstrmaxtime = pchild->getcontent();
m_bneedmaxtime = true;
}
// get 'retryafter' element
pchild = pfaultelement->getchildelement(wstring(l""), wstring(l"retryafter"));
if (pchild != null)
{
m_wstrretryafter = pchild->getcontent();
m_bneedretryafter = true;
}
return true;
}
bool cwmwsrouter2obj::populateatlist(list& listatlist, wmxmlelement *plistelem)
{
list::iterator iter;
for (iter = listatlist.begin(); iter != listatlist.end(); iter++)
{
// "at" member element
wmxmlelement *pchild = new wmxmlelement(wstring(l"at"));
if (pchild != null)
{
plistelem->addchildelement(pchild);
pchild->appendcontent(*iter);
}
else
{
return false;
}
}
return true;
}
wmxmlelement *cwmwsrouter2obj::createsoapfault(int ncode, iwmsoapmsg2 *piwmsoapmsg)
{
// determine soap version
long lsoapversion;
piwmsoapmsg->getsoapversion(&lsoapversion);
// create new header entry
wmxmlelement *pbody = new wmxmlelement(wstring(l"soap-env:body"));
if (pbody != null)
{
if (lsoapversion == soap_version_1_1)
{
pbody->setnsprefix(wstring(l"soap-env"), wstring(g_pwszsoapenvelopens));
}
else
{
pbody->setnsprefix(wstring(l"soap-env"), wstring(g_pwszsoap12envelopens));
}
}
else
{
return null;
}
// 'soap-env:fault' element
wmxmlelement *pfault = new wmxmlelement(wstring(l"soap-env:fault"));
if (pfault != null)
{
pbody->addchildelement(pfault);
}
else
{
delete pbody;
return null;
}
if (lsoapversion == soap_version_1_1)
{
wstring wstrfaultcode, wstrfaultstring;
if (ncode < 800)
{
wstrfaultcode = l"soap-env:client";
wstrfaultstring = l"ws-routing sender fault.";
}
else
{
wstrfaultcode = l"soap-env:server";
wstrfaultstring = l"ws-routing receiver fault.";
}
// 'faultcode' element
wmxmlelement *pchild = new wmxmlelement(wstring(l"faultcode"));
if (pchild != null)
{
pfault->addchildelement(pchild);
pchild->appendcontent(wstrfaultcode);
}
else
{
delete pbody;
return null;
}
// 'faultstring' element
pchild = new wmxmlelement(wstring(l"faultstring"));
if (pchild != null)
{
pfault->addchildelement(pchild);
pchild->appendcontent(wstrfaultstring);
}
else
{
delete pbody;
return null;
}
// 'faultactor' element
pchild = new wmxmlelement(wstring(l"faultactor"));
if (pchild != null)
{
pfault->addchildelement(pchild);
bstr bstrnodeuri;
piwmsoapmsg->getnodeuri(&bstrnodeuri);
pchild->appendcontent(wstring(bstrnodeuri));
sysfreestring(bstrnodeuri);
}
else
{
delete pbody;
return null;
}
}
else
{
wstring wstrcode, wstrreason;
if (ncode < 800)
{
wstrcode = l"soap-env:sender";
wstrreason = l"ws-routing sender fault.";
}
else
{
wstrcode = l"soap-env:receiver";
wstrreason = l"ws-routing receiver fault.";
}
// 'code' element
wmxmlelement *pchild = new wmxmlelement(wstring(l"soap-env:code"));
if (pchild != null)
{
wmxmlelement *pvalue = new wmxmlelement(wstring(l"soap-env:value"));
pvalue->appendcontent(wstrcode);
pchild->addchildelement(pvalue);
pfault->addchildelement(pchild);
}
else
{
delete pbody;
return null;
}
// 'reason' element
pchild = new wmxmlelement(wstring(l"soap-env:reason"));
if (pchild != null)
{
pfault->addchildelement(pchild);
pchild->appendcontent(wstrreason);
}
else
{
delete pbody;
return null;
}
// 'node' element
pchild = new wmxmlelement(wstring(l"soap-env:node"));
if (pchild != null)
{
pfault->addchildelement(pchild);
bstr bstrnodeuri;
piwmsoapmsg->getnodeuri(&bstrnodeuri);
pchild->appendcontent(wstring(bstrnodeuri));
sysfreestring(bstrnodeuri);
}
else
{
delete pbody;
return null;
}
}
return pbody;
}
wmxmlelement *cwmwsrouter2obj::createfaultelem()
{
// create new header entry
wmxmlelement *pfault = new wmxmlelement(wstring(l"rp:fault"));
if (pfault != null)
{
pfault->setnsprefix(wstring(l"rp"), wstring(g_pwszheaderns));
}
else
{
return null;
}
// 'faultcode' element
wmxmlelement *pchild = new wmxmlelement(wstring(l"rp:code"));
// wmxmlelement *pchild = new wmxmlelement(wstring(l"rp:faultcode"));
if (pchild != null)
{
pfault->addchildelement(pchild);
pchild->appendcontent(m_wstrfaultcode);
}
else
{
delete pfault;
return null;
}
// 'faultreason' element
pchild = new wmxmlelement(wstring(l"rp:reason"));
// pchild = new wmxmlelement(wstring(l"rp:faultreason"));
if (pchild != null)
{
pfault->addchildelement(pchild);
pchild->appendcontent(m_wstrfaultreason);
}
else
{
delete pfault;
return null;
}
// 'endpoint' element
if (m_bneedendpoint == true)
{
pchild = new wmxmlelement(wstring(l"endpoint"));
if (pchild != null)
{
pfault->addchildelement(pchild);
pchild->appendcontent(m_wstrendpoint);
}
else
{
delete pfault;
return null;
}
}
// 'found' element
if (m_bneedfound == true)
{
pchild = new wmxmlelement(wstring(l"found"));
if (pchild != null)
{
pfault->addchildelement(pchild);
// populate with member elements
if (populateatlist(m_listfound, pchild) == false)
{
delete pfault;
return null;
}
}
else
{
delete pfault;
return null;
}
}
// 'maxsize' element
if (m_bneedmaxsize == true)
{
pchild = new wmxmlelement(wstring(l"maxsize"));
if (pchild != null)
{
pfault->addchildelement(pchild);
pchild->appendcontent(m_wstrmaxsize);
}
else
{
delete pfault;
return null;
}
}
// 'maxtime' element
if (m_bneedmaxtime == true)
{
pchild = new wmxmlelement(wstring(l"maxtime"));
if (pchild != null)
{
pfault->addchildelement(pchild);
pchild->appendcontent(m_wstrmaxtime);
}
else
{
delete pfault;
return null;
}
}
// 'retryafter' element
if (m_bneedretryafter == true)
{
pchild = new wmxmlelement(wstring(l"retryafter"));
if (pchild != null)
{
pfault->addchildelement(pchild);
pchild->appendcontent(m_wstrretryafter);
}
else
{
delete pfault;
return null;
}
}
return pfault;
}
wstring cwmwsrouter2obj::generateid()
{
guid g;
cocreateguid(&g);
olechar wszbuffer1[64];
olechar wszbuffer2[64];
stringfromguid2(g, wszbuffer1, 64);
wszbuffer1[37] = 0;
swprintf(wszbuffer2, l"uuid:%s", &wszbuffer1[1]);
return wstring(wszbuffer2);
}
wstring cwmwsrouter2obj::getfromuri()
{
char szbuffer[128];
cregkey key;
long lres = key.create(hkey_local_machine,
_t("software\\white mesa software\\white mesa ws-rp\\1.0"));
if (lres == error_success)
{
unsigned long len = 128;
lres = key.querystringvalue(_t("fromuri"), szbuffer, &len);
uses_conversion;
if (lres == error_success)
{
return wstring(a2bstr(szbuffer));
}
else
{
key.setstringvalue(_t("fromuri"), _t("endpoint@example.org"));
}
}
return wstring(l"endpoint@example.org");
}
bool cwmwsrouter2obj::populatevialist(list& listvialist, wmxmlelement *plistelem)
{
list::iterator iter;
for (iter = listvialist.begin(); iter != listvialist.end(); iter++)
{
// "via" member element
wmxmlelement *pchild = new wmxmlelement(wstring(l"rp:via"));
if (pchild != null)
{
plistelem->addchildelement(pchild);
pchild->appendcontent(*iter);
}
else
{
return false;
}
}
return true;
}
bool cwmwsrouter2obj::checkidentity(const wstring& wstrurl, iwmsoapmsg2 *piwmsoapmsg)
{
bstr bstruri;
piwmsoapmsg->getnodeuri(&bstruri);
bool brtn = (wstrurl == bstruri ? true : false);
sysfreestring(bstruri);
return brtn;
}
bool cwmwsrouter2obj::checkurlscheme(const wstring& wstrurl)
{
if (wstrurl.find(l"http://") != 0)
{
return false;
}
return true;
}
bool cwmwsrouter2obj::readvialist(wmxmlelement *plistelem, list& listvialist)
{
// components of qname
wstring wstrchildelemname(l"via");
wstring wstrchildelemns(g_pwszheaderns);
// clear list
listvialist.clear();
// iterate over elements in list
childelementslist::iterator il;
for (il = plistelem->getchildelements().begin();
il != plistelem->getchildelements().end();
il++)
{
if(*il != null && (*il)->getlocalname() == wstrchildelemname && (*il)->geturi() == wstrchildelemns)
{
// add to list
listvialist.push_back((*il)->getcontent());
}
}
return true;
}
bool cwmwsrouter2obj::readfoundlist(wmxmlelement *plistelem, list& listfoundlist)
{
// components of qname
wstring wstrchildelemname(l"at");
wstring wstrchildelemns(l"");
// iterate over elements in list
childelementslist::iterator il;
for (il = plistelem->getchildelements().begin();
il != plistelem->getchildelements().end();
il++)
{
if(*il != null && (*il)->getlocalname() == wstrchildelemname && (*il)->geturi() == wstrchildelemns)
{
// add to list
listfoundlist.push_back((*il)->getcontent());
}
}
return true;
}
bool cwmwsrouter2obj::readheader(iwmsoapmsg2 *piwmsoapmsg)
{
bstr bstrnamespaceuri = sysallocstring(g_pwszheaderns);
bstr bstrlocalname = sysallocstring(l"path");
bstr bstrxml;
wstring wstrxml;
variant_bool bresult;
hresult hres = piwmsoapmsg->getheaderelemliteral(bstrnamespaceuri, bstrlocalname, &bstrxml, &bresult);
sysfreestring(bstrlocalname);
sysfreestring(bstrnamespaceuri);
if (hres != s_ok || bresult == variant_false)
{
return false;
}
wstrxml = bstrxml;
sysfreestring(bstrxml);
// set up for parsing
wmxmlparser parser;
parser.setbuildtree(true);
bool brtn = true;
// parse the xml fragment representing the header entry
try
{
parser.parsexml_widestring(wstrxml, null);
}
catch(int e)
{
int x = e;
return false;
}
// get the wmxmlelement pointer representing root node of parse tree
wmxmlelement *proot = parser.detachdocroot();
if (proot == null)
{
return false;
}
// reset flags
m_bactionelemfound = false;
m_btoelemfound = false;
m_bfwdelemfound = false;
m_brevelemfound = false;
m_bfromelemfound = false;
m_bidelemfound = false;
m_brelatestoelemfound = false;
m_bfaultelemfound = false;
// get 'action' element
wmxmlelement *pchild = proot->getchildelement(wstring(g_pwszheaderns), wstring(l"action"));
if (pchild != null)
{
m_wstraction = pchild->getcontent();
m_bactionelemfound = true;
}
// get 'to' element
pchild = proot->getchildelement(wstring(g_pwszheaderns), wstring(l"to"));
if (pchild != null)
{
m_wstrto = pchild->getcontent();
m_btoelemfound = true;
}
// get 'fwd' element
pchild = proot->getchildelement(wstring(g_pwszheaderns), wstring(l"fwd"));
if (pchild != null)
{
readvialist(pchild, m_listfwd);
m_bfwdelemfound = true;
}
// get 'rev' element
pchild = proot->getchildelement(wstring(g_pwszheaderns), wstring(l"rev"));
if (pchild != null)
{
readvialist(pchild, m_listrev);
m_brevelemfound = true;
}
// get 'from' element
pchild = proot->getchildelement(wstring(g_pwszheaderns), wstring(l"from"));
if (pchild != null)
{
m_wstrfrom = pchild->getcontent();
m_bfromelemfound = true;
}
// get 'id' element
pchild = proot->getchildelement(wstring(g_pwszheaderns), wstring(l"id"));
if (pchild != null)
{
m_wstrid = pchild->getcontent();
m_bidelemfound = true;
}
// get 'relatesto' element
pchild = proot->getchildelement(wstring(g_pwszheaderns), wstring(l"relatesto"));
if (pchild != null)
{
m_wstrrelatesto = pchild->getcontent();
m_brelatestoelemfound = true;
}
// capture 'fault' element contents
pchild = proot->getchildelement(wstring(g_pwszheaderns), wstring(l"fault"));
if (pchild != null)
{
readfault(pchild);
m_bfaultelemfound = true;
}
delete proot;
return true;
}
bool cwmwsrouter2obj::processfault(int ncode, iwmsoapmsg2 *piwmsoapmsg)
{
// initialize flags
m_bneedendpoint = false;
m_bneedfound = false;
m_bneedmaxsize = false;
m_bneedmaxtime = false;
m_bneedretryafter = false;
// determine soap version
long lsoapversion;
piwmsoapmsg->getsoapversion(&lsoapversion);
switch(ncode)
{
case 700:
{
// invalid soap-rp header
m_wstrfaultcode = l"700";
m_wstrfaultreason = l"invalid ws-routing header";
}
break;
case 701:
{
// soap-rp header required
m_wstrfaultcode = l"701";
m_wstrfaultreason = l"ws-routing header required";
}
break;
case 710:
{
// endpoint not found
m_wstrfaultcode = l"710";
m_wstrfaultreason = l"endpoint not found";
m_wstrendpoint = m_wstruri;
m_bneedendpoint = true;
}
break;
case 712:
{
// endpoint not supported
m_wstrfaultcode = l"712";
m_wstrfaultreason = l"endpoint not supported";
m_wstrendpoint = m_wstruri;
m_bneedendpoint = true;
}
}
break;
case 800:
{
// unknown soap-rp fault
m_wstrfaultcode = l"800";
m_wstrfaultreason = l"unknown ws-routing fault";
}
break;
case 810:
{
// element not implemented
m_wstrfaultcode = l"810";
m_wstrfaultreason = l"element not implemented";
}
break;
case 811:
{
// service unavailable
m_wstrfaultcode = l"811";
m_wstrfaultreason = l"service unavailable";
m_wstrfaultreason = l"service unavailable";
}
break;
case 812:
{
// service too busy
m_wstrfaultcode = l"812";
m_wstrfaultreason = l"service too busy";
}
break;
case 820:
{
// endpoint not reachable
m_wstrfaultcode = l"820";
m_wstrfaultreason = l"endpoint not reachable";
m_wstrendpoint = m_wstruri;
m_bneedendpoint = true;
}
break;
default:
{
// should never happen
m_wstrfaultcode = l"000";
m_wstrfaultreason = l"invalid fault code";
m_wstrendpoint = m_wstruri;
m_bneedendpoint = true;
}
}
// create new header entry
wmxmlelement *ppath = new wmxmlelement(wstring(l"rp:path"));
if (ppath != null)
{
ppath->setnsprefix(wstring(l"rp"), wstring(g_pwszheaderns));
if (lsoapversion == soap_version_1_1)
{
ppath->setnsprefix(wstring(l"soap-env"), wstring(g_pwszsoapenvelopens));
ppath->setattribute(wstring(l"soap-env:actor"), wstring(g_pwszsoapactornext));
ppath->setattribute(wstring(l"soap-env:mustunderstand"), wstring(l"1"));
}
else
{
ppath->setnsprefix(wstring(l"soap-env"), wstring(g_pwszsoap12envelopens));
ppath->setattribute(wstring(l"soap-env:role"), wstring(g_pwszsoap12rolenext));
ppath->setattribute(wstring(l"soap-env:mustunderstand"), wstring(l"true"));
}
}
else
{
return false;
}
// 'action' element
wmxmlelement *pchild = new wmxmlelement(wstring(l"rp:action"));
if (pchild != null)
{
ppath->addchildelement(pchild);
pchild->appendcontent(wstring(l"http://schemas.xmlsoap.org/soap/fault"));
}
else
{
delete ppath;
return false;
}
// 'fwd' element (derived from 'rev' path received)
pchild = new wmxmlelement(wstring(l"rp:fwd"));
if (pchild != null)
{
ppath->addchildelement(pchild);
if (m_brevelemfound == true)
{
// use contents of "rev" element received
populatevialist(m_listrev, pchild);
}
}
else
{
delete ppath;
return false;
}
// 'from' element (only from endpoint)
if (m_bintermediary == false)
{
pchild = new wmxmlelement(wstring(l"rp:from"));
if (pchild != null)
{
ppath->addchildelement(pchild);
pchild->appendcontent(getfromuri());
}
else
{
delete ppath;
return false;
}
}
// 'id' element
pchild = new wmxmlelement(wstring(l"rp:id"));
if (pchild != null)
{
ppath->addchildelement(pchild);
pchild->appendcontent(generateid());
}
else
{
delete ppath;
return false;
}
// 'relatesto' element (value is id of request message)
pchild = new wmxmlelement(wstring(l"rp:relatesto"));
if (pchild != null)
{
ppath->addchildelement(pchild);
pchild->appendcontent(m_wstrid);
}
else
{
delete ppath;
return false;
}
// 'fault' element
pchild = createfaultelem();
if (pchild != null)
{
ppath->addchildelement(pchild);
}
else
{
delete ppath;
return false;
}
// now serialize
wstring wstrbuffer;
ppath->serialize(null, wstrbuffer);
delete ppath;
bstr bstrbuffer = sysallocstring(wstrbuffer.c_str());
bstr bstrnamespaceuri = sysallocstring(g_pwszheaderns);
bstr bstrlocalname = sysallocstring(l"path");
variant_bool bmustunderstand = variant_true;
// determine actor uri
bstr bstractoruri = null;
if (lsoapversion == soap_version_1_1)
{
bstractoruri = sysallocstring(g_pwszsoapactornext);
}
else
{
bstractoruri = sysallocstring(g_pwszsoap12rolenext);
}
bstr bstrencodingstyle = sysallocstring(l"");
variant_bool bresult;
piwmsoapmsg->addfaultheaderelemliteral( bstrnamespaceuri,
bstrlocalname,
bstrbuffer,
bmustunderstand,
bstractoruri,
bstrencodingstyle,
&bresult);
sysfreestring(bstrnamespaceuri);
sysfreestring(bstrlocalname);
sysfreestring(bstractoruri);
sysfreestring(bstrencodingstyle);
sysfreestring(bstrbuffer);
// generate soap fault
bstr bstrfaultcode, bstrfaultcodens, bstrfaultstring;
if (lsoapversion == soap_version_1_1)
{
if (ncode < 800)
{
bstrfaultcode = sysallocstring(l"client");
bstrfaultstring = sysallocstring(l"ws-routing sender fault.");
}
else
{
bstrfaultcode = sysallocstring(l"server");
bstrfaultstring = sysallocstring(l"ws-routing receiver fault.");
}
bstrfaultcodens = sysallocstring(g_pwszsoapenvelopens);
piwmsoapmsg->setsoapfault(bstrfaultcode, bstrfaultcodens, bstrfaultstring, variant_false, &bresult);
}
else
{
if (ncode < 800)
{
bstrfaultcode = sysallocstring(l"sender");
bstrfaultstring = sysallocstring(l"ws-routing sender fault.");
}
else
{
bstrfaultcode = sysallocstring(l"receiver");
bstrfaultstring = sysallocstring(l"ws-routing receiver fault.");
}
bstrfaultcodens = sysallocstring(g_pwszsoap12envelopens);
bstr bstrsubcode = sysallocstring(l"");
bstr bstrsubcodens = sysallocstring(l"");
bstr bstrlangid = sysallocstring(l"en");
piwmsoapmsg->setsoap12fault(bstrfaultcode, bstrfaultcodens, bstrsubcode, bstrsubcodens, bstrfaultstring, bstrlangid, &bresult);
sysfreestring(bstrsubcode);
sysfreestring(bstrsubcodens);
sysfreestring(bstrlangid);
}
sysfreestring(bstrfaultcode);
sysfreestring(bstrfaultcodens);
sysfreestring(bstrfaultstring);
// set flag to disable response processing
m_brequestfault = true;
return (bresult == variant_true);
}
bool cwmwsrouter2obj::processreqasintermediary(iwmsoapmsg2 *piwmsoapmsg)
{
// determine next hop
if (m_listfwd.empty() == true)
{
// we were the last intermediary
m_wstruri = m_wstrto;
}
else
{
m_wstruri = m_listfwd.front();
}
// is this url scheme supported?
if (checkurlscheme(m_wstruri) == false)
{
processfault(712, piwmsoapmsg);
return true;
}
// set next hop
bstr bstrtemp = sysallocstring(m_wstruri.c_str());
piwmsoapmsg->setnexthopurl(bstrtemp);
sysfreestring(bstrtemp);
// determine soap version
long lsoapversion;
piwmsoapmsg->getsoapversion(&lsoapversion);
// create new header entry
wmxmlelement *ppath = new wmxmlelement(wstring(l"rp:path"));
if (ppath != null)
{
ppath->setnsprefix(wstring(l"rp"), wstring(g_pwszheaderns));
if (lsoapversion == soap_version_1_1)
{
ppath->setnsprefix(wstring(l"soap-env"), wstring(g_pwszsoapenvelopens));
ppath->setattribute(wstring(l"soap-env:actor"), wstring(g_pwszsoapactornext));
ppath->setattribute(wstring(l"soap-env:mustunderstand"), wstring(l"1"));
}
else
{
ppath->setnsprefix(wstring(l"soap-env"), wstring(g_pwszsoap12envelopens));
ppath->setattribute(wstring(l"soap-env:role"), wstring(g_pwszsoap12rolenext));
ppath->setattribute(wstring(l"soap-env:mustunderstand"), wstring(l"true"));
}
}
else
{
return false;
}
// 'action' element
wmxmlelement *pchild = new wmxmlelement(wstring(l"rp:action"));
if (pchild != null)
{
ppath->addchildelement(pchild);
pchild->appendcontent(m_wstraction);
}
else
{
delete ppath;
return false;
}
// 'to' element
if (m_btoelemfound == true)
{
pchild = new wmxmlelement(wstring(l"rp:to"));
if (pchild != null)
{
ppath->addchildelement(pchild);
pchild->appendcontent(m_wstrto);
}
else
{
delete ppath;
return false;
}
}
// 'fwd' element
if (m_bfwdelemfound == true)
{
// we have already removed the top "via" element
pchild = new wmxmlelement(wstring(l"rp:fwd"));
if (pchild != null)
{
ppath->addchildelement(pchild);
populatevialist(m_listfwd, pchild);
}
else
{
delete ppath;
return false;
}
}
// 'rev' element
if (m_brevelemfound == true)
{
// add empty "via" element to top of list
m_listrev.push_front(wstring(l""));
pchild = new wmxmlelement(wstring(l"rp:rev"));
if (pchild != null)
{
ppath->addchildelement(pchild);
populatevialist(m_listrev, pchild);
}
else
{
delete ppath;
return false;
}
}
// 'from' element
if (m_bfromelemfound == true)
{
pchild = new wmxmlelement(wstring(l"rp:from"));
if (pchild != null)
{
ppath->addchildelement(pchild);
pchild->appendcontent(m_wstrfrom);
}
else
{
delete ppath;
return false;
}
}
// 'id' element
if (m_bidelemfound == true)
{
pchild = new wmxmlelement(wstring(l"rp:id"));
if (pchild != null)
{
ppath->addchildelement(pchild);
pchild->appendcontent(m_wstrid);
}
else
{
delete ppath;
return false;
}
}
// 'relatesto' element
if (m_brelatestoelemfound == true)
{
pchild = new wmxmlelement(wstring(l"rp:relatesto"));
if (pchild != null)
{
ppath->addchildelement(pchild);
pchild->appendcontent(m_wstrrelatesto);
}
else
{
delete ppath;
return false;
}
}
// 'fault' element
if (m_bfaultelemfound == true)
{
pchild = createfaultelem();
if (pchild != null)
{
ppath->addchildelement(pchild);
}
else
{
delete ppath;
return false;
}
}
// now serialize
wstring wstrbuffer;
ppath->serialize(null, wstrbuffer);
delete ppath;
bstr bstrbuffer = sysallocstring(wstrbuffer.c_str());
bstr bstrnamespaceuri = sysallocstring(g_pwszheaderns);
bstr bstrlocalname = sysallocstring(l"path");
variant_bool bmustunderstand = variant_true;
// determine actor uri
bstr bstractoruri = null;
if (lsoapversion == soap_version_1_1)
{
bstractoruri = sysallocstring(g_pwszsoapactornext);
}
else
{
bstractoruri = sysallocstring(g_pwszsoap12rolenext);
}
bstr bstrencodingstyle = sysallocstring(l"");
variant_bool bresult;
piwmsoapmsg->addheaderelemliteral( bstrnamespaceuri,
bstrlocalname,
bstrbuffer,
bmustunderstand,
bstractoruri,
bstrencodingstyle,
&bresult);
sysfreestring(bstrnamespaceuri);
sysfreestring(bstrlocalname);
sysfreestring(bstractoruri);
sysfreestring(bstrencodingstyle);
sysfreestring(bstrbuffer);
return (bresult == variant_true);
}
bool cwmwsrouter2obj::processreqasendpoint(iwmsoapmsg2 *piwmsoapmsg)
{
return true;
}
bool cwmwsrouter2obj::processrespasintermediary(iwmsoapmsg2 *piwmsoapmsg)
{
// determine soap version
long lsoapversion;
piwmsoapmsg->getsoapversion(&lsoapversion);
// create new header entry
wmxmlelement *ppath = new wmxmlelement(wstring(l"rp:path"));
if (ppath != null)
{
ppath->setnsprefix(wstring(l"rp"), wstring(g_pwszheaderns));
if (lsoapversion == soap_version_1_1)
{
ppath->setnsprefix(wstring(l"soap-env"), wstring(g_pwszsoapenvelopens));
ppath->setattribute(wstring(l"soap-env:actor"), wstring(g_pwszsoapactornext));
ppath->setattribute(wstring(l"soap-env:mustunderstand"), wstring(l"1"));
}
else
{
ppath->setnsprefix(wstring(l"soap-env"), wstring(g_pwszsoap12envelopens));
ppath->setattribute(wstring(l"soap-env:role"), wstring(g_pwszsoap12rolenext));
ppath->setattribute(wstring(l"soap-env:mustunderstand"), wstring(l"true"));
}
}
else
{
return false;
}
// 'action' element
wmxmlelement *pchild = new wmxmlelement(wstring(l"rp:action"));
if (pchild != null)
{
ppath->addchildelement(pchild);
pchild->appendcontent(m_wstraction);
}
else
{
delete ppath;
return false;
}
// 'fwd' element
if (m_bfwdelemfound == true)
{
// we have already removed the top "via" element
pchild = new wmxmlelement(wstring(l"rp:fwd"));
if (pchild != null)
{
ppath->addchildelement(pchild);
populatevialist(m_listfwd, pchild);
}
else
{
delete ppath;
return false;
}
}
// 'rev' element
if (m_brevelemfound == true)
{
// add cached uri indentifying us to top of list
m_listrev.push_front(m_wstrintermediaryuri);
pchild = new wmxmlelement(wstring(l"rp:rev"));
if (pchild != null)
{
ppath->addchildelement(pchild);
populatevialist(m_listrev, pchild);
}
else
{
delete ppath;
return false;
}
}
// 'from' element
if (m_bfromelemfound == true)
{
pchild = new wmxmlelement(wstring(l"rp:from"));
if (pchild != null)
{
ppath->addchildelement(pchild);
pchild->appendcontent(m_wstrfrom);
}
else
{
delete ppath;
return false;
}
}
// 'id' element
if (m_bidelemfound == true)
{
pchild = new wmxmlelement(wstring(l"rp:id"));
if (pchild != null)
{
ppath->addchildelement(pchild);
pchild->appendcontent(m_wstrid);
}
else
{
delete ppath;
return false;
}
}
// 'relatesto' element
if (m_brelatestoelemfound == true)
{
pchild = new wmxmlelement(wstring(l"rp:relatesto"));
if (pchild != null)
{
ppath->addchildelement(pchild);
pchild->appendcontent(m_wstrrelatesto);
}
else
{
delete ppath;
return false;
}
}
// 'fault' element
if (m_bfaultelemfound == true)
{
pchild = createfaultelem();
if (pchild != null)
{
ppath->addchildelement(pchild);
}
else
{
delete ppath;
return false;
}
}
// now serialize
wstring wstrbuffer;
ppath->serialize(null, wstrbuffer);
delete ppath;
bstr bstrbuffer = sysallocstring(wstrbuffer.c_str());
bstr bstrnamespaceuri = sysallocstring(g_pwszheaderns);
bstr bstrlocalname = sysallocstring(l"path");
variant_bool bmustunderstand = variant_true;
// determine actor uri
bstr bstractoruri = null;
if (lsoapversion == soap_version_1_1)
{
bstractoruri = sysallocstring(g_pwszsoapactornext);
}
else
{
bstractoruri = sysallocstring(g_pwszsoap12rolenext);
}
bstr bstrencodingstyle = sysallocstring(l"");
variant_bool bresult;
// was this a fault response?
piwmsoapmsg->issoapfault(&bresult);
if (bresult == variant_true)
{
piwmsoapmsg->addfaultheaderelemliteral( bstrnamespaceuri,
bstrlocalname,
bstrbuffer,
bmustunderstand,
bstractoruri,
bstrencodingstyle,
&bresult);
}
else
{
piwmsoapmsg->addheaderelemliteral( bstrnamespaceuri,
bstrlocalname,
bstrbuffer,
bmustunderstand,
bstractoruri,
bstrencodingstyle,
&bresult);
}
sysfreestring(bstrnamespaceuri);
sysfreestring(bstrlocalname);
sysfreestring(bstractoruri);
sysfreestring(bstrencodingstyle);
sysfreestring(bstrbuffer);
return (bresult == variant_true);
}
bool cwmwsrouter2obj::processrespasendpoint(iwmsoapmsg2 *piwmsoapmsg)
{
// determine soap version
long lsoapversion;
piwmsoapmsg->getsoapversion(&lsoapversion);
// create new header entry
wmxmlelement *ppath = new wmxmlelement(wstring(l"rp:path"));
if (ppath != null)
{
ppath->setnsprefix(wstring(l"rp"), wstring(g_pwszheaderns));
if (lsoapversion == soap_version_1_1)
{
ppath->setnsprefix(wstring(l"soap-env"), wstring(g_pwszsoapenvelopens));
ppath->setattribute(wstring(l"soap-env:actor"), wstring(g_pwszsoapactornext));
ppath->setattribute(wstring(l"soap-env:mustunderstand"), wstring(l"1"));
}
else
{
ppath->setnsprefix(wstring(l"soap-env"), wstring(g_pwszsoap12envelopens));
ppath->setattribute(wstring(l"soap-env:role"), wstring(g_pwszsoap12rolenext));
ppath->setattribute(wstring(l"soap-env:mustunderstand"), wstring(l"true"));
}
}
else
{
return false;
}
// 'action' element
wmxmlelement *pchild = new wmxmlelement(wstring(l"rp:action"));
if (pchild != null)
{
ppath->addchildelement(pchild);
pchild->appendcontent(m_wstraction);
}
else
{
delete ppath;
return false;
}
// 'fwd' element
if (m_brevelemfound == true)
{
// use contents of "rev" element received
pchild = new wmxmlelement(wstring(l"rp:fwd"));
if (pchild != null)
{
ppath->addchildelement(pchild);
populatevialist(m_listrev, pchild);
}
else
{
delete ppath;
return false;
}
}
// 'rev' element
// we need to insert "via" element with our uri
if (m_btoelemfound == true)
{
// use the "to" value received
m_listfwd.push_front(m_wstrto);
}
else
{
// use the value of the "via" element found in "fwd"
m_listfwd.push_front(m_wstruri);
}
pchild = new wmxmlelement(wstring(l"rp:rev"));
if (pchild != null)
{
ppath->addchildelement(pchild);
populatevialist(m_listfwd, pchild);
}
else
{
delete ppath;
return false;
}
// 'from' element
pchild = new wmxmlelement(wstring(l"rp:from"));
if (pchild != null)
{
ppath->addchildelement(pchild);
pchild->appendcontent(getfromuri());
}
else
{
delete ppath;
return false;
}
// 'id' element
pchild = new wmxmlelement(wstring(l"rp:id"));
if (pchild != null)
{
ppath->addchildelement(pchild);
pchild->appendcontent(generateid());
}
else
{
delete ppath;
return false;
}
// 'relatesto' element (value is id of request message)
pchild = new wmxmlelement(wstring(l"rp:relatesto"));
if (pchild != null)
{
ppath->addchildelement(pchild);
pchild->appendcontent(m_wstrid);
}
else
{
delete ppath;
return false;
}
// 'fault' element
if (m_bfaultelemfound == true)
{
pchild = createfaultelem();
if (pchild != null)
{
ppath->addchildelement(pchild);
}
else
{
delete ppath;
return false;
}
}
// now serialize
wstring wstrbuffer;
ppath->serialize(null, wstrbuffer);
delete ppath;
bstr bstrbuffer = sysallocstring(wstrbuffer.c_str());
bstr bstrnamespaceuri = sysallocstring(g_pwszheaderns);
bstr bstrlocalname = sysallocstring(l"path");
variant_bool bmustunderstand = variant_true;
// determine actor uri
bstr bstractoruri = null;
if (lsoapversion == soap_version_1_1)
{
bstractoruri = sysallocstring(g_pwszsoapactornext);
}
else
{
bstractoruri = sysallocstring(g_pwszsoap12rolenext);
}
bstr bstrencodingstyle = sysallocstring(l"");
variant_bool bresult;
// was this a fault response?
piwmsoapmsg->issoapfault(&bresult);
if (bresult == variant_true)
{
piwmsoapmsg->addfaultheaderelemliteral( bstrnamespaceuri,
bstrlocalname,
bstrbuffer,
bmustunderstand,
bstractoruri,
bstrencodingstyle,
&bresult);
}
else
{
piwmsoapmsg->addheaderelemliteral( bstrnamespaceuri,
bstrlocalname,
bstrbuffer,
bmustunderstand,
bstractoruri,
bstrencodingstyle,
&bresult);
}
sysfreestring(bstrnamespaceuri);
sysfreestring(bstrlocalname);
sysfreestring(bstractoruri);
sysfreestring(bstrencodingstyle);
sysfreestring(bstrbuffer);
return (bresult == variant_true);
}
bool cwmwsrouter2obj::processrequest(iwmsoapmsg2 *piwmsoapmsg)
{
m_brequestfault = false;
m_bintermediary = true;
m_bnoreversepath = false;
if (readheader(piwmsoapmsg) == false)
{
// missing soap-rp header
processfault(701, piwmsoapmsg);
return true;
}
// is this a fault message?
if (m_bfaultelemfound == true || m_wstraction == l"http://schemas.xmlsoap.org/soap/fault")
{
// send "no content" response
piwmsoapmsg->setnocontentresponse(variant_true);
// set flag to abort processing
m_babortprocessing = true;
return true;
}
// was a reverse path specified?
if (m_brevelemfound == false)
{
// no, set flag, normal processing will proceed
m_bnoreversepath = true;;
}
// were "id" and "action" elements found?
if (m_bidelemfound == false || m_bactionelemfound == false)
{
{
// ill formed header... should have "id" and "action" elements
processfault(700, piwmsoapmsg);
return true;
}
}
// was a "fwd" element with entries(s) found?
if (m_bfwdelemfound == false || m_listfwd.empty() == true)
{
// no, so check for "to" element
if (m_btoelemfound == false)
{
// ill formed header... should have "to" element
processfault(700, piwmsoapmsg);
return true;
}
// "to" element found... we are the endpoint
m_bintermediary = false;
// check the uri to make sure it's us
if (checkidentity(m_wstrto, piwmsoapmsg) == false)
{
// not us... "invalid ws-routing header" fault
processfault(700, piwmsoapmsg);
return true;
}
// it's us, so process as endpoint
m_wstruri = m_wstrto;
if (processreqasendpoint(piwmsoapmsg) == false)
{
processfault(800, piwmsoapmsg);
}
return true;
}
else
{
// non-empty "fwd" element... get top element
m_wstruri = m_listfwd.front();
m_listfwd.pop_front();
// is it us?
if (checkidentity(m_wstruri, piwmsoapmsg) == false)
{
// not us... send invalid ws-routing header fault
processfault(700, piwmsoapmsg);
return true;
}
// was this the last one and no "to" element is present?
if (m_listfwd.empty() == true && m_btoelemfound == false)
{
// we are the endpoint, so process as such
m_bintermediary = false;
if (processreqasendpoint(piwmsoapmsg) == false)
{
processfault(800, piwmsoapmsg);
}
return true;
}
// we are an intermediary... process as such
m_wstrintermediaryuri = m_wstruri;
return processreqasintermediary(piwmsoapmsg);
}
return true;
}
bool cwmwsrouter2obj::processresponse(iwmsoapmsg2 *piwmsoapmsg)
{
// was a reverse path found in request?
if (m_bnoreversepath == true)
{
// send "no content" response and quit
piwmsoapmsg->setnocontentresponse(variant_true);
return true;
}
// was a fault generated in request phase?
if (m_brequestfault == true)
{
// do nothing
return true;
}
variant_bool bresult;
piwmsoapmsg->isintermediary(&bresult);
if (bresult == variant_false)
{
// we are endpoint, process as such
if (processrespasendpoint(piwmsoapmsg) == false)
{
processfault(800, piwmsoapmsg);
}
// will we be using implicit reverse path?
wstring wstrfirstrevurl = m_listrev.front();
if (wstrfirstrevurl.empty() == true || checkurlscheme(wstrfirstrevurl) == false)
{
// use implicit path
return true;
}
// no, an explicit reverse path
return forwardmsghttp(wstrfirstrevurl, piwmsoapmsg);
}
// we are intermediary... look for ws-routing header in response
if (readheader(piwmsoapmsg) == false)
{
// did attempt to forward message fail?
piwmsoapmsg->issoapfault(&bresult);
if (bresult == variant_true)
{
bstr bstrfaultstring;
piwmsoapmsg->getsoapfaultstring(&bstrfaultstring);
if (wcscmp(l"attempt to forward soap message by intermediary failed.", bstrfaultstring) == 0)
{
sysfreestring(bstrfaultstring);
// was a "rev" element with entries(s) found?
if (m_brevelemfound == true && m_listrev.empty() == false)
{
// non-empty "rev" element... remove top element added in request phase
m_listrev.pop_front();
}
processfault(820, piwmsoapmsg);
return true;
}
sysfreestring(bstrfaultstring);
}
// no forwarding failure, no soap-rp header found... do nothing.
return true;
}
// were "id" and "action" elements found?
if (m_bidelemfound == false || m_bactionelemfound == false)
{
{
// ill formed header... should have "id" and "action" elements
processfault(700, piwmsoapmsg);
return true;
}
}
// was a "fwd" element with entries(s) found?
if (m_bfwdelemfound == true && m_listfwd.empty() == false)
{
// non-empty "fwd" element... get top element
m_wstruri = m_listfwd.front();
m_listfwd.pop_front();
// is it us (an empty "via" element means it's for us)?
if (m_wstruri.empty() == false)
{
// not us... send invalid header fault
processfault(700, piwmsoapmsg);
return true;
}
}
// now process as intermediary
return processrespasintermediary(piwmsoapmsg);
}
stdmethodimp cwmwsrouter2obj::onprocessheader(variant soapmsginterface, variant_bool *presult)
{
// set up, assume success
m_babortprocessing = false;
*presult = variant_true;
// get interface ptr
idispatch *pidispatch = soapmsginterface.pdispval;
iwmsoapmsg2 *piwmsoapmsg;
hresult hres = pidispatch->queryinterface(iid_iwmsoapmsg2, (void **)&piwmsoapmsg);
if (hres != s_ok)
{
return e_fail;
}
variant_bool bresult;
piwmsoapmsg->isrequestphase(&bresult);
if (bresult == variant_true)
{
// this is request phase
if (processrequest(piwmsoapmsg) == false)
{
processfault(800, piwmsoapmsg);
}
piwmsoapmsg->release();
// abort processing?
if (m_babortprocessing == true)
{
// set out parameter to signal abort
*presult = variant_false;
}
return s_ok;
}
// response phase
if (processresponse(piwmsoapmsg) == false)
{
processfault(800, piwmsoapmsg);
}
piwmsoapmsg->release();
if (m_babortprocessing == true)
{
// set out parameter to signal abort
*presult = variant_false;
}
return s_ok;
}
bool cwmwsrouter2obj::forwardmsghttp(const wstring& wstrurl, iwmsoapmsg2 *piwmsoapmsg)
{
// toggle to 'response' phase
piwmsoapmsg->setrequestphase(variant_false);
variant_bool bresult;
// must forward request, so re-serialize request message
piwmsoapmsg->serialize(&bresult);
if (bresult == variant_false)
{
// failed
return false;
}
// set up http client
string strnexthopurl, strhost, strsvcuri, strtemp;
uses_conversion;
strnexthopurl = ole2a(wstrurl.c_str());
int nportnbr = 80;
string::size_type pos;
if ((pos = strnexthopurl.find("http://")) != string::npos)
{
strtemp = strnexthopurl.substr(pos + 7);
pos = strtemp.find('/');
if (pos == string::npos)
{
strsvcuri = "/";
}
else
{
strsvcuri = strtemp.substr(pos);
}
strtemp = strtemp.substr(0, pos);
if ((pos = strtemp.find(':')) != string::npos)
{
// port specified explicitly
nportnbr = atoi(strtemp.substr(pos + 1).c_str());
strhost = strtemp.substr(0, pos);
}
else
{
strhost = strtemp;
}
}
// get serialized message
_variant_t varbuffer;
piwmsoapmsg->getbuffer(&varbuffer, &bresult);
safearray *parray = varbuffer.parray;
void *pdata;
if ( bresult == variant_false ||
!(varbuffer.vt & (vt_array | vt_ui1)) ||
parray == null ||
safearraygetdim(parray) != 1 ||
failed(safearrayaccessdata(parray, &pdata)))
{
return false;
}
// get soap version
long lsoapversion;
piwmsoapmsg->getsoapversion(&lsoapversion);
dimeparser dimeparser;
string strbody;
long lnumattachments = 0;
piwmsoapmsg->getnumrespattachments(&lnumattachments);
unsigned long ulmsglength;
if (lnumattachments > 0)
{
// try to initialize parser for serialization
// accept default record size of 4096 octets
try
{
dimeparser.serializeinit();
}
catch (dimeparserexception *e)
{
delete e;
safearrayunaccessdata(parray);
return false;
}
string strtypeuri;
if (lsoapversion == soap_version_1_1)
{
strtypeuri = g_pszsoapenvelopens;
}
else
{
strtypeuri = g_pszsoap12envelopens;
}
// add primary dime payload
if (dimeparser.addpayload( (const char *)pdata,
parray->rgsabound[0].celements,
string(""),
strtypeuri,
dime_typename_format_uri) == false)
{
safearrayunaccessdata(parray);
return false;
}
safearrayunaccessdata(parray);
// now get secondary payloads
long lposition;
bstr bstrid, bstrtype;
long ltnf;
iunknown *piunknown;
_variant_t varoptions;
for (piwmsoapmsg->getfirstdimeattachmentresp(&bstrid,
&bstrtype,
<nf,
&piunknown,
&varoptions,
&lposition,
&bresult);
bresult == variant_true;
piwmsoapmsg->getnextdimeattachmentresp( &bstrid,
&bstrtype,
<nf,
&piunknown,
&varoptions,
&lposition,
&bresult)
)
{
string strid, strtype;
widestringtoutf8(wstring(bstrid), strid);
widestringtoutf8(wstring(bstrtype), strtype);
sysfreestring(bstrid);
sysfreestring(bstrtype);
istorage *pistorage;
hresult res = piunknown->queryinterface(iid_istorage, (void **)&pistorage);
if (failed(res))
{
return false;
}
safearray *parray = null;
if ((varoptions.vt & vt_typemask) & (vt_array | vt_ui1))
{
parray = varoptions.parray;
}
if (dimeparser.addpayload( pistorage,
strid,
strtype,
ltnf,
parray) == false)
{
// this will result in 500 "internal server error"
pistorage->release();
return false;
}
varoptions.clear();
pistorage->release();
}
ulmsglength = dimeparser.calcseriallength();
}
else
{
// no attachments, send without dime packaging
strbody.append((char *)pdata, parray->rgsabound[0].celements);
ulmsglength = parray->rgsabound[0].celements;
safearrayunaccessdata(parray);
}
// build http header
char szbuffer[128];
string strheaders = "host: ";
strheaders += strhost;
sprintf(szbuffer, ":%d\r\n", nportnbr);
strheaders += szbuffer;
strheaders += "user-agent: ";
strheaders += string(g_pszuseragent);
if (lnumattachments > 0)
{
strheaders += "\r\ncontent-type: application/dime\r\n";
}
else
{
if (lsoapversion == soap_version_1_1)
{
strheaders += "\r\ncontent-type: text/xml; charset=\"utf-8\"\r\n";
}
else
{
strheaders += "\r\ncontent-type: application/soap+xml; charset=\"utf-8\"\r\n";
}
}
sprintf(szbuffer, "content-length: %d\r\n", ulmsglength);
strheaders += szbuffer;
// now send message
wmdimerequestsock httpclient;
bool bsuccess;
if (lnumattachments > 0)
{
bsuccess = httpclient.sendhttprequest(nportnbr,
string("post"),
strhost,
strsvcuri,
string(""),
strheaders,
&dimeparser);
}
else
{
bsuccess = httpclient.sendhttprequest(nportnbr,
string("post"),
strhost,
strsvcuri,
string(""),
strheaders,
strbody,
&dimeparser);
}
if (bsuccess == false || httpclient.getstatus() >= 300)
{
// something went wrong
return false;
}
// set "no content" response
piwmsoapmsg->setnocontentresponse(variant_true);
return true;
}
stdmethodimp cwmwsrouter2obj::ontestmuheaderblock(bstr bstrnamespace, bstr bstrlocalname, variant_bool *presult)
{
*presult = variant_false;
if (wcscmp(bstrnamespace, g_pwszheaderns) == 0)
{
if (wcscmp(bstrlocalname, l"path") == 0)
{
*presult = variant_true;
return s_ok;
}
}
return s_ok;
}