Call to VB's CreateObject method in C++ - c++

I'm trying to call Visual Basic's CreateObject method from my C++ code. In VB, I'd simply type:
Dim obj As Object
obj = CreateObject("WScript.Network")
And that returns me the object from which I can call more methods. But how can I do that in C++? I'm following the MSDN documentation in http://msdn.microsoft.com/en-us/library/bb776046(v=VS.85).aspx, but those parameters are very obscure and I can't figure them out.
The first parameter is a reference to a CLSID, and I can see from the registry that the CLSID for "WScript.Network" is {093FF999-1EA0-4079-9525-9614C3504B74}. But what's the difference between this parameter and the third one, REFIID?
Thanks in advance!

I'll provide my solution, just for the record. It calls the AddWindowsPrinterConnection to install a network printer. It asks for user confirmation, so if you want to bypass that, you need to set HKEY_CURRENT_USER/Printers/LegacyPointAndPrint/DisableLegacyPointAndPrintAdminSecurityWarning to 1 (you can change it back to 0, after everything is done).
CoInitialize(NULL);
{
ATL::CComPtr<IDispatch> test;
_variant_t printerConnection = "\\\\serverAddress\\printerName";
_variant_t result;
test.CoCreateInstance(L"WScript.Network");
test.Invoke1(L"AddWindowsPrinterConnection", &printerConnection, &result);
}
CoUninitialize();

First, you probably want to use CoCreateInstance http://msdn.microsoft.com/en-us/library/ms686615%28VS.85%29.aspx, or the equivalent call inside a smart pointer wrapper (eg: CComPtr<>, _com_ptr<>, etc.).
Second, to your specific question, the IID is the interface ID, the CLSID is the class ID. COM objects can have multiple interfaces on the same object in general, which is why there is a distinction (although VB can only see one, which is why you don't need so to specify anything other than the CLSID for VB).
The "correct" way to duplicate what VB is doing is to create the IDispatch interface on the object, and then enumerate the methods using IDispatch. The "better" way in C++ is to create the direct interface you want to use, and call methods directly through it. However, this requires knowing the interface ID (IID, or REFIID passing the struct by reference), which is specific to the other object.
Hope that helps. I can't provide specifics for your particular interface, but maybe this points you in the right direction.

Related

What is CLSID? Is it a GUID?

I want to know what is exactly CLSID data type, as it is used in C++, and I want to use it in delphi.
what is CLSID?
A CLSID is a GUID that identifies a COM object. In order to instantiate a registered COM object, you need to know its CLSID.
Typically in Delphi you would be calling CoCreateInstance. You simply call the function and pass a CLSID. The declaration of CoCreateInstance declares the class ID parameter as having type TCLSID which is a simple alias of TGUID. So pass one of those.
Here are the declarations, as lifted from the Delphi source:
type
TCLSID = TGUID;
function CoCreateInstance(const clsid: TCLSID; unkOuter: IUnknown;
dwClsContext: Longint; const iid: TIID; out pv): HResult; stdcall;
An example of a call to CoCreateInstance, taken from my code base:
const
CLSID_WICImagingFactory: TGUID = '{CACAF262-9370-4615-A13B-9F5539DA4C0A}';
if not Succeeded(CoCreateInstance(CLSID_WICImagingFactory, ...)) then
...
You will likely be creating a different interface, and so will need to substitute the appropriate CLSID for that interface.
There is one other little trick that is worth knowing about. If you pass an interface type as a parameter of type TGUID, and that interface type has a GUID, then the compiler will substitute the GUID for you. So the above code could equally well be written:
type
IWICImagingFactory = interface
// this is the GUID of the interface, the CLSID
[{ec5ec8a9-c395-4314-9c77-54d7a935ff70}]
....
end;
....
if not Succeeded(CoCreateInstance(IWICImagingFactory, ...)) then
...
What is a CLSID? A Class ID (CLSID) is a 128 bit (large) number that represents a unique id for a software application or application
component. Typically they are displayed like this
"{AE7AB96B-FF5E-4dce-801E-14DF2C4CD681}".
You can think of a CLSID as a "social security number" for a piece of
software, or a software component.
What are they used for? CLSIDs are used by Windows to identify software components without having to know their "name". They can also
be used by software applications to identify a computer, file or other
item.
Where do they come from? Microsoft provides a utility (program) called GUIDGEN.EXE that generates these numbers. They are generated by
using the current time, network adapter address (if present) and other
items in your computer so that no two numbers will ever be the same. [1]
and
COM classes are named by CLSIDs, which are UUIDs as defined by OSF/DCE
RPC [2]
Two quotes are cited

How to send list through COM

Can I send a list of objects through COM?
I have my class and there is also a list of this class. And I need to send this through a COM function. Can I do that? If yes, then how? Do I need serialization marshaling?
COM does not pin down any particular collection type, it certainly doesn't have anything standard that models a list. By convention, you can model any collection with an interface. So say you have a collection of Foo objects that each implement IFoo. Then declare an IEnumFoo interface similar to:
interface IEnumFoo : IUnknown
{
HRESULT Next( [in] ULONG celt,
[out, size_is(celt), length_is(*pceltFetched)] IFoo **rgelt,
[in,out,unique] ULONG *pceltFetched );
HRESULT Skip( [in] ULONG celt);
HRESULT Reset();
HRESULT Clone( [out] IEnumFoo **ppenum );
}
And then simply return an interface pointer to an implementation of this interface to allow the client code to enumerate the list. Check the MSDN docs for IEnumVARIANT, a very common enumeration interface type for variants. Which also explains what the methods do.
If one side of the interface will be written in a language with a "simpler" type system, such as VB6 or script, then the SAFEARRAY is the way to go. COM's universal marshaller can take care of it.
If you have C++ on both sides of the interface, and you're happy to define the interface in IDL, and generate custom marshalling code, then IDL includes a "size_is" attribute that can be used. See here for details.
To any reasonable degree, there's no way to do so with std::list. I'm sure there is some maniac who could manage it but from my experience, it's not worth it. If doesn't have to be an std::list and just some linked list, then you'll have to either define a new COM interface and provide it's implementation (which can just be a wrapper around std::list) or find some thirdparty resource that has an adequate implementation for your purposes. If you don't have much experience with implementing COM interfaces, then you'll need to do some good amount of reading.
If it can be an array, then you can make your life a lot simpler by using a SAFEARRAY. And SAFEARRAYs can be easier to use with ATL's CComSafeArray, which is pretty much a wrapper. It tries to help/save you from issues, such as reference counting, when dealing with COM objects. You can then just pass the array between your COM objects. Just going to remind you that you still need to pay attention to who is responsible for de-allocating the memory.

C++ DispInvoke fails to find member

The scenario is this:
I have a COM object to ask questions. Name it ICom.
The COM object requires me to implement an IDispatch , descendant of , say, IComEvents, that notifies me for events.
I implement an IDispatch and connect it to the COM interface.
So far so good. My IComEvents descentant's Invoke() is called when the events occur.
The point is now that I must manually parse Invoke() parameters. For example, if a notification function is HRESULT OnMouseHit(int x), I have to detect this function from the DispID, then call it manually, for example
if (dispIdMember == 0xfa)
{
OnMouseHit(pDispParams->rgvarg[0].pIntVal);
}
I would have to do it for all the functions I want to implement. However I saw the DispInvoke() function which presumably will automatically do this for me and call the appropriate overloaded method for the dispId, with the correct parameters:
DispInvoke(this,m_ptinfo,dispIdMember,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr);
How do I generate m_ptinfo? By calling LoadRegTypeLib with the libid of the COM object, and then ITypeLib::GetTypeInfoOfGuid() with the IID of IComEvents. However, DispInvoke() always returns "member not found".
What would be wrong? I expect DispInvoke to parse the type information, find the member function name from the DispID and then use the "this" pointer to get the function address from the vtbl.
What am I doing wrong?
Thanks a lot.
Michael.
Is IComEvents a dual interface or a dispinterface? If it is a pure dispinterface it doesn't have a vtable. DispInvoke requires the interface to have a vtable (ie that it is a dual interface).

is DISPID_VALUE reliable for invokes on IDispatchs from scripts?

Continuing from this question, i am confused whether DISPID_VALUE on IDispatch::Invoke() for script functions and properties (JavaScript in my case) can be considered standard and reliable for invoking the actual function that is represented by the IDispatch?
If yes, is that mentioned anywhere in MSDN?
Please note that the question is about if that behaviour can be expected, not what some interfaces i can't know in advance might look like.
A simple use case would be:
// usage in JavaScript
myObject.attachEvent("TestEvent", function() { alert("rhubarb"); });
// handler in ActiveX, MyObject::attachEvent(), C++
incomingDispatch->Invoke(DISPID_VALUE, IID_NULL, LOCALE_SYSTEM_DEFAULT,
DISPATCH_METHOD, par, res, ex, err);
edit: tried to clarify the question.
It should be reliable for invokes on objects from scripts if the script defines it consistently. This should be the case for JScript/Javascript in MSHTML, but unfortunately there is really sparse documentation on the subject, I don't have any solid proof in-hand.
In my own experience, a Javascript function passed to attachEvent() should always be consistent- an object received that is a 'function' can only have one callable method that matches itself. Hence the default method is the only one you can find, with DISPID 0. Javascript functions don't ordinarily have member functions, although i'm sure there is a way for this to be possible. If it did have member functions, you would see them the same way as member functions on objects. Member functions in JScript will always be consistent with regard to IDispatchEx, according to the rules of expando functions, as any functions added to an object count as expandos.
IDispatchEx interface # MSDN
The default method or property that DISPID_VALUE invokes should be consistent for a given interface. That method/property has to be specified as DISPID_VALUE in the definition of the interface in the IDL for the type library. The only way it could change is if the owner of the interface released a new version of the interface that changed which method/property was the default but that would violate a fundamental rule of COM interfaces.
As meklarian said, DISPID_VALUE (0) seems to work pretty consistantly for JS functions (thus it works great with a custom attachEvent). I've been using them this way for about a year, and it's always worked. I've also found with an activeX control embedded with an <object> tag that to get it to work consistently, I need to implement IConnectionPointContainer and IConnectionPoint for the main (object tag) IDispatch-implementing CComObject, but any others that I expose to javascript as return values from methods or properties (through Invoke) I have to implement attachEvent and detachEvent myself.
When using Connection Points, the IDispatch objects in question will expect events to be fired to the same DISPID as they are attached to on your IDispatch object..
see http://code.google.com/p/firebreath/source/browse/src/ActiveXPlugin/JSAPI_IDispatchEx.h for an example of implementing the ConnectionPoints.
You can add DISPID's to a DISPINTERFACE, but you cannot change them once it has been published. If you need to, you can use IDispatch::GetIDsOfNames to map names to DISPIDs.
Pick up a copy of Inside Ole (2nd ed) and Inside Ole 2 (2nd ed) for a few bucks used on Amazon. It's a good reference for these obscure OLE incantations.

C++ ATL Member Variable access help

I am not familiar with this, and can use a kick start.
I am using ATL (unmanaged C++) user control and would like to use the ShockWave ActiveX object. I need to know how to declare it so that I can set a property or call a method.
For instance, if I could assign a variable to it, then I would like to call 'variable->LoadMovie()'
I know this is super ridiculous... almost embarrassed to ask it here. ;) (almost)
If you #import the dll (which I recommend when working with COM because it makes your life SO much easier), you can use a smart pointer paired with the CLSID of the object. Remember that smart pointer classes have the post-fix 'Ptr' after the interface name.
For instance:
ISomeInterfacePtr pSomeInterface( CLSID_SomeComponent );
HRESULT hr = pSomeInterface->SomeMethod();
Hope that helps.
EDIT: If you want to check the HRESULT of the allocation, you can do the following:
ISomeInterfacePtr pSomeInterface = 0;
HRESULT hr = pSomeInterface.CreateInstance( CLSID_SomeComponent );
I cut&paste the necessary code so many times I can't remember the exact syntax but you have to:
get a CComPtr<> of the correct interface,
CreateInstance the object
QueryInterface to get the interface you want (assuming you're not using the CComPtr)
then call methods on it.
Alternatively you can #import the dll, then the compiler will generate a c++ class with all the methods and properties for you.