#include "pch.h" #include "comptree.h" #include "tagtab.h" //////////////////////////////////////////////////////////////////////////////// HRESULT TraverseXMLDoc( const CComPtr& spxmlElt , TagInformation* pTagTable , const CTagHandler* pthParent , CTagData& tdRoot ); //////////////////////////////////////////////////////////////////////////////// // ((!pszTagName) || pszTagName == spxmlElt.parent.tagName) ? S_OK : S_FALSE HRESULT TagNameMatchesParent( LPCWSTR pszTagName , const CComPtr& spxmlElt ) { HRESULT hr = S_OK; if(pszTagName != NULL) { CComPtr 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& 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& spcol , CComPtr& spEltOut ) { HRESULT hr; CComPtr 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& spcol , CComPtr& 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& spxmlElt , TagInformation* pTagTable , const CTagHandler* pthParent , CTagHandler* pthVisitor ) { HRESULT hr; CComPtr 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 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& 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& spxmlDoc , TagInformation* pTagTable , LPCWSTR pszOutputFileName ) { HRESULT hr; CComPtr 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& spxmlDoc ) { HRESULT hr; if(SUCCEEDED(hr = spxmlDoc.CoCreateInstance( CLSID_XMLDocument ))) { hr = spxmlDoc->put_URL( bstrUrl ); } return hr; } HRESULT GetXMLDocFromFile( const CComBSTR& bstrFileName , CComPtr& spxmlDoc ) { HRESULT hr; if(SUCCEEDED(hr = spxmlDoc.CoCreateInstance( CLSID_XMLDocument ))) { CComPtr spstm; if(SUCCEEDED(hr = SHCreateStreamOnFileW( bstrFileName, 0, &spstm ))) { CComPtr 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 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; }