Sample 3: Using IPersistMoniker::Load to Load a Document
//**************************************** // MSXML OM test code // // adapted for multithreaded urlmon testing //**************************************** #include <windows.h> #include <windowsx.h> #include <stdlib.h> #include <stdio.h> #include <io.h> #include <urlmon.h> #include <hlink.h> #include <dispex.h> #include "mshtml.h" #include "msxml.h" int MyStrToOleStrN(LPOLESTR pwsz, int cchWideChar, LPCTSTR psz); #define ASSERT(x) if(!(x)) DebugBreak() #define CHECK_ERROR(cond, err) if (!(cond)) {pszErr=(err); goto done;} #define SAFERELEASE(p) if (p) {(p)->Release(); p = NULL;} else ; // // SAFECAST(obj, type) // // This macro is extremely useful for enforcing strong typechecking on other // macros. It generates no code. // // Simply insert this macro at the beginning of an expression list for // each parameter that must be typechecked. For example, for the // definition of MYMAX(x, y), where x and y absolutely must be integers, // use: // // #define MYMAX(x, y) (SAFECAST(x, int), SAFECAST(y, int), ((x) > (y) ? (x) : (y))) // // #define SAFECAST(_obj, _type) (((_type)(_obj)==(_obj)?0:0), (_type)(_obj)) #define WALK_ELEMENT_COLLECTION(pCollection, pDispItem) \ {\ long length;\ \ if (SUCCEEDED(pCollection->get_length(&length)) && length > 0)\ {\ VARIANT vIndex, vEmpty;\ vIndex.vt = VT_I4;\ vEmpty.vt = VT_EMPTY;\ \ for (long i=0; i<length; i++)\ {\ vIndex.lVal = i;\ IDispatch *pDispItem = NULL;\ if (SUCCEEDED(pCollection->item(vIndex, vEmpty, &pDispItem)))\ { #define END_WALK_ELEMENT_COLLECTION(pDispItem) \ pDispItem->Release();\ }\ }\ }\ } //========================================================================== class CTestBindStatusCallback : public IBindStatusCallback , public IAuthenticate , public IHttpSecurity { public: // *** IUnknown methods *** STDMETHOD(QueryInterface)(REFIID riid, LPVOID * ppvObj); STDMETHOD_(ULONG, AddRef)(void) ; STDMETHOD_(ULONG, Release)(void); // *** IAuthenticate *** STDMETHOD(Authenticate)( HWND *phwnd, LPWSTR *pszUsername, LPWSTR *pszPassword); // *** IBindStatusCallback *** STDMETHOD(OnStartBinding)( /* [in] */ DWORD grfBSCOption, /* [in] */ IBinding *pib); STDMETHOD(GetPriority)( /* [out] */ LONG *pnPriority); STDMETHOD(OnLowResource)( /* [in] */ DWORD reserved); STDMETHOD(OnProgress)( /* [in] */ ULONG ulProgress, /* [in] */ ULONG ulProgressMax, /* [in] */ ULONG ulStatusCode, /* [in] */ LPCWSTR szStatusText); STDMETHOD(OnStopBinding)( /* [in] */ HRESULT hresult, /* [in] */ LPCWSTR szError); STDMETHOD(GetBindInfo)( /* [out] */ DWORD *grfBINDF, /* [unique][out][in] */ BINDINFO *pbindinfo); STDMETHOD(OnDataAvailable)( /* [in] */ DWORD grfBSCF, /* [in] */ DWORD dwSize, /* [in] */ FORMATETC *pformatetc, /* [in] */ STGMEDIUM *pstgmed); STDMETHOD(OnObjectAvailable)( /* [in] */ REFIID riid, /* [iid_is][in] */ IUnknown *punk); /* *** IHttpSecurity *** */ STDMETHOD(GetWindow)(REFGUID rguidReason, HWND* phwnd); STDMETHOD(OnSecurityProblem)(DWORD dwProblem); // Worker routines IBinding* m_pib; IMoniker* m_pmk; IBindCtx* m_pbc; HANDLE m_hEvent; ULONG m_cRef; VOID Abort(); // Aborts the binding ~CTestBindStatusCallback(); CTestBindStatusCallback(IBindCtx *pbc, IMoniker *pmkIn, HANDLE hEvent); }; void Indent(int indent, FILE *fileID) { while (indent-->0) { fprintf(fileID, " "); } } // // Dump an element attribute member if present. // void DumpAttrib(IXMLElement *pElem, BSTR bstrAttribName, FILE *fileID) { VARIANT vProp; VariantInit(&vProp); if (SUCCEEDED(pElem->getAttribute(bstrAttribName, &vProp))) { if (vProp.vt == VT_BSTR) { fprintf(fileID, "%S=\"%S\" ", bstrAttribName, vProp.bstrVal); } VariantClear(&vProp); } } HRESULT DumpElement(IXMLElement *pElem, int indent, FILE *fileID) { BSTR bstr = NULL; IXMLElementCollection * pChildren; Indent(indent, fileID); // // Dump the name of the NODE. // pElem->get_tagName(&bstr); fprintf(fileID, "<%S ", bstr?bstr:L"XML"); // // Dump the attributes if present. // DumpAttrib(pElem, L"VALUE", fileID); DumpAttrib(pElem, L"HREF", fileID); DumpAttrib(pElem, L"HOUR", fileID); DumpAttrib(pElem, L"DAY", fileID); DumpAttrib(pElem, L"IsClonable", fileID); DumpAttrib(pElem, L"Type", fileID); // // Find the children if they exist. // if (SUCCEEDED(pElem->get_children(&pChildren)) && pChildren) { fprintf(fileID, ">\n"); WALK_ELEMENT_COLLECTION(pChildren, pDisp) { // // pDisp will iterate over an IDispatch for each item in the collection. // IXMLElement * pChild; if (SUCCEEDED(pDisp->QueryInterface(IID_IXMLElement, (void **)&pChild))) { DumpElement(pChild, indent+1, fileID); pChild->Release(); } } END_WALK_ELEMENT_COLLECTION(pDisp); pChildren->Release(); // // Have output children display closing tag. // Indent(indent, fileID); fprintf(fileID, "</%S>\n", bstr?bstr:L"XML"); } else { // // No children so terminate tag on same line. // fprintf(fileID, "/>\n"); } if (bstr) SysFreeString(bstr); return S_OK; } HANDLE g_hMutex = NULL; ULONG g_ulNextThreadId = 0; DWORD WINAPI LoadFunc(CHAR *pszUrl) { FILE *fileID = stdout; HRESULT hr; IXMLElement *pElem = NULL; IUnknown *pUnk = NULL; IXMLDocument *pDoc = NULL; IMoniker *pmk = NULL; HANDLE hEvent = NULL; IBindStatusCallback *pPreviousCallback = NULL; IPersistMoniker *pPersistmk = NULL; PSTR pszErr = NULL; IBindCtx *pbc = NULL; IBindStatusCallback *pbsc = NULL; DWORD dwRet; LONG len; WCHAR *pwszUrl; ASSERT(SUCCEEDED(hr)); len = lstrlenA(pszUrl); pwszUrl = (WCHAR *)LocalAlloc(LMEM_FIXED, (len + 1)*sizeof(WCHAR)); ASSERT(pwszUrl); MyStrToOleStrN(pwszUrl, len + 1, pszUrl); // // Dump the root element and all children of the XML object. // ASSERT(SUCCEEDED(hr)); if (!pDoc) { hr = CoCreateInstance(CLSID_XMLDocument, NULL, CLSCTX_INPROC_SERVER, IID_IUnknown, (void**)&pUnk); } CHECK_ERROR (pUnk, "CoCreateInstance"); hr = pUnk->QueryInterface(IID_IXMLDocument, (void **)&pDoc); ASSERT(SUCCEEDED(hr)); pUnk->Release(); pUnk = NULL; CHECK_ERROR (pDoc, "QI for IXMLDocument"); hr = pDoc->QueryInterface(IID_IPersistMoniker, (void **)&pPersistmk); ASSERT(SUCCEEDED(hr)); CHECK_ERROR(pPersistmk, "QI for IPersistMoniker"); hr = CreateURLMoniker(NULL, pwszUrl, &pmk); ASSERT(SUCCEEDED(hr)); CHECK_ERROR(pmk, "CreateURLMoniker"); hr = CreateBindCtx(0, &pbc); if((!pbc) || FAILED(hr)) goto done; pbc->AddRef(); hEvent = CreateEventA(0, 0, 0, 0); pbsc = new CTestBindStatusCallback(pbc, pmk, hEvent); ASSERT(pbsc); if(!pbsc) { fprintf (stderr, "Out of memory "); goto done; } pbsc->AddRef(); hr = RegisterBindStatusCallback(pbc, pbsc, &pPreviousCallback, 0); if(FAILED(hr)) { fprintf (stderr, "RegisterBindStatusCallback : Failed"); goto done; } hr = pPersistmk->Load(FALSE, pmk, pbc, 0); ASSERT(SUCCEEDED(hr)); if(pPersistmk) { pPersistmk->Release(); pPersistmk = NULL; } while(1) { MSG msg; dwRet = MsgWaitForMultipleObjects(1, &hEvent, FALSE, INFINITE, QS_ALLINPUT); if(dwRet == WAIT_OBJECT_0) { // We're done break; } else { GetMessage(&msg, NULL, 0, 0); DispatchMessage(&msg); } } // Ready to start dumping the document. // // Now walk the OM and look at interesting things. // hr = pDoc->get_root(&pElem); CHECK_ERROR(pElem, "Thread Failed to get_root of XML object"); DumpElement(pElem, 0, fileID); done: // Clean up. fclose(fileID); pElem->Release(); pDoc->Release(); LocalFree(pwszUrl); pbsc->Release(); return 0; } int MyStrToOleStrN(LPOLESTR pwsz, int cchWideChar, LPCTSTR psz) { int i; i=MultiByteToWideChar(CP_ACP, 0, psz, -1, pwsz, cchWideChar); if (!i) { //DBG_WARN("MyStrToOleStrN string too long; truncated"); pwsz[cchWideChar-1]=0; } else ZeroMemory(pwsz+i, sizeof(OLECHAR)*(cchWideChar-i)); return i; } #define NUM_THREADS 1 const WCHAR *szUrls[NUM_THREADS] = { L"http://ie_tools/bharats/msnbc0.cdf", //L"http://ie_tools/bharats/msnbc1.cdf", // L"http://ie_tools/bharats/msnbc2.cdf", //L"http://ie_tools/bharats/msnbc3.cdf", //L"http://ie_tools/bharats/msnbc4.cdf" }; int _cdecl main (int argc, char **argv) { PSTR pszErr = NULL; IStream *pStm = NULL; IPersistStreamInit *pPSI = NULL; IXMLElement *pElem = NULL; char buf[MAX_PATH]; char *pszURL; UINT uNumThreads = NUM_THREADS; // Atleast three threads UINT ui;// iterator DWORD dwThreadId; HANDLE hThd; WCHAR *pwszStrUrlCopy = NULL; LONG len; HRESULT hr; // // Check usage. // if (argc < 2) { fprintf (stderr, "Usage: %s URL\n",argv[0]); fprintf (stderr, "Eg %s c:\\nt\\private\\inet\\xml\\test\\channel.uni\n", argv[0]); fprintf (stderr, "or %s http://ohserv/users/julianj/channel.xml\n", argv[0]); exit (1); } // HACK if passed in a file name, expand if it doesn't look like a URL. // if (CompareString(LOCALE_USER_DEFAULT, NORM_IGNORECASE, argv[1], 7, "http://", 7) == CSTR_EQUAL) { pszURL = argv[1]; } else { pszURL = buf; GetFullPathName(argv[1], MAX_PATH, pszURL, NULL); } hr = CoInitialize(NULL); ASSERT(SUCCEEDED(hr)); // // Create an empty XML document. // LoadFunc(pszURL); len = lstrlen(pszURL) + 1; // // Dump the root element and all children of the XML object onto screen. done: // Clean up. // // Release any used interfaces. // SAFERELEASE(pPSI); SAFERELEASE(pStm); SAFERELEASE(pElem); if (pszErr) fprintf (stderr, "%s, last error %d\n", pszErr, GetLastError()); return 0; } STDMETHODIMP CTestBindStatusCallback::QueryInterface( REFIID riid, LPVOID * ppvObj) { if (IsEqualIID(riid, IID_IBindStatusCallback) || IsEqualIID(riid, IID_IUnknown)) { *ppvObj = SAFECAST(this, IBindStatusCallback*); } else if (IsEqualIID(riid, IID_IAuthenticate)) { *ppvObj = SAFECAST(this, IAuthenticate*); } else if (IsEqualIID(riid, IID_IHttpSecurity)) { *ppvObj = SAFECAST(this, IHttpSecurity*); } else { *ppvObj = NULL; return E_NOINTERFACE; } ((LPUNKNOWN)*ppvObj)->AddRef(); return NOERROR; } ULONG CTestBindStatusCallback::AddRef(void) { return ++m_cRef; } ULONG CTestBindStatusCallback::Release(void) { if( 0L != --m_cRef ) return m_cRef; delete this; return 0L; } VOID CTestBindStatusCallback::Abort() { if(m_pib) { m_pib->Abort(); } } CTestBindStatusCallback::CTestBindStatusCallback(IBindCtx *pbc, IMoniker *pmkIn, HANDLE hEvent) { // Initialize object. m_cRef=0L; m_pib = NULL; m_pbc = pbc; if(m_pbc) m_pbc->AddRef(); m_pmk = pmkIn; if(m_pmk) m_pmk->AddRef(); m_hEvent = hEvent; } CTestBindStatusCallback::~CTestBindStatusCallback() { SAFERELEASE(m_pib); SAFERELEASE(m_pbc); SAFERELEASE(m_pmk); if(m_hEvent) CloseHandle(m_hEvent); } // IAuthenticate Methods STDMETHODIMP CTestBindStatusCallback::Authenticate( HWND *phwnd, LPWSTR *pszUsername, LPWSTR *pszPassword) { return E_NOTIMPL; } // IBindStatusCallback Methods STDMETHODIMP CTestBindStatusCallback::OnStartBinding(DWORD grfBSCOption, IBinding *pibIn) { return S_OK; } STDMETHODIMP CTestBindStatusCallback::GetPriority(LONG *pnPriority) { return S_OK; } STDMETHODIMP CTestBindStatusCallback::OnLowResource(DWORD reserved) { return S_OK; //BUGBUG } STDMETHODIMP CTestBindStatusCallback::OnProgress( ULONG ulProgress, ULONG ulProgressMax, ULONG ulStatusCode, LPCWSTR szStatusText) { return S_OK; } STDMETHODIMP CTestBindStatusCallback::OnStopBinding( HRESULT hresult, LPCWSTR szError) { HRESULT hr = S_OK; if(SUCCEEDED(hresult)) { OutputDebugString(TEXT("Done Loading succesfully")); } // Signal event to wake up thread to navigate children. SetEvent(m_hEvent); SAFERELEASE(m_pib); return hr; } STDMETHODIMP CTestBindStatusCallback::GetBindInfo( DWORD *grfBINDF, /* [out] */ BINDINFO *pbindinfo /* [unique][out][in] */ ) { return E_NOTIMPL; } STDMETHODIMP CTestBindStatusCallback::OnDataAvailable( /* [in] */ DWORD grfBSCF, /* [in] */ DWORD dwSize, /* [in] */ FORMATETC *pformatetc, /* [in] */ STGMEDIUM *pstgmed) { return S_OK; } STDMETHODIMP CTestBindStatusCallback::OnObjectAvailable( /* [in] */ REFIID riid, /* [iid_is][in] */ IUnknown *punk) { return S_OK; } /* *** IHttpSecurity *** */ // BUGBUG - Do we need to implement this interface STDMETHODIMP CTestBindStatusCallback::GetWindow(REFGUID rguidReason, HWND* phwnd) { if (!phwnd) return E_POINTER; *phwnd = NULL; // BUGBUG return S_OK; } STDMETHODIMP CTestBindStatusCallback::OnSecurityProblem(DWORD dwProblem) { // Force UI - return S_FALSE for all problems. return S_FALSE; }
© 1999 Microsoft Corporation. All rights reserved. Terms of use.