In this code, I am creating a COM object to programatically access internet explorer. In order to access this object's properties and methods, I am writing wrapper functions like navigate
or setVisible
.
Is there a cleaner or easier way to use COM objects from C? Moreover, can you point out things that I could have done better?
#include <stdio.h>
#include <windows.h>
HRESULT createIE(LPVOID *pDisp)
{
CLSID clsid;
HRESULT hr;
hr = CLSIDFromProgID(L"InternetExplorer.Application", &clsid);
if(FAILED(hr)) {
MessageBox(NULL, "Internet Explorer not registered.", "Error",
MB_SETFOREGROUND);
return hr;
}
hr = CoCreateInstance(&clsid, NULL, CLSCTX_LOCAL_SERVER,
&IID_IDispatch, pDisp);
if(FAILED(hr)) {
MessageBox(NULL, "Couldn't start Internet Explorer.", "Error",
MB_SETFOREGROUND);
return hr;
}
return S_OK;
}
HRESULT navigate(IDispatch *pDisp, BSTR *url)
{
HRESULT hr;
DISPID dispID;
VARIANT parm1;
DISPPARAMS dispParams = { NULL, NULL, 0, 0 };
LPOLESTR rgszNames[1] = {L"Navigate"};
pDisp->lpVtbl->GetIDsOfNames(pDisp, &IID_NULL, rgszNames, 1, LOCALE_USER_DEFAULT, &dispID);
VariantInit(&parm1);
parm1.vt = VT_BSTR;
parm1.pbstrVal = url;
// One argument.
dispParams.cArgs = 1;
dispParams.rgvarg = &parm1;
// Navigate to url
hr = pDisp->lpVtbl->Invoke(pDisp,
dispID, &IID_NULL, LOCALE_SYSTEM_DEFAULT, DISPATCH_METHOD,
&dispParams, NULL, NULL, NULL
);
if (FAILED(hr)) {
char buf[8192];
sprintf(buf, "IDispatch::Invoke() failed with %08lx", hr);
MessageBox(NULL, buf, "Debug Notice", MB_SETFOREGROUND);
return hr;
}
return S_OK;
}
HRESULT setVisible(IDispatch *pDisp, BOOL visibility)
{
HRESULT hr;
DISPID dispID;
DISPPARAMS dispParams = { NULL, NULL, 0, 0 };
VARIANT parm1;
DISPID dispidNamed = DISPID_PROPERTYPUT;
LPOLESTR rgszNames[1] = {L"Visible"};
pDisp->lpVtbl->GetIDsOfNames(pDisp, &IID_NULL, rgszNames, 1, LOCALE_USER_DEFAULT, &dispID);
VariantInit(&parm1);
parm1.vt = VT_I4;
parm1.lVal = visibility;
// One argument.
dispParams.cArgs = 1;
dispParams.rgvarg = &parm1;
// Handle special-case for property-puts!
dispParams.cNamedArgs = 1;
dispParams.rgdispidNamedArgs = &dispidNamed;
// Set 'visible' property
hr = pDisp->lpVtbl->Invoke(pDisp,
dispID, &IID_NULL, LOCALE_SYSTEM_DEFAULT,
DISPATCH_PROPERTYPUT | DISPATCH_METHOD,
&dispParams, NULL, NULL, NULL
);
if(FAILED(hr)) {
char buf[8192];
sprintf(buf, "IDispatch::Invoke() failed with %08lx", hr);
MessageBox(NULL, buf, "Debug Notice", MB_SETFOREGROUND);
return hr;
}
return S_OK;
}
void main(void) {
IDispatch *pDisp; // Main IDispatch pointer.
HRESULT hr; // General error/result holder.
// Initialize OLE Libraries.
OleInitialize(NULL);
hr = createIE((void **)&pDisp);
if (FAILED(hr)) {
return;
}
hr = setVisible(pDisp, TRUE);
if (FAILED(hr)) {
return;
}
BSTR url = SysAllocString(L"www.google.com");
hr = navigate(pDisp, url);
if (FAILED(hr)) {
return;
}
// Uninitialize OLE Libraries.
OleUninitialize();
}