HRESULT 0x80004005 E_FAIL

HRESULT 0x80004005 E_FAIL

This is a brief description of the project.

Contains of two libraries, one containing interfaces, other containing coclasses, COM visible.

Used Module Wizard to create modules out of these libraries.

Created COM objects using CLSIDs provided. Two methods from different objcts worked fine, but it brakes at third method that is no different than these two. This is the error I get:

"Unspecified error (Exception from HRESULT: 0x80004005 (E_FAIL))"

I found that program goes inside the correct .f90 file, finds the right description of a method, but after viewing the Log file, I saw that program never enters the actual function. This is the part of the code which returns the error.

INTEGER(4) FUNCTION $IFlash_SetReferenceFluid($OBJECT, ReferenceFluid) IMPLICIT NONE

INTEGER(INT_PTR_KIND()), INTENT(IN) :: ReferenceFluid ! IUnknown
INTEGER(INT_PTR_KIND()) $VTBL ! Interface Function Table
$VPTR = $OBJECT ! Interface Function Table
$VPTR = $VTBL + 9 * INT_PTR_KIND() ! Add routine table offset
IFlash_SetReferenceFluid_PTR = $VTBL
$RETURN = IFlash_SetReferenceFluid($OBJECT, ReferenceFluid)                        !!!!!!!!!!!!!!!!!!!!  THIS LINE RETURNS ERROR   !!!!!!!!!!!!!!!!
$IFlash_SetReferenceFluid = $RETURN
END FUNCTION $IFlash_SetReferenceFluid

Thing is that I created sample programs in VB, C++, C#, HTML and they all work without a problem. I'm using Visual Studio 2010 and Intel Composer XE 2013.

14 posts / 0 new
Last post
For more complete information about compiler optimizations, see our Optimization Notice.

This is the code produced by the Module Wizard? The code I've generated in my cases doesn't explicitly use $VPTR and things like "$VPTR = $VTBL + 9 * INT_PTR_KIND() ! Add routine table offset" which contain an explicit offset.

Instead it looks like this

INTEGER(INT_PTR_KIND()) invokeargs
$$STATUS = AUTOINVOKE($OBJECT, 44, invokeargs)
IF ($$STATUS == DISP_E_EXCEPTION) CALL $$DisplayError(invokeargs)

Using the IVF routines for COM. In my example the AUTOINVOKE call has a 44 which corresponds to your offset of 9. Each of the routines of course has a unique offset into the table.

When you start the Module Wizard, there is a checkbox "Generate code that uses Automation interfaces". If you do not check it, you get the code like mine and if you check it, you should get code like yours. Thing is that if I check it, I don't get any methods listed in the module.
Also, if you can make make the code that doesn't use Automation interfaces, you should be able to use it. Well, to some point it works.

So when you go to the Module Wizard it shows up on the COM tab, but if you check the Use Automation Interfaces it doesn't produce any Method calls.

When you look (in the OLE/COM Object Viewer) at the interface you are using, does it show the methods you want to use? When you look at your COM object in that viewer does it show that it supports that interface? Presumably it does, but I'm blathering here because when I've had questions with using COM interfaces I've gotten a dearth of responses.

How are you getting your Object value that you are using? If it's from a dialog window, and that window has closed when you get to using this particular method, then the Object will no longer be valid and you'll get this kind of result. That's my best suggestion for now.

To create objects, I use (for one object, similar for all others)

CALL COMCreateObjectByGUID(CLSID_FluidDepoWaxDataLayer, CLSCTX_ALL, IID_IFluidDepoWaxDataLayer, FluidDatalayerPtr, Status)

with CLSID and IID provided in the module. As I said in the first message, I can access all the properties, and I can ran two methods, but the program crashes with this one.

Class does support this interface, but I can't see if the interface has this function, because OLE/COM viewer comes with a message
"IDataObject interface viewer only supports IID_IdataObject"

But because VB sample works (and C++, C#, HTML), and uses these methods and classes, this is a very peculiar problem.

regarding the viewer:
If the OLE/COM viewer lists the interface for your Object when you expand it, then it is supposed to support that interface. If you look below the Objects in the Type Libraries section and locate the type for your object and double click on that, it will open the ITypeLib Viewer which will show dispinterfaces and coclasses for your type. If you expand your dispinterface that your trying to use on the left, it will list sections for Constants, Properties and Methods. If you expand the Methods section it will show all the methods available using that interface.

You mentioned that you have two methods that work. Is that with the same Object as for the method that gives the error? The error your getting is the same as one gets when the Object is not valid.

Everything in viewer is now fine, there is interface in class's tree, and methods in interface's tree.

Two methods that work are from two different classes, but the one that doesn't work is in the same class as one that works. Those are global objects, no reason for them not to exist. I even put them in the same subroutine, one call after another, and still it doesn't work.

So lets refer to the one that works (of the two of the same class) A and the one that fails F. Have you tried the calls in both orders, A followed by F and then F followed by A. Its the same one that fails both ways? If they are both instances of the same kind of object, and they are both being created and initialized the same way, I'd still look for what could be wrong in the second F object.

I've written applications which use three different COM objects. In two cases the COM objects were ActiveX components, and I resorted to putting them in dialog windows to get them to initialize correctly so that I could use them. In the other case I was able to initialize the COM object without putting it into a dialog window, but I couldn't get the ActiveX objects to initialize in the same way.

I tried that and again it brakes with the same method. So it must be something wrong with it.
But what is the difference between Fortran, VBA and JavaScript, because the latter two also approach through COM and use the same methods and they work.

In my example that wasn't an ActiveX, I had several instances of the same type Object. I used COMCreateObjectByProgID instead of COMCreateObjectByGUID, but that shouldn't make a real difference, certainly not in whether it works. I didn't do anything further before using my objects. Here is that section of code for my example:
do i=1,maxDEV ! get IDispatch for each object
call COMCreateObjectByProgID("DevCntl.Device.1", devOBJ(I), HRES)
if (HRES/=s_OK) exit ! loop, got problem
end do
Did you check the status return to make sure there wasn't a problem with your creation of the second object?

I don't think there's supposed to be any difference based on the language of the application, that's supposed to be the charm of COM.

With my ActiveX examples this approach failed, the status return of the create was nonzero.

Actually, that last about ActiveX is bogus, probably wrong. The one case was my first COM project, and the dialog route was probably just the way I figured out how to get it to work. The other was the second project, and there hasn't been a need to try to rework those since my understanding has improve ever so slightly.

I have set status checks on every object creation and every method call. Zero until this particular method. Something with it is not as it should be, I will keep digging to see what it is. I hoped that this could be some common Fortran error, some parameter you set in Visual Studio and everything suddenly works. But, I guess there is something wrong with the code.

It is not a common problem, but I admit there is very little guidance on using COM from Fortran. But it does seem to be either an issue with the method or the Module Wizard is not generating correct source for dealing with that method. In the latter case, you have the source so you can step through it and see what is going on.

Retired 12/31/2016

We have tried another approach. We merged the two libraries into one dll. So now we can create code that uses automation interfaces, and it works. But there are still few minor bugs that I am not sure of. When the Module Wizard creates a module, only CLSIDs are displayed, but not IIDs. So I have to input them manually into the module or just use ProgIDs to create objects.
Other thing is when I don't use "Generate code that uses Automation interfaces" I still get the same error (but both CLSIDs and IIDs are displayed). But this I can live without.

Leave a Comment

Please sign in to add a comment. Not a member? Join today