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();
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;
}
Top of Page
© 1997 Microsoft Corporation. All rights reserved. Terms of Use.