📄 automationpermissions.cpp
字号:
#include <windows.h>
//////////////////////////////////////////////////////////////
// Class Declaraction for Automation.
// This class is entirely defined inline.
// This class is used to call automation objects using the
// morefamiliar CreateObject notation available to Visual
// Basic and Delphi.
//////////////////////////////////////////////////////////////
class CComVariant : public VARIANT
{
public:
CComVariant(){};
CComVariant(VARIANT v)
:VARIANT(v)
{
};
CComVariant(BSTR bstr)
{
vt = VT_BSTR;
bstrVal = bstr;
};
};
class Automation
{
public:
// HRESULT returned from last automation call
HRESULT hresult;
// IDISPATCH interface pointer for the existing object
LPDISPATCH pdisp;
// hold exception info here
EXCEPINFO excepinfo;
// hold argument error here
UINT uArgErr;
// Constructor, intializes the data members
Automation();
// Copy constructor, intialize data members and call AddRef
Automation(const Automation & rhs);
// Destructor, if dispatch is not NULL then release it
virtual ~Automation();
// assignment operator
Automation & operator=(const Automation & rhs);
// Create the dispatch interface object
HRESULT CreateObject(WCHAR * str);
// Retrieve the active dispatch object
HRESULT GetObject(WCHAR * str);
// Invoke a method
CComVariant Invoke(WCHAR * str, VARIANT * var = NULL,
unsigned int cArgs = 0);
// retrieve a data members value
CComVariant Get(WCHAR * str);
// post a data members value
HRESULT Put(WCHAR * str, CComVariant & var);
};
//////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////
inline Automation::Automation()
: pdisp(NULL),
hresult(S_OK)
{
}
inline Automation::Automation(const Automation & rhs)
: pdisp(rhs.pdisp),
hresult(rhs.hresult)
{
// return an exception if the dispatch pointer is NULL
if (pdisp==NULL)
{
hresult = DISP_E_EXCEPTION;
}
pdisp->AddRef();
}
inline Automation::~Automation()
{
// Release the object
if (pdisp != NULL)
{
pdisp->Release();
pdisp = NULL;
}
}
//////////////////////////////////////////////////////////////
// Assignment operator
//////////////////////////////////////////////////////////////
inline Automation& Automation::operator=(const Automation& rhs)
{
// If the previous object was not release, then do it now.
if (pdisp != NULL)
{
pdisp->Release();
pdisp = NULL;
}
pdisp = rhs.pdisp;
hresult = rhs.hresult;
pdisp->AddRef();
return *this;
};
//////////////////////////////////////////////////////////////
// Method GetObject
// Retrieves the active object, does not create a new instance
//////////////////////////////////////////////////////////////
inline HRESULT Automation::GetObject(WCHAR * str)
{
// If the previous object was not release, then do it now.
if (pdisp != NULL)
{
pdisp->Release();
pdisp = NULL;
}
// Convert the progid to a clsid
CLSID clsid;
hresult = ::CLSIDFromProgID(str, &clsid);
if (hresult)
{
// CLSIDFromProgID failed
return hresult;
};
// Retrieve the instance of the object
LPUNKNOWN punk;
hresult = ::GetActiveObject(clsid, NULL, &punk);
if (hresult)
{
// GetActiveObject failed
return hresult;
};
// Retrieve the interface pointer
hresult = punk->QueryInterface(IID_IDispatch,
(LPVOID FAR *)&pdisp);
if (hresult)
{
// QueryInterface failed
return hresult;
};
// Release the IUnknown reference.
hresult = punk->Release();
return hresult;
}
//////////////////////////////////////////////////////////////
// Method CreateObject
// Retrieves the a new instance of the object
//////////////////////////////////////////////////////////////
inline HRESULT Automation::CreateObject(WCHAR * str)
{
// If the previous object was not release, then do it now.
if (pdisp != NULL)
{
pdisp->Release();
pdisp = NULL;
}
// Convert the progid to a clsid
CLSID clsid;
hresult = ::CLSIDFromProgID(str, &clsid);
if (hresult)
{
// CLSIDFromProgID failed
return hresult;
};
// Create the instance of the object
LPUNKNOWN punk;
hresult = ::CoCreateInstance(clsid, NULL, CLSCTX_SERVER,
IID_IUnknown, (LPVOID FAR *) &punk);
if (hresult)
{
// CoCreateInstance failed
return hresult;
};
// Retrieve the interface pointer
hresult = punk->QueryInterface(IID_IDispatch,
(LPVOID FAR *)&pdisp);
if (hresult)
{
// QueryInterface failed
return hresult;
};
// Release the IUnknown reference.
hresult = punk->Release();
return hresult;
}
//////////////////////////////////////////////////////////////
// Method Get
// Retrieves the property's value
//////////////////////////////////////////////////////////////
inline CComVariant Automation::Get(WCHAR * str)
{
// return an exception if the dispatch pointer is NULL
if (pdisp==NULL)
{
hresult = DISP_E_EXCEPTION;
return CComVariant();
}
// Retrieve the dispatch id for the function name
DISPID dispid;
hresult = pdisp->GetIDsOfNames(IID_NULL, &str, 1,
LOCALE_USER_DEFAULT, &dispid);
if (hresult)
{
// GetIDsOfNames failed
return CComVariant();
};
// Invoke the property GET
DISPPARAMS dispparams = {0};
VARIANTARG variantarg;
VariantInit(&variantarg);
::memset(&excepinfo, 0, sizeof(EXCEPINFO));
uArgErr = 0;
hresult = pdisp->Invoke(dispid, IID_NULL,
LOCALE_USER_DEFAULT,
DISPATCH_PROPERTYGET,
&dispparams, &variantarg,
&excepinfo, &uArgErr);
if (hresult)
{
// Invoke failed
return CComVariant();
};
// return to lhs
return CComVariant(variantarg);
}
//////////////////////////////////////////////////////////////
// Method Put
// Posts the property's value
//////////////////////////////////////////////////////////////
inline HRESULT Automation::Put(WCHAR * str, CComVariant & var)
{
// return an exception if the dispatch pointer is NULL
if (pdisp==NULL)
{
hresult = DISP_E_EXCEPTION;
return hresult;
}
// Retrieve the dispatch id for the function name
DISPID dispid;
hresult = pdisp->GetIDsOfNames(IID_NULL, &str, 1,
LOCALE_USER_DEFAULT, &dispid);
if (hresult)
{
// GetIDsOfNames failed
return hresult;
};
// Invoke the property PUT
DISPPARAMS dispparams = {0};
dispparams.rgvarg = &var;
DISPID x = DISPID_PROPERTYPUT;
dispparams.rgdispidNamedArgs = &x;
dispparams.cArgs = 1;
dispparams.cNamedArgs = 1;
VARIANTARG variantarg;
VariantInit(&variantarg);
::memset(&excepinfo, 0, sizeof(EXCEPINFO));
uArgErr = 0;
// I'm not sure why you have to call PUTREF with these type
// but I encountered similar code in "ATLCTL.CPP"
if (var.vt == VT_UNKNOWN || var.vt == VT_DISPATCH ||
(var.vt & VT_ARRAY) || (var.vt & VT_BYREF))
{
hresult = pdisp->Invoke(dispid, IID_NULL,
LOCALE_USER_DEFAULT,
DISPATCH_PROPERTYPUTREF,
&dispparams, &variantarg,
&excepinfo, &uArgErr);
if (SUCCEEDED(hresult))
return hresult;
}
// If the previous failed or the type did not match then
// make the standard call.
hresult = pdisp->Invoke(dispid, IID_NULL,
LOCALE_USER_DEFAULT,
DISPATCH_PROPERTYPUT,
&dispparams, &variantarg,
&excepinfo, &uArgErr);
return hresult;
}
//////////////////////////////////////////////////////////////
// Method Invoke
// Executes the method
//////////////////////////////////////////////////////////////
inline CComVariant Automation::Invoke(WCHAR * str,
VARIANT * var, unsigned int cArgs)
{
// return an exception if the dispatch pointer is NULL
if (pdisp==NULL)
{
hresult = DISP_E_EXCEPTION;
return CComVariant();
}
// Retrieve the dispatch id for the function name
DISPID dispid;
hresult = pdisp->GetIDsOfNames(IID_NULL, &str, 1,
LOCALE_USER_DEFAULT, &dispid);
if (hresult)
{
// GetIDsOfNames failed
return CComVariant();
};
// Invoke the method
DISPPARAMS dispparams = {0};
dispparams.rgvarg = var;
dispparams.cArgs = cArgs;
VARIANTARG variantarg;
VariantInit(&variantarg);
::memset(&excepinfo, 0, sizeof(EXCEPINFO));
uArgErr = 0;
hresult = pdisp->Invoke(dispid, IID_NULL,
LOCALE_USER_DEFAULT,
DISPATCH_METHOD,
&dispparams, &variantarg,
&excepinfo, &uArgErr);
if (hresult)
{
return CComVariant();
};
return CComVariant(variantarg);
}
int main(int, char **)
{
CoInitialize(NULL);
{
Automation ob;
ob.CreateObject(L"MyAutomationServer.MyAutomationObject");
long l = ob.Get(L"Hello").lVal;
}
CoUninitialize();
return 0;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -