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.
380 lines
10 KiB
380 lines
10 KiB
#include "pch.h"
|
|
#include "comptree.h"
|
|
#include "tagtab.h"
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
HRESULT TraverseXMLDoc( const CComPtr<IXMLElement>& spxmlElt ,
|
|
TagInformation* pTagTable ,
|
|
const CTagHandler* pthParent ,
|
|
CTagData& tdRoot );
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
// ((!pszTagName) || pszTagName == spxmlElt.parent.tagName) ? S_OK : S_FALSE
|
|
HRESULT TagNameMatchesParent( LPCWSTR pszTagName ,
|
|
const CComPtr<IXMLElement>& spxmlElt )
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
if(pszTagName != NULL)
|
|
{
|
|
CComPtr<IXMLElement> spParent;
|
|
|
|
hr = spxmlElt->get_parent( &spParent ); // S_FALSE if no parent
|
|
|
|
ASSERT((hr != S_FALSE) || (!spParent));
|
|
|
|
if(hr == S_OK)
|
|
{
|
|
CComBSTR bstrParentName;
|
|
|
|
if(SUCCEEDED(hr = spParent->get_tagName( &bstrParentName )))
|
|
{
|
|
hr = (_wcsicmp( bstrParentName, pszTagName )) ? S_FALSE : S_OK;
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
// looks up the tagName in pTagTable and calls the appropriate
|
|
// CreateInstance function to create pTagHndlr
|
|
HRESULT VisitElement( const CComPtr<IXMLElement>& spxmlElt ,
|
|
TagInformation * pTagTable ,
|
|
CTagHandler*& pTagHandler )
|
|
{
|
|
HRESULT hr;
|
|
CComBSTR bstrTagName;
|
|
|
|
pTagHandler = NULL;
|
|
|
|
if(SUCCEEDED(hr = spxmlElt->get_tagName( &bstrTagName )))
|
|
{
|
|
TagInformation* ptiElt;
|
|
|
|
for(ptiElt = pTagTable; ptiElt->pszTagName; ++ptiElt)
|
|
{
|
|
if(!_wcsicmp( ptiElt->pszTagName, bstrTagName ))
|
|
{
|
|
if(SUCCEEDED(hr = TagNameMatchesParent( ptiElt->pszParent, spxmlElt )))
|
|
{
|
|
if(hr == S_OK)
|
|
{
|
|
// call the CreateInstance function for the tag
|
|
pTagHandler = ptiElt->pfnTag();
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
// these are not the droids you're looking for
|
|
}
|
|
}
|
|
else
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else if(hr == E_NOTIMPL) // this is a node without tag information (comment)
|
|
{
|
|
hr = S_FALSE;
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
HRESULT GetChild( const CComVariant& varChild ,
|
|
const CComPtr<IXMLElementCollection>& spcol ,
|
|
CComPtr<IXMLElement>& spEltOut )
|
|
{
|
|
HRESULT hr;
|
|
CComPtr<IDispatch> spDisp;
|
|
CComVariant varEmpty;
|
|
|
|
|
|
hr = spcol->item( varChild, varEmpty, &spDisp );
|
|
if(hr == S_OK)
|
|
{
|
|
hr = spDisp.QueryInterface( &spEltOut );
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
// return (spcol.item(lChildID));
|
|
// gets an IXMLElement from an IXMLElementCollection
|
|
HRESULT GetChild( LONG lChildID ,
|
|
const CComPtr<IXMLElementCollection>& spcol ,
|
|
CComPtr<IXMLElement>& spEltOut )
|
|
{
|
|
CComVariant varItem( lChildID );
|
|
|
|
return GetChild( varItem, spcol, spEltOut );
|
|
}
|
|
|
|
// for (obj in spxmlElt.children)
|
|
// {
|
|
// phs = TraverseXMLDoc(obj);
|
|
// pthVisitor->AddChild(obj, phs);
|
|
// }
|
|
HRESULT VisitChildren( const CComPtr<IXMLElement>& spxmlElt ,
|
|
TagInformation* pTagTable ,
|
|
const CTagHandler* pthParent ,
|
|
CTagHandler* pthVisitor )
|
|
{
|
|
HRESULT hr;
|
|
CComPtr<IXMLElementCollection> spcolChildren;
|
|
|
|
if(SUCCEEDED(hr = spxmlElt->get_children( &spcolChildren )) && spcolChildren)
|
|
{
|
|
long lChildren;
|
|
|
|
if(SUCCEEDED(hr = spcolChildren->get_length( &lChildren )))
|
|
{
|
|
for(long l = 0; l < lChildren; ++l)
|
|
{
|
|
CComPtr<IXMLElement> spxmlChild;
|
|
|
|
if(SUCCEEDED(hr = GetChild( l, spcolChildren, spxmlChild )))
|
|
{
|
|
CTagData td;
|
|
|
|
hr = TraverseXMLDoc( spxmlChild, pTagTable, pthVisitor, td );
|
|
if(hr == S_OK)
|
|
{
|
|
hr = pthVisitor->AddChild( spxmlChild, td );
|
|
}
|
|
}
|
|
|
|
if(FAILED(hr)) break;
|
|
}
|
|
|
|
// convert return value from TraverseXMLDoc
|
|
if(hr == S_FALSE) hr = S_OK;
|
|
}
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
// return S_FALSE when no element found
|
|
HRESULT TraverseXMLDoc( const CComPtr<IXMLElement>& spxmlElt ,
|
|
TagInformation* pTagTable ,
|
|
const CTagHandler* pthParent , //TODO: Get rid of this parameter
|
|
CTagData& tdRoot )
|
|
{
|
|
HRESULT hr;
|
|
CTagHandler *pTagHandler;
|
|
|
|
if(SUCCEEDED(hr = VisitElement( spxmlElt, pTagTable, pTagHandler )))
|
|
{
|
|
// skip children we have no TagHandler for
|
|
if(pTagHandler)
|
|
{
|
|
if(SUCCEEDED(hr = pTagHandler->BeginChildren( spxmlElt )))
|
|
{
|
|
if(SUCCEEDED(hr = VisitChildren( spxmlElt, pTagTable, pthParent, pTagHandler )))
|
|
{
|
|
hr = pTagHandler->EndChildren( tdRoot );
|
|
|
|
if(SUCCEEDED(hr)) hr = S_OK;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
hr = S_FALSE;
|
|
}
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
unsigned int WriteBlobToFileHandle( LPCWSTR pszFileName, int fh, const void *pvBlob, DWORD dwSize )
|
|
{
|
|
unsigned int bytesWritten;
|
|
|
|
if ((bytesWritten = _write(fh, pvBlob, dwSize)) != -1)
|
|
{
|
|
if (bytesWritten == dwSize)
|
|
{
|
|
// S_OK!!!
|
|
}
|
|
else
|
|
{
|
|
wprintf(L"%s File %s wasn't totally written: "
|
|
L"Are you out of disk space?\n", g_szErrorPrefix,
|
|
pszFileName);
|
|
bytesWritten = (unsigned int)-1;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
ERRMSG(L"%s Cannot write to %s\n", g_szErrorPrefix, pszFileName);
|
|
bytesWritten = (unsigned int)-1;
|
|
}
|
|
|
|
return bytesWritten;
|
|
}
|
|
|
|
|
|
HRESULT WriteBlobToFile( LPCWSTR pszFileName, const char *pszCookie, void *pvBlob, DWORD dwSize, unsigned int &cbWritten )
|
|
{
|
|
HRESULT hr = E_FAIL;
|
|
|
|
cbWritten = 0;
|
|
|
|
int fh;
|
|
unsigned int _cbWritten = 0;
|
|
|
|
USES_CONVERSION;
|
|
|
|
if ( (fh = _open(W2A(pszFileName), _O_RDWR | _O_CREAT | _O_TRUNC | _O_BINARY,
|
|
_S_IREAD | _S_IWRITE)) > 0)
|
|
{
|
|
|
|
if (pszCookie)
|
|
{
|
|
hr = ((_cbWritten =
|
|
WriteBlobToFileHandle(pszFileName, fh, pszCookie,
|
|
lstrlenA(pszCookie) + 1)) == -1)
|
|
? E_FAIL : S_OK;
|
|
}
|
|
|
|
unsigned int _cbWritten2;
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = ((_cbWritten2 =
|
|
WriteBlobToFileHandle(pszFileName, fh, pvBlob, dwSize)) == -1)
|
|
? E_FAIL : S_OK;
|
|
|
|
cbWritten = _cbWritten + _cbWritten2;
|
|
|
|
}
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
HRESULT DoTraverse( const CComPtr<IXMLDocument>& spxmlDoc ,
|
|
TagInformation* pTagTable ,
|
|
LPCWSTR pszOutputFileName )
|
|
{
|
|
HRESULT hr;
|
|
CComPtr<IXMLElement> spxmlRoot;
|
|
|
|
if(SUCCEEDED(hr = spxmlDoc->get_root( &spxmlRoot )))
|
|
{
|
|
CTagData tdRoot;
|
|
|
|
hr = TraverseXMLDoc( spxmlRoot, pTagTable, NULL, tdRoot );
|
|
|
|
ASSERT(tdRoot.pData && "No Root Data!!!");
|
|
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
if(hr == S_OK)
|
|
{
|
|
unsigned int cbWritten;
|
|
|
|
hr = WriteBlobToFile( pszOutputFileName, g_szMMFCookie, tdRoot.pData, tdRoot.dwSize, cbWritten );
|
|
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
STATUSMSG( L"Wrote %d bytes to %s.\n", cbWritten, pszOutputFileName );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
HRESULT GetXMLDoc( const CComBSTR& bstrUrl ,
|
|
CComPtr<IXMLDocument>& spxmlDoc )
|
|
{
|
|
HRESULT hr;
|
|
|
|
if(SUCCEEDED(hr = spxmlDoc.CoCreateInstance( CLSID_XMLDocument )))
|
|
{
|
|
hr = spxmlDoc->put_URL( bstrUrl );
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
HRESULT GetXMLDocFromFile( const CComBSTR& bstrFileName ,
|
|
CComPtr<IXMLDocument>& spxmlDoc )
|
|
{
|
|
HRESULT hr;
|
|
|
|
if(SUCCEEDED(hr = spxmlDoc.CoCreateInstance( CLSID_XMLDocument )))
|
|
{
|
|
CComPtr<IStream> spstm;
|
|
|
|
if(SUCCEEDED(hr = SHCreateStreamOnFileW( bstrFileName, 0, &spstm )))
|
|
{
|
|
CComPtr<IPersistStream> sppsPersist;
|
|
|
|
if(SUCCEEDED(hr = spxmlDoc.QueryInterface( &sppsPersist )))
|
|
{
|
|
hr = sppsPersist->Load( spstm );
|
|
}
|
|
}
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
int usage(char *progName)
|
|
{
|
|
printf("Usage: %s inputFileName outputFileName\n", progName);
|
|
return 1;
|
|
}
|
|
|
|
int __cdecl main(int argc, char *argv[])
|
|
{
|
|
int retCode = 0;
|
|
|
|
CoInitialize(NULL);
|
|
|
|
{
|
|
CComPtr<IXMLDocument> spxmlDoc;
|
|
|
|
USES_CONVERSION;
|
|
|
|
if (argc == 3)
|
|
{
|
|
//if (SUCCEEDED(GetXMLDoc(A2W(argv[1]), spxmlDoc)))
|
|
if (SUCCEEDED(GetXMLDocFromFile(A2W(argv[1]), spxmlDoc)))
|
|
{
|
|
if (FAILED(DoTraverse(spxmlDoc, g_rgMasterTagTable, A2W(argv[2]))))
|
|
retCode = 1;
|
|
}
|
|
else
|
|
{
|
|
ERRMSG(L"Failed to load FILE: %s\n", A2W(argv[1]));
|
|
}
|
|
}
|
|
else
|
|
retCode = usage(argv[0]);
|
|
|
|
// this scope calls Release on spxmlDoc *before* CoUnitialize()
|
|
}
|
|
|
|
CoUninitialize();
|
|
|
|
return retCode;
|
|
}
|