What does the ISupportErrorInfo interface mean? I'm at a bit of a loss to understand it. From MSDN:
This interface ensures that error
information can be propagated up the
call chain correctly. Automation
objects that use the error handling
interfaces must implement
ISupportErrorInfo.
This method indicates whether or not
an interface supports the IErrorInfo
interface.
HRESULT InterfaceSupportsErrorInfo(
REFIID riid
);
What does it mean to return S_OK in InterfaceSupportsErrorInfo? Should you return S_OK for all interfaces? Just some?
My understanding of it (based on some related MSDN pages) is that by implementing ISupportErrorInfo, you are indicating that one or more interfaces on your class returns error information by calling SetErrorInfo, as opposed to just returning a failure HRESULT.
To that end, your implementation of ISuportErrorInfo::InterfaceSupportsErrorInfo should return S_OK only for those interfaces on your class that actually use SetErrorInfo to return error information to the caller, and only those interfaces.
For example, say you have a class that implements an interface you wrote called IFoo that has a DoSomething method. If someone else creates an instance of your class and calls IFoo::DoSomething, they are supposed to do the following if DoSomething returns a failure HRESULT (paraphrasing from various MSDN pages, but I started from here: http://msdn.microsoft.com/en-us/library/ms221510.aspx):
Call QueryInterface on the IFoo pointer to get the ISupportErrorInfo interface for the object that is implementing IFoo
If the called object doesn't implement ISupportErrorInfo,
then the caller will have
to handle the error based on the
HRESULT value, or pass it up the call stack.
If the called object does implement ISupportErrorInfo, then the caller should call ISupportErrorInfo::InterfaceSupportsErrorInfo, passing in a REFIID for the interface that returned the error. In this case, the DoSomething method of the IFoo interface returned an error, so you would pass REFIID_IFoo (assuming it's defined) to InterfaceSupportsErrorInfo.
If InterfaceSupportsErrorInfo
returns S_OK, then the caller
knows at this point that it can
retrieve more detailed information
about the error by calling
GetErrorInfo. If InterfaceSupportsErrorInfo returns S_FALSE, the caller can assume the called interface doesn't supply detailed error information, and will have to rely on the returned HRESULT to figure out what happened.
The reason for this somewhat confusing/convoluted error-handling API seems to be for flexibility (as far I as I can tell anyway. This is COM after all ;). With this design, a class can support multiple interfaces, but not every interface is required to use SetErrorInfo to return error information from its methods. You can have certain, select interfaces on your class return detailed error information via SetErrorInfo, while other interfaces can continue to use normal HRESULTs to indicate errors.
In summary, the ISupportErrorInfo interface is a way to inform the calling code that at least one of the interfaces your class implements can return detailed error information, and the InterfaceSupportsErrorInfo method tells the caller whether a given interface is one of those interfaces. If so, then the caller can retrieve the detailed error information by calling GetErrorInfo.
Related
During the course of Tour of Go, the following extract is presented but I couldn't make much meaning of it (guess I'm lacking in OOP knowledge).
An interface in Go is defined as a set of method signatures. In Go interfaces are implicit. So there is no need to define on a given type that it implements a certain interface. The advantage of this is that the definition of an interface is decoupled from its implementation which could then appear in any package without prearrangement.
How is decoupling a definition of an interface from its implementation advantageous? My initial thought is that this approach greatly reduces the 'rigidity' (aka significance) of interfaces.. is it just syntactic-sugar and things actually "work as normal" under the hood?
Thank you for your time.
This is called "duck typing", and it allows interfaces to be defined where they are needed, instead of as part of the data type itself. Consider the following type:
type X struct {...}
func (X) f()
func (X) g()
func (X) h()
The type X has three methods, f(), g(), h(). If you have a data structure or function that needs to call a f() method, you can define an interface:
type FIntf interface {
f()
}
and now X implements that interface. You can pass instances of X wherever FIntf is needed.
If, in another module you need g() and h(), you can define an interface there:
type GIntf interface {
g()
h()
and now X implements GIntf.
This is especially useful if you have a third-party library that doesn't implement the interfaces you need. You can simply define an interface where you use it, and use the third-party types with the correct method set implement your interface.
The main advantage of this method is that you can still emulate the traditional notion of interfaces where you define an interface and a concrete implementation of it. On top of that, you have the flexibility to define different interfaces as you need them without modifying the implementation. In a language like Java, if you have a function that gets a certain interface and if your object doesn't, you have to write an adapter even though the method set exists on the original type. In Go, you don't need to do that.
Duck typing also allows for type-safety when it comes to calling methods. For instance, if you have a function that has to call method x() and y() of one of its arguments, define an interface containing x() and y(), and use a type assertion to validate the argument implements those two methods.
MSDN:
"You implement an IClassFactory interface for each (COM) class of object that you offer to be instantiated."
Is it useful to create COM class without Class Factory?
The IClassFactory is provided for objects which are instantiated directly by the caller, for example using CreateObject or CoCreateInstance, or GetObject.
Other objects can be obtained by getting them indirectly from objects that are created.
For example, the Scripting.FileSystemObject in VB or VBScript is created directly. You can use the methods to obtain File or Folder objects, which cannot be directly created. Instead these are created by the FileSystemObject and returned from FileSystemObject methods.
Is it useful to create COM class without Class Factory?
Yes, why not? It can still be fully featured COM class, just except that you cannot launch it via CoCreateInstance API. For some reason you might want to make it available otherwise, e.g. as a returned [out] parameter on a method of another interface/class, or via GetActiveObject API.
Class factories let you expose your class for direct instantiation.
I'm not entirely sure the wording is quite correct here. You almost always implement IClassFactory once for all COM classes of objects that your host will instantiate. In particular, your implementation of IClassFactory is what gets returned from DllGetClassObject.
In particular, when someone calls CoCreateInstance(CLSID_foo, pUnkOuter, CLSCTX_INPROC, IID_IFoo, (void **) &pFoo), the following things happen (assuming you're not doing remoting):
COM looks up CLSID_foo in the registry. (In particular, HKEY_CLASSES_ROOT\CLSID\\InprocServer32).
COM loads that DLL and calls DllGetClassObject with IID_IClassFactory.
Your DLL returns a function pointer to the implementation of IClassFactory.
COM calls your implementation of IClassFactory::CreateInstance with pUnkOuter, IID_IFoo, and pFoo.
There are many other situations where you would have COM objects that aren't directly creatable, as #Ben mentioned. There are even other standard factory interfaces, like IServiceProvider, that exist so that classes can expose a dynamic set of interfaces.
I am building an automation interface for an existing application. After implementing a DLL server and an EXE server (mainly for getting familiar with the basics of COM) I am now at the point where I generate a type library from an IDL file and can, for example, basically automate my application from VBScript:
Set oApp = CreateObject("MyApp.1")
oApp.ShowAboutBox()
This simple call to a function that takes no parameters works. The next step I want to take is call a function that takes a parameter.
The signature of the function in the IDL file is
HRESULT CreateSomeChildWindow([out, retval] MyChildWindow** ppChildWindow);
and in VBScript I assume it would be
Dim oWnd As MyChildWindow
oWnd = oApp.CreateSomeChildWindow()
This call already works in C++ although MyChildWindow is not currently registered as a COM object in the registry. The reason MyChildWindow doesn't need to be registered is that CreateSomeChildWindow simply returns the interface pointer to the created MyChildWindow object in a parameter. And the reason it isn't registered is that I want to avoid redundancy, and also I don't want MyChildWindow to be instantiated directly (e.g. by calling CreateObject in VBScript).
Question:
Now I'm trying to find out whether it will be necessary to register MyChildWindow after all. Is my assumption correct that in order to call CreateSomeChildWindow in VBScript
I need to write Dim oWnd As MyChildWindow
For this to work, MyChildWindow must be registered
And if the answer to that is yes, hopefully clients still can't MyChildWindow directly, since I don't implement a class object for it? Or will I have to implement a class object?
Your out/retval is not an object (on the scripting side), it is an interface pointer. And since the method CreateSomeChildWindow is on IDL, in type library, in registered type library - scripting/automation is aware of interface definition, such as methods etc, because the whole type library is already registered. You are already well set, no additional registration required.
When caller receives an interface pointer, it does not care what object the pointer belongs to. Interface pointer alone is good enough, and scripting/automation environment known how to deal with it.
On the callee side however, you need to return an interface pointer, and you are dealing with objects. So you need some class which implements this interface and you return this object's interface.
I'm writing a COM object that provides access to a service that must be explicitly connected before calls can succeed.
Is there a generic HRESULT code that describes that the callee object is in a state where it is unprepared to handle calls, ideally with the implication that this is the caller's fault?
Currently I'm using E_FAIL, which is too generic for my taste; OLE_E_BLANK might be an option, however this is not an OLE object and I'd rather not return a confusing error code.
I would suggest that E_NOT_VALID_STATE would be closest to what you want to convey.
But, as Hans says, implement IErrorInfo to give chapter and verse.
C++/CLI helpfully generates the IDisposable scaffolding for you when you implement a destructor on a ref class. Also, if you don't implement a destructor, but your class has a member variable which implements IDisposable, then IDisposable is again automatically implemented on your class. It's pretty helpful and much better than how IDisposable is handled in C#.
I have run into this behaviour when implementing a ref class that holds onto an msclr::com::ptr (a smart pointer that contains an RCW).
ref class Test /* : IDisposable added by the compiler */
{
msclr::com::ptr<IWhatever> _aComObject;
}
In my specific case, the COM object referenced by my class doesn't 'lock' some unmanaged resource, it effectively just uses up a bit of unmanaged memory that the CLR can't see. Therefore I would like to avoid confusing the users of my ref class by not implementing IDisposable the class. Instead I want to make the CLR aware of the existence of the COM object by using the GC API to add the appropriate memory pressure.
So, the question is: is there a way to suppress implementation of IDisposable on a ref class that doesn't implement a destructor, but does hold an IDisposable member variable?
NB: often this would be the wrong thing to do, as it would prevent users of the class from deterministically disposing of the underlying COM object, but given the particular circumstances, exposing IDisposable has the potential to confuse users of my ref class, since it really is not necessary to Dispose of the ref class in question.
I suppose one option would be to implement a variant of msclr::com::ptr without a destructor.
Any other method to suppress the automatic addition of IDisposable would be appreciated. Thanks.
Answer
Declare _aComObject as a handle to an msclr::com::ptr (msclr::com::ptr<IWhatever>^). The compiler does not then regard Test as being the 'owner' of the com ptr object, and does not Dispose it when Test is deleted.
I think the answer is to hold a handle to the msclr::com::ptr rather than holding it 'by value' (which is still holding it as a handle 'behind the scenes', except the C++CLI compiler treats it as a value - 'deleting' it (calling Dispose) when the owner object is deleted (Disposed)).
I'm not sure I agree with the ratioanle for avoiding the IDispose implementation -- but why not just store an IWhatever* in your class. The compiler shouldn't then generate the IDisposable implementation.
If you don't want the destructor behaviour then what benefit is the com::ptr wrapper buying you? You can always declare an com::ptr on the stack and assign your member pointer to it in any given method if you really need it.