Last active
June 26, 2022 01:21
-
-
Save Alexhuszagh/c231052cb6e51868215608305fe4e797 to your computer and use it in GitHub Desktop.
Example Using COM IDispatch Interface
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** Example using the COM interface without AutoCOM. The entire | |
* file can be automated with AutoCOM in under 15-lines of code. | |
* | |
* #include "autocom.hpp" | |
* int main(int argc, char *argv[]) | |
* { | |
* com::Bstr text; | |
* com::Dispatch dispatch("VBScript.RegExp"); | |
* dispatch.put("Pattern", L"\\w+"); | |
* for (auto match: dispatch.iter("Execute", L"A(b) c35 d_[x] yyy")) { | |
* match.get("Value", text); | |
* printf("Match is %S\n", text); | |
* } | |
* return 0; | |
* } | |
*/ | |
#include <cassert> | |
#include <cstdio> | |
#include <dispex.h> | |
#include <oaidl.h> | |
#include <wtypes.h> | |
void putPattern(IDispatch *dispatch) | |
{ | |
// initialize parameters | |
DISPPARAMS dp = {nullptr, nullptr, 0, 0}; | |
VARIANT *args = new VARIANT[1]; | |
DISPID named = DISPID_PROPERTYPUT; | |
VariantInit(&args[0]); | |
args[0].vt = VT_BSTR; | |
args[0].bstrVal = SysAllocString(L"\\w+"); | |
dp.rgvarg = args; | |
dp.cArgs = 1; | |
dp.rgdispidNamedArgs = &named; | |
dp.cNamedArgs = 1; | |
// get function ID | |
DISPID id; | |
LPOLESTR string = L"Pattern"; | |
if (FAILED(dispatch->GetIDsOfNames(IID_NULL, &string, DISPATCH_METHOD, LOCALE_USER_DEFAULT, &id))) { | |
assert(false); | |
} | |
// call method | |
VARIANT result; | |
VariantInit(&result); | |
if (FAILED(dispatch->Invoke(id, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_PROPERTYPUT, &dp, &result, nullptr, nullptr))) { | |
assert(false); | |
} | |
// cleanup | |
VariantClear(&args[0]); | |
VariantClear(&result); | |
delete[] args; | |
} | |
IDispatch * callExecute(IDispatch *dispatch) | |
{ | |
// initialize parameters | |
DISPPARAMS dp = {nullptr, nullptr, 0, 0}; | |
VARIANT *args = new VARIANT[1]; | |
VariantInit(&args[0]); | |
args[0].vt = VT_BSTR; | |
args[0].bstrVal = SysAllocString(L"A(b) c35 d_[x] yyy"); | |
dp.rgvarg = args; | |
dp.cArgs = 1; | |
// get function ID | |
DISPID id; | |
LPOLESTR string = L"Execute"; | |
if (FAILED(dispatch->GetIDsOfNames(IID_NULL, &string, DISPATCH_METHOD, LOCALE_USER_DEFAULT, &id))) { | |
assert(false); | |
} | |
// call method | |
VARIANT result; | |
if (FAILED(dispatch->Invoke(id, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_PROPERTYGET | DISPATCH_METHOD, &dp, &result, nullptr, nullptr))) { | |
assert(false); | |
} | |
// cleanup | |
VariantClear(&args[0]); | |
delete[] args; | |
return result.pdispVal; | |
} | |
IEnumVARIANT * requestEnumVariant(IDispatch *dispatch) | |
{ | |
// initialize parameters | |
DISPPARAMS dp = {nullptr, nullptr, 0, 0}; | |
VARIANT result; | |
// call method | |
auto hr = dispatch->Invoke(DISPID_NEWENUM, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_PROPERTYGET | DISPATCH_METHOD, &dp, &result, nullptr, nullptr); | |
if (FAILED(hr)) { | |
assert(false); | |
} | |
IEnumVARIANT *ev = nullptr; | |
if (result.vt == VT_DISPATCH) { | |
hr = result.pdispVal->QueryInterface(IID_IEnumVARIANT, (void**) &ev); | |
} else if (result.vt == VT_UNKNOWN) { | |
hr = result.punkVal->QueryInterface(IID_IEnumVARIANT, (void**) &ev); | |
} else { | |
hr = E_NOINTERFACE; | |
} | |
VariantClear(&result); | |
if (FAILED(hr)) { | |
assert(false); | |
} | |
return ev; | |
} | |
void printMatch(IDispatch *match) | |
{ | |
// initialize parameters | |
DISPPARAMS dp = {nullptr, nullptr, 0, 0}; | |
VARIANT result; | |
VariantInit(&result); | |
// get function ID | |
DISPID id; | |
LPOLESTR string = L"Value"; | |
if (FAILED(match->GetIDsOfNames(IID_NULL, &string, DISPATCH_METHOD, LOCALE_USER_DEFAULT, &id))) { | |
assert(false); | |
} | |
// call method | |
if (FAILED(match->Invoke(id, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_PROPERTYGET | DISPATCH_METHOD, &dp, &result, nullptr, nullptr))) { | |
assert(false); | |
} | |
// get value | |
printf("Match is %S\n", result.bstrVal); | |
VariantClear(&result); | |
} | |
int main(int argc, char *argv[]) | |
{ | |
CoInitializeEx(nullptr, COINIT_MULTITHREADED); | |
// create our dispatcher | |
GUID guid; | |
IDispatch *dispatch; | |
CLSIDFromProgID(L"VBScript.RegExp", (LPCLSID) &guid); | |
if (FAILED(CoCreateInstance(guid, nullptr, CLSCTX_INPROC_SERVER, IID_IDispatch, (void **) &dispatch))) { | |
assert(false); | |
} | |
// call methods | |
putPattern(dispatch); | |
auto *enumdispatcher = callExecute(dispatch); | |
auto ev = requestEnumVariant(enumdispatcher); | |
// iterate | |
VARIANT result; | |
ULONG fetched; | |
if (SUCCEEDED(ev->Next(1, &result, &fetched))) { | |
IDispatch *match = result.pdispVal; | |
printMatch(match); | |
} | |
// cleanup | |
ev->Release(); | |
enumdispatcher->Release(); | |
dispatch->Release(); | |
CoUninitialize(); | |
return 0; | |
} |
@WKleinschmit you are correct about parameter #3, but the bug is, he's using DISPATCH_METHOD
in that position. (LOCALE_USER_DEFAULT
is in fact the symbol to use for parameter #4 unless there is some actual locale work being done.) His bug is how I ended up here in the first place, because I'm looking for a good example of Invoke(… DISPATCH_METHOD …)
, with little luck so far.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
The 3rd parameter of GetIDsOfNames is the number of names. This should be 1 not LOCALE_USER_DEFAULT since it has nothing to do with a localse.