What is CLSID? Is it a GUID? - c++

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

Related

COM Object version number and how it's handled via the Win registry

a COM object is registered to the system via a bunch of informaion - stuff like the GUID, ProgId etc.
TypeLibs also have a 'version' field which a) can be written to the registry and b) are inside the idl.
My question now is - is the version field somehow checked by the system while using/ initating the COM object.
E.g. if I create a new version of my COM Object without changeing the GUID but with incrementing the version number does this lead to any kind of inconsistency?
The reason for not changing the GUID but incrementing the version number would be bug fixes in the typelib without touching the interface.
This should not be an issue, gven your deployment scenario. COM is an umbrella term for a series of technologies. At almost the lowest level*, CoCreateInstance doesn't care about higher-level concepts such as typelibs. It does care about IClassFactory, and in particular its CreateInstance method. Neither the CoGetClassObject function to get IClassFactory, nor the IClassFactory::CreateInstance method use the typelib version number, or even assume that a typelib exists.
*At the very lowest level, you can even have COM objects without a class factory or CLSID, but those can't be created by CoCreateInstance.

Add Method to COM Interface

I created a ATL COM dll workspace with VS2008. It has generated MyCom.idl interface. Does it provide any easy way to add a method to this interface?
Yes, there is an option to do that.
It is not that hard to do this without a wizard. I learned that adding COM interface methods the hard way because I was too lazy to look it up in MSDN, so I looked closely at other COM interfaces and experimented by adding properties, methods, etc.
First of all there are two drawbacks when using the wizard, especially when editing existing COM interfaces. First it is slow, especially if you have a large component with dozens of interfaces. I sit in front of a quite decent workstation and opening the wizard and completeing the two or three steps takes longer than adding the method by hand to the IDL, .h and .cpp file.
Second is that when using different Visual Studio and thus different Wizard versions there will be generated c++ dirt like multiple public-statements without any need and stuff like that. However I recommend that you act like the wizard in order to not confuse it further if the next programmer uses the wizard again - which will increase confusion and in the end leading to increased file sizes, unreadable class declarations and longer compile times. Just insert the same type of methods or macros at the same place the wizard does.
So maybe you might find useful what I found out so long. You can find a lot more details in the article "Understanding IDL" which is quite old, but provides essential basics which I will not mention here though.
The IDL file holds all interface definitions your component will export. So if you want to add a method you need to find the corresponding interface definition which is introduced by the "interface" keyword and a name which usally starts with a capital I. The interface is preceded by some annotations surrounded by [ and ] which I will not explain for the sake of simplicity. When using Visual Studio IDL keywords will be highlighted correctly. This is how a typical interface might look like:
[
object,
uuid(0B2499FA-0D73-488C-B961-03FB8327485C),
dual, helpstring("IMyInterface Interface"),
pointer_default(unique)
]
interface IMyInterface : IDispatch {
// ... methods and properties
};
Now let us assume the IMyInterface contains one method only and you want to add a similar second one:
[id(1), EXCLUDE_FROM_HELP] HRESULT DoSomething([in] long newVal, [out, retval] long* pRetVal);
Again there are annotations within the [ ] brackets. When adding a new method increase the id annotations value. Also precede the parameters with the [in] annotation for input parameters, [out] for parameters which will contain the methods results. If there is only one result you may want to use a method which uses the result as return value. Then use the [out, retval] annotation.
So when adding such a method copy the line above, increase the ID and changed the methods name and adapt the parameters accordingly.
Note that the [out] parameters always must be a pointer. There are several reasons for this, the most obvious one is that [in, out] is possible too, thus the result for a parameter should be written to the same memory address inside the component so it is possible to pass it back to the caller easily. Also note that the "real" return value should be an HRESULT handle, which will indicate the success or failure of the method.
Now let us look inside the C++ header. I assume you will find the correct file and place by yourself.
STDMETHOD(DoSomething)(/*[in]*/ long newVal, /*[out, retval]*/ long* pRetVal);
The STDMETHOD macro takes care of the result value which is HRESULT and the calltype. The annoations are not valid here but for clarification of the intended usage within the IDL file they are added as comments. These comments are optional though. Be careful to use the same datatypes as inside the IDL file.
STDMETHODIMP CMyClass::DoSomething( /*[in]*/ long newVal, /*[out, retval]*/ long* pRetVal )
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
long result = GetTheResultValueFromSomewhere();
*pRetVal = result;
return S_OK;
}
The STDMETHODIMP is a different macro than in the header. Basically it does the same though. Important is the AFX_MANAGE_STATE macro if you want to use resources within an MFC dialog for instance. Imagine the value in the example above is determined by prompting the user. Read about it in the Technical Tips blog post.
Understanding the IDL mechanisms will help you as soon as errors occur which do not necessarily refer to a problem in your logic but the interface. It will also allow you to understand what the interface actually does, which will help you avoding errors when using the wizard so I encourage anyone to read at least some basic information about it.
There should be an option if you expand the idl in the class view to right click on a specific class and 'add method' or 'add property' which will take you through a small wizard adding the method to your interface and your associated implementation.

"Set" COM object properties in batch in c++

I have to set the properties of a COM object.
The COM object has a Set function that takes a key (string) and a value (variant) as parameters. For example I can do : com_object->Set("name", "John").
I have many properties to set, but I don't know how to do it in C++. In VB.Net it would look like that:
com_object.Set "name,age", Array("M2", 1)
I would like to do the same in C++ but I don't know the syntax.
EDIT
Here is the code I have written to access properties in batch:
template < class ComObjectType >
void read(ComObjectType com_object, std::string const& fields)
{
COleSafeArray data_array_;
data_array_ = com_object->GetGet((LPCSTR)fields.c_str());
long index = 0;
VARIANT value_temp_;
_variant_t value_reader_;
data_array_.GetElement(&index, &value_temp_);
value_reader_.Attach(value_temp_);
std::string str1 = (LPCSTR)((_bstr_t) value_reader_)
++index
data_array_.GetElement(&index, &value_temp_);
value_reader_.Attach(value_temp_);
long long1 = value_reader_.lVal;
}
Then I call this function (which actually does not do much but is just there for the demonstration. The IAPIOrderObj* can be anything but it is defined in the .tlh file of the API I am being provided with, and it inherits from IDispatch interface.
MYAPI::IAPIOrderObj* my_obj;
read< IAPIOrderObj* >(my_obj, "StatusString,StatusCode");
What are you using to access the COM component MFC or ATL or only c++ library like _bsrt_t I cannot derive this information from your code snippet.
With some basic assumptions here are some points to consider.
Normally VB uses the IDispatch interface to access the COM components. From C++ there may be a native interface which may be much more easier to access than the IDispatch interface. From the com_object you can query this c++ interface.
Always use the COM strings (BSTR, SysAllocString allocated) for passing string information across.
Don't typecast from LPCSTR to _bstr_t. Both string representation has different meanings. Always use proper conversion functions to do the conversions.
Hope this helps.

Call to VB's CreateObject method in 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.

Custom COM Implementation?

I'm looking to implement a custom implementation of COM in C++ on a UNIX type platform to allow me to dynamically load and link object oriented code. I'm thinking this would be based on a similar set of functionality that POSIX provides to load and call dll's ie dlopen, dlsym and dlclose.
I understand that the general idea of COM is that you link to a few functions ie QueryInterface, AddRef and Release in a common dll (Kernel32.dll) which then allows you to access interfaces which are just a table of function pointers encapsulated with a pointer to the object for which the function pointers should be called with. These functions are exposed through IUnknown which you must inherit off of.
So how does this all work? Is there a better way to dynamically link and load to object oriented code? How does inheritance from a dll work - does every call to the base class have to be to an exposed member function i.e private/protected/public is simply ignored?
I'm quite well versed in C++ and template meta-programming and already have a fully reflective C++ system i.e member properties, member functions and global/static functions that uses boost.
A couple of things to keep in mind:
The power of COM comes largely from the IDL and the midl compiler. It allows a verry succint definition of the objects and interfaces with all the C/C++ boilerplate generated for you.
COM registration. On Windows the class IDs (CLSID) are recorded in the registry where they are associated with the executable. You must provide similar functionality in the UNIX environment.
The whole IUnknown implementation is fairly trivial, except for QueryInterface which works when implemented in C (i.e. no RTTI).
A whole another aspect of COM is IDispatch - i.e. late bound method invocation and discovery (read only reflection).
Have a look at XPCOM as it is a multi-platform COM like environment. This is really one of those things you are better off leveraging other technologies. It can suck up a lot of the time better spent elsewhere.
I'm looking to implement a custom implementation of COM in C++ on a UNIX type platform to allow me to dynamically load and link object oriented code. I'm thinking this would be based on a similar set of functionality that POSIX provides to load and call dll's ie dlopen, dlsym and dlclose.
At its simplest level, COM is implemented with interfaces. In c++, if you are comfortable with the idea of pure virtual, or abstract base classes, then you already know how to define an interface in c++
struct IMyInterface {
void Method1() =0;
void Method2() =0;
};
The COM runtime provides a lot of extra services that apply to the windows environment but arn't really needed when implementing "mini" COM in a single application as a means to dynamically link to a more OO interface than traditionally allowed by dlopen, dlsym, etc.
COM objects are implemented in .dll, .so or .dylib files depending on your platform. These files need to export at least one function that is standardized: DllGetClassObject
In your own environment you can prototype it however you want but to interop with the COM runtime on windows obviously the name and parameters need to conform to the com standard.
The basic idea is, this is passed a pointer to a GUID - 16 bytes that uniquely are assigned to a particular object, and it creates (based on the GUID) and returns the IClassFactory* of a factory object.
The factory object is then used, by the COM runtime, to create instances of the object when the IClassFactory::CreateInstance method is called.
So, so far you have
a dynamic library exporting at least one symbol, named "DllGetClassObject" (or some variant thereof)
A DllGetClassObject method that checks the passed in GUID to see if and which object is being requested, and then performs a "new CSomeObjectClassFactory"
A CSomeObjectClassFactory implementation that implements (derives from) IClassFactory, and implements the CreateInstance method to "new" instances of CSupportedObject.
CSomeSupportedObject that implements a custom, or COM defined interface that derives from IUnknown. This is important because IClassFactory::CreateInstance is passed an IID (again, a 16byte unique id defining an interface this time) that it will need to QueryInterface on the object for.
I understand that the general idea of COM is that you link to a few functions ie QueryInterface, AddRef and Release in a common dll (Kernel32.dll) which then allows you to access interfaces which are just a table of function pointers encapsulated with a pointer to the object for which the function pointers should be called with. These functions are exposed through IUnknown which you must inherit off of.
Actually, COM is implemented by OLE32.dll which exposes a "c" api called CoCreateInstance. The app passed CoCreateInstance a GUID, which it looks up in the windows registry - which has a DB of GUID -> "path to dll" mappings. OLE/COM then loads (dlopen) the dll, calls its DllGetClassObject (dlsym) method, passing in the GUID again, presuming that succeeds, OLE/COM then calls the CreateInstance and returns the resulting interface to app.
So how does this all work? Is there a better way to dynamically link and load to object oriented code? How does inheritance from a dll work - does every call to the base class have to be to an exposed member function i.e private/protected/public is simply ignored?
implicit inheritance of c++ code from a dll/so/dylib works by exporting every method in the class as a "decorated" symbol. The method name is decorated with the class, and type of every parameter. This is the same way the symbols are exported from static libraries (.a or .lib files iirc). Static or dynamic libraries, "private, protected etc." are always enforced by the compiler, parsing the header files, never the linker.
I'm quite well versed in C++ and template meta-programming and already have a fully reflective C++ system i.e member properties, member functions and global/static functions that uses boost.
c++ classes can typically only be exported from dlls with static linkage - dlls that are loaded at load, not via dlopen at runtime. COM allows c++ interfaces to be dynamically loaded by ensuring that all datatypes used in COM are either pod types, or are pure virtual interfaces. If you break this rule, by defining an interface that tries to pass a boost or any other type of object you will quickly get into a situation where the compiler/linker will need more than just the header file to figure out whats going on and your carefully prepared "com" dll will have to be statically or implicitly linked in order to function.
The other rule of COM is, never pass ownership of an object accross a dynamic library boundary. i.e. never return an interface or data from a dll, and require the app to delete it. Interfaces all need to implement IUnknown, or at least a Release() method, that allows the object to perform a delete this. Any returned data types likewise must have a well known de-allocator - if you have an interface with a method called "CreateBlob", there should probably be a buddy method called "DeleteBlob".
To really understand how COM works, I suggest reading "Essential COM" by Don Box.
Look at the CORBA documentation, at System.ComponentModel in the sscli, the XPCOM parts of the Mozilla codebase. Miguel de Icaza implemented something like OLE in GNOME called Bonobo which might be useful as well.
Depending on what you're doing with C++ though, you might want to look at plugin frameworks for C++ like Yehia. I believe Boost also has something similar.
Edit: pugg seems better maintained than Yehia at the moment. I have not tried it though.
The basic design of COM is pretty simple.
All COM objects expose their functionality through one or more interfaces
All interfaces are derived from the IUnknown interface, thus all interfaces have
QueryInterface, AddRef & Release methods as the first 3 methods of their virtual
function table in a known order
All objects implement IUnknown
Any interface that an object supports can be queried from any other interface.
Interfaces are identified by Globally Unique Identifiers, these are IIDs GUIDs or CLSIDs, but they are all really the same thing. http://en.wikipedia.org/wiki/Globally_Unique_Identifier
Where COM gets complex is in how it deals with allowing interfaces to be called from outside the process where the object resides. COM marshalling is a nasty, hairy, beast. Made even more so by the fact that COM supports both single threaded and multi-threaded programming models.
The Windows implementaion of COM allows objects to be registered (the original use of the Windows registry was for COM). At a minimum the COM registry contains the mapping between the unique GUID for a COM object, and the library (dll) that contains it's code.
For this to work. DLLs that implement COM objects must have a ClassFactory - an entry point in the DLL with a standard name that can be called to create one of the COM objects the DLL implements. (In practice, Windows COM gets an IClassFactory object from this entry point, and uses that to create other COM objects).
so that's the 10 cent tour, but to really understand this, you need to read Essential COM by Don Box.
You may be interested in the (not-yet)Boost.Extension library.