This is my first attempt to use COM. I am trying to use COM functions in a DLL made by someone else. I wrote the code below just for testing, it should just display an aboutbox of the DLL:

invoke CoInitialize,NULL
invoke CoCreateInstance,addr CLSID_IfcServer,NULL,CLSCTX_INPROC_SERVER,addr IID_IIfcServer,addr pIfcServer
coinvoke pIfcServer,IIfcServer,About
invoke CoUninitialize

The CoCreateInstance seems to be working. However, the coinvoke crashes the program. My guess is that i am just passing a wrong argument somewhere or have some other simple error, i just can't find it.

I traced the coinvoke part with a debugger and it compiles to this:
mov edx,
mov edx,
push dword ptr
call ;this will screw things up (points to totally wrong address?)

I have the following defined in .data section:

DeclareGuid CLSID_IfcServer
DeclareGuid IID_IIfcServer
pIfcServer dword 0


I made an INC file from the appropriate TLB file with Tlb2Inc.exe. This is the relevent part of it:

;CoClass : IfcServer
;~~~~~~~~~~~~~~~~~
;{0D2BA2E1-6CE5-11D3-A74D-00104BF20ED3}
sCLSID_IfcServer TEXTEQU <{00D2BA2E1H, 06CE5H, 011D3H, {0A7H, 04DH, 000H, 010H, 04BH, 0F2H, 00EH, 0D3H}}>

;DispInterface : IIfcServer
;~~~~~~~~~~~~~~~~~~~~~~
;{0D2BA2E0-6CE5-11D3-A74D-00104BF20ED3}
sIID_IIfcServer TEXTEQU <{00D2BA2E0H, 06CE5H, 011D3H, {0A7H, 04DH, 000H, 010H, 04BH, 0F2H, 00EH, 0D3H}}>

IIfcServer_GetSpacesProto typedef proto IIfcServer_GetSpacesProto :DWORD
IIfcServer_ReadIfcFileProto typedef proto IIfcServer_ReadIfcFileProto :DWORD,:DWORD
IIfcServer_ReadIfcHeaderProto typedef proto IIfcServer_ReadIfcHeaderProto :DWORD,:DWORD
IIfcServer_GetWallsProto typedef proto IIfcServer_GetWallsProto :DWORD
IIfcServer_GetProjectProto typedef proto IIfcServer_GetProjectProto :DWORD
IIfcServer_SaveIfcFileProto typedef proto IIfcServer_SaveIfcFileProto :DWORD
IIfcServer_GetLastErrorMessageProto typedef proto IIfcServer_GetLastErrorMessageProto :DWORD
IIfcServer_FindSpaceProto typedef proto IIfcServer_FindSpaceProto :DWORD,:REAL8,:REAL8
IIfcServer_AboutProto typedef proto IIfcServer_AboutProto :DWORD
IIfcServer_GetObjectProto typedef proto IIfcServer_GetObjectProto :DWORD,:DWORD
IIfcServer_GetPreferenceProto typedef proto IIfcServer_GetPreferenceProto :DWORD
IIfcServer_CreateNewProxyProto typedef proto IIfcServer_CreateNewProxyProto :DWORD
IIfcServer_GetBuildingStoreysProto typedef proto IIfcServer_GetBuildingStoreysProto :DWORD
IIfcServer_CreateSimplifiedGeometryProto typedef proto IIfcServer_CreateSimplifiedGeometryProto :DWORD,:DWORD
IIfcServer_GetBuildingPartsBetweenSpacesProto typedef proto IIfcServer_GetBuildingPartsBetweenSpacesProto :DWORD,:DWORD,:DWORD
IIfcServer_CreateNewTableProto typedef proto IIfcServer_CreateNewTableProto :DWORD
IIfcServer_GetTablesProto typedef proto IIfcServer_GetTablesProto :DWORD
IIfcServer_GetIfcSchemaProto typedef proto IIfcServer_GetIfcSchemaProto :DWORD

IIfcServer_GetSpacesVal typedef ptr IIfcServer_GetSpacesProto
IIfcServer_ReadIfcFileVal typedef ptr IIfcServer_ReadIfcFileProto
IIfcServer_ReadIfcHeaderVal typedef ptr IIfcServer_ReadIfcHeaderProto
IIfcServer_GetWallsVal typedef ptr IIfcServer_GetWallsProto
IIfcServer_GetProjectVal typedef ptr IIfcServer_GetProjectProto
IIfcServer_SaveIfcFileVal typedef ptr IIfcServer_SaveIfcFileProto
IIfcServer_GetLastErrorMessageVal typedef ptr IIfcServer_GetLastErrorMessageProto
IIfcServer_FindSpaceVal typedef ptr IIfcServer_FindSpaceProto
IIfcServer_AboutVal typedef ptr IIfcServer_AboutProto
IIfcServer_GetObjectVal typedef ptr IIfcServer_GetObjectProto
IIfcServer_GetPreferenceVal typedef ptr IIfcServer_GetPreferenceProto
IIfcServer_CreateNewProxyVal typedef ptr IIfcServer_CreateNewProxyProto
IIfcServer_GetBuildingStoreysVal typedef ptr IIfcServer_GetBuildingStoreysProto
IIfcServer_CreateSimplifiedGeometryVal typedef ptr IIfcServer_CreateSimplifiedGeometryProto
IIfcServer_GetBuildingPartsBetweenSpacesVal typedef ptr IIfcServer_GetBuildingPartsBetweenSpacesProto
IIfcServer_CreateNewTableVal typedef ptr IIfcServer_CreateNewTableProto
IIfcServer_GetTablesVal typedef ptr IIfcServer_GetTablesProto
IIfcServer_GetIfcSchemaVal typedef ptr IIfcServer_GetIfcSchemaProto

_vtIIfcServer MACRO CastName:REQ
; IDispatch methods
_vtIDispatch CastName
; IIfcServer methods
&CastName&_GetSpaces IIfcServer_GetSpacesVal ?
&CastName&_ReadIfcFile IIfcServer_ReadIfcFileVal ?
&CastName&_ReadIfcHeader IIfcServer_ReadIfcHeaderVal ?
&CastName&_GetWalls IIfcServer_GetWallsVal ?
&CastName&_GetProject IIfcServer_GetProjectVal ?
&CastName&_SaveIfcFile IIfcServer_SaveIfcFileVal ?
&CastName&_GetLastErrorMessage IIfcServer_GetLastErrorMessageVal ?
&CastName&_FindSpace IIfcServer_FindSpaceVal ?
&CastName&_About IIfcServer_AboutVal ?
&CastName&_GetObject IIfcServer_GetObjectVal ?
&CastName&_GetPreference IIfcServer_GetPreferenceVal ?
&CastName&_CreateNewProxy IIfcServer_CreateNewProxyVal ?
&CastName&_GetBuildingStoreys IIfcServer_GetBuildingStoreysVal ?
&CastName&_CreateSimplifiedGeometry IIfcServer_CreateSimplifiedGeometryVal ?
&CastName&_GetBuildingPartsBetweenSpaces IIfcServer_GetBuildingPartsBetweenSpacesVal ?
&CastName&_CreateNewTable IIfcServer_CreateNewTableVal ?
&CastName&_GetTables IIfcServer_GetTablesVal ?
&CastName&_GetIfcSchema IIfcServer_GetIfcSchemaVal ?

ENDM

IIfcServer STRUCT
_vtIIfcServer IIfcServer
IIfcServer ENDS


Thanks for any help.
Posted on 2003-06-20 17:28:53 by Janne
Hi Janne

code looks good, cant see any error. Are you sure CoCreateInstance returns S_OK (=0)?

since this server uses typeinfo, you also may use comview to test it (comview uses IDispatch::Invoke to call methods, not vtable calls, but vtable will be shown).

japheth
Posted on 2003-06-21 00:52:51 by japheth
Thanks, Japheth

The CoCreateInstance does return 0.

When I use Comview's "Create Instance" it shows two interfaces, Iunknown and IDispatch. When i select IDispatch and "View VTable", it displays entries 0 - 6. Now im kinda confused because i don't know

- what is the purpose of IDispatch interface
- what are the methods of IDispatch
- where is the IIfcServer interface and its methods
Posted on 2003-06-21 02:37:32 by Janne
IDispatch is the root interface of Automation, or any program that accepts late binfing for scripting. Your IIfcServer interface inherits from it.

I've never used Comview, so I couldn't tell you if it is properly reporting the interface or just up chucking some bug.

what I do see in the definition you have for IIfcServer looks wrong. It lacks any parameters, and every method has at least one (the THIS parameter). This is the part with the &castname& prefix, and you don't need the typedef protos.

The code section starting with "_vtIIfcServer MACRO CastName:REQ" creates a structure for the interface definitions, without any methods there all bets are off (If you're using my colib stuff then coinvoke is looking for the wrong count of parameters)

Just for a giggle, try something simple with the interface that HAS to work, like a paired AddRef and Release, or even Queryinterface it for IIfcServer.


Good luck
Posted on 2003-06-21 09:51:51 by Ernie
Hi Janne

Comview will scan an object for interfaces it founds in HKEY_CLASSES_ROOT\Interface. For automation objects like your dll, the interface inheriting from IDispatch should be inserted there with its IID (00D2BA2E0H, 06CE5H, 011D3H, ...). If it is not, comview will not show it (same behaviour as OLEView).

So if this interface isnt shown, something is wrong, perhabs type library isnt registered properly

Ernie

what I see from Jannes first post
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
mov edx,
mov edx,
push dword ptr
call ;this will screw things up (points to totally wrong address?)
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
is that the called method HAS this pointer, so its possibly not the problem

Japheth
Posted on 2003-06-21 10:45:37 by japheth
Thanks for the replies.

Japheth, you guessed right, the typelib was'nt registered, so i used Comview to register it. Now both Comview and oleview display also the IIfcServer interface.

However, the problem still remains, the program crashes.

Looking with Comview, i see that IIfcServer and IDispatch Vtables are identical. Maybe IIfcServer is a "dispatchonly" interface? Is there any sure way checking if this is the case?

Ernie, i tested the AddRef / Release,they seem to be working. AddRef returned 2, Release returned 1.
Posted on 2003-06-21 12:10:40 by Janne
Janne,

to check if methods may be called via vtable open type library with comview, the interface typeinfo should be marked as DUAL and all methods should have a vtable offset.
But since comview doesn't show any differences between IIfcServer and IDispatch, I guess there is a problem. vtable of IIfcServer should contain all methods (with its names, not just numbers) if it is a real dual interface.

Japheth
Posted on 2003-06-22 01:14:44 by japheth
Hi again,

i attached an image about what Comview tells about the typelib.

I thought i'd try to access the methods with IDispatch::Invoke. Then i saw that Comview can help in that, too. So i used Comviews "create dispatch helper" function and included also the .inc files that come with Comview. Then i commented out my own COM related code and tried to build the project.

I'm using masm32v8, so after i replaced windows.inc 1.25e with 1.25a i got the project to assemble. But the link keeps giving me the error

error LNK2001: unresolved external symbol _GUID_NULL

I tried to build using several different versions of uuid.lib, but the error is always the same. Any ideas?
Posted on 2003-06-22 09:33:53 by Janne
Hi Janne,

for some problems (and workaround) with MASM32 V8 look here

An excerpt from WebBrowserApp MAP file shows:

0002:00000058 __imp__CoInitialize@4 00402058 ole32:ole32.dll
0002:0000005c __imp__CoCreateInstance@20 0040205c ole32:ole32.dll
0002:00000060 __imp__CLSIDFromProgID@8 00402060 ole32:ole32.dll
0002:00000064 \177ole32_NULL_THUNK_DATA 00402064 ole32:ole32.dll
0002:000001d0 _GUID_NULL 004021d0 uuid:cguid_i_guid0.obj
0002:000001e0 _IID_IUnknown 004021e0 uuid:unknwn_i_guid0.obj
0002:000001f0 _IID_IDispatch 004021f0 uuid:oaidl_i_guid4.obj
0002:00000200 _IID_IConnectionPointContainer 00402200 uuid:ocidl_i_guid3.obj
0002:00000210 __IMPORT_DESCRIPTOR_KERNEL32 00402210 kernel32:KERNEL32.dll
0002:00000224 __IMPORT_DESCRIPTOR_USER32 00402224 user32:USER32.dll
0002:00000238 __IMPORT_DESCRIPTOR_ole32 00402238 ole32:ole32.dll
0002:0000024c __IMPORT_DESCRIPTOR_OLEAUT32 0040224c oleaut32:OLEAUT32.dll
0002:00000260 __NULL_IMPORT_DESCRIPTOR 00402260 kernel32:KERNEL32.dll

so GUID_NULL should be defined in UUID.LIB, but you may define it at your own, presumably
its just the same as IID_NULL, that are 16 NULL bytes.
Posted on 2003-06-22 13:14:54 by japheth
After i added to .data

GUID_NULL GUID {000000000H,00000H,00000H,{000H,000H,000H,000H,000H,000H,000H,000H}}

the project links just fine. My COM test code works too, now using IDispatch:

invoke CoCreateInstance,addr CLSID_IfcServer,NULL,CLSCTX_INPROC_SERVER,addr IID_IIfcServer, addr pIfcServer

invoke dm(pIfcServer,IIfcServer,About)

So Japheth, thanks a lot for your help and making the Comview, which is a great tool for this COM stuff.
Posted on 2003-06-22 17:07:30 by Janne
Yet another question, i'm still dealing with the same DLL.

For example, this is in the asm include created by Comview:

;--- IIfcSpace, Type=DISPATCH, GUID={0D2BA2E3-6CE5-11D3-A74D-00104BF20ED3}

;DISPID_Code EQU 01h
;DISPID_Name EQU 02h
;DISPID_Type EQU 03h
;DISPID_Area EQU 04h
;DISPID_Volume EQU 05h
;DISPID_Perimeter EQU 06h
;DISPID_VentilationAirFlowrate EQU 07h
;DISPID_TotalHeatGain EQU 08h
;DISPID_TotalHeatLoss EQU 09h
;DISPID_HeatingDesignTemperature EQU 0Ah
;DISPID_CoolingDesignTemperature EQU 0Bh
;DISPID_ExhaustAirFlowrate EQU 0Ch

;--- dispinterface only
ifndef IIfcSpaceVtbl
BEGIN_INTERFACE IIfcSpace, IDispatch
DISPMETHOD GetGUID , :ptr BSTR
DISPMETHOD GetBorder , :ptr LPDISPATCH
DISPMETHOD GetInstance , :ptr SDWORD
DISPMETHOD GetWalls , :ptr LPDISPATCH
DISPMETHOD GetAdjacentSpaces , :ptr LPDISPATCH
DISPMETHOD GetOwnerHistory , :ptr LPDISPATCH
DISPMETHOD GetAxis2Placement3d , :ptr LPDISPATCH
DISPMETHOD GetFloor , :ptr LPDISPATCH
DISPMETHOD GetRoofSlab , :ptr LPDISPATCH
END_INTERFACE
endif

sIID_IIfcSpace textequ <IID {00D2BA2E3h,06CE5h,011D3h,{0A7h,04Dh,000h,010h,04Bh,0F2h,00Eh,0D3h}}>


and this in the Dispatch helper

;--- IIfcSpace, Type=DISPATCH, GUID={0D2BA2E3-6CE5-11D3-A74D-00104BF20ED3}

DEFINE_DISPMETHOD IIfcSpace , GetGUID, 0Dh, METHOD, VT_BSTR
DEFINE_DISPMETHOD IIfcSpace , GetBorder, 0Eh, METHOD, VT_DISPATCH
DEFINE_DISPMETHOD IIfcSpace , GetInstance, 0Fh, METHOD, VT_I4
DEFINE_DISPMETHOD IIfcSpace , GetWalls, 010h, METHOD, VT_DISPATCH
DEFINE_DISPMETHOD IIfcSpace , GetAdjacentSpaces, 011h, METHOD, VT_DISPATCH
DEFINE_DISPMETHOD IIfcSpace , GetOwnerHistory, 012h, METHOD, VT_DISPATCH
DEFINE_DISPMETHOD IIfcSpace , GetAxis2Placement3d, 013h, METHOD, VT_DISPATCH
DEFINE_DISPMETHOD IIfcSpace , GetFloor, 014h, METHOD, VT_DISPATCH
DEFINE_DISPMETHOD IIfcSpace , GetRoofSlab, 015h, METHOD, VT_DISPATCH


so, if i got it right, the dispatch macros in Comview includes work with methods only? Not when getting / setting properties (Code, Name etc for this interface)?
Posted on 2003-07-01 17:04:22 by Janne
so, if i got it right, the dispatch macros in Comview includes work with methods only? Not when getting / setting properties (Code, Name etc for this interface)?


I've never used Comview, but in gereral a property is actually just a method.

VB established the concept of an object having both methods and properties to make it easier on the developer to keep re-use an object, but a property to VB is implimented in COM by having a pair of methods to get and set some property (or just one or the other, example a read only property only had a get method).

So properties are really methods.
Posted on 2003-07-02 00:00:25 by Ernie
If I remember correctly, comview should add prefixes "get_" and "put_" to PROPERTY_GET and PROPERTY_PUT "methods" names. Thats the whole difference.

So theres an excerpt of an interface with properties created by comview



DEFINE_DISPMETHOD IAsmClass , put_Value, 00h, PROPERTYPUT, , VT_I4
DEFINE_DISPMETHOD IAsmClass , get_Value, 00h, PROPERTYGET, VT_I4
DEFINE_DISPMETHOD IAsmClass , Raise, 01h, METHOD, , VT_USERDEFINED,VT_BYREF OR VT_VARIANT,VT_VARIANT,VT_I4
DEFINE_DISPMETHOD IAsmClass , put_ForeColor, 0FFFFFDFFh, PROPERTYPUT, , VT_USERDEFINED
DEFINE_DISPMETHOD IAsmClass , get_ForeColor, 0FFFFFDFFh, PROPERTYGET, VT_USERDEFINED
DEFINE_DISPMETHOD IAsmClass , put_BackColor, 0FFFFFE0Bh, PROPERTYPUT, , VT_USERDEFINED
DEFINE_DISPMETHOD IAsmClass , get_BackColor, 0FFFFFE0Bh, PROPERTYGET, VT_USERDEFINED
DEFINE_DISPMETHOD IAsmClass , put_ClientEdge, 02h, PROPERTYPUT, , VT_I2
DEFINE_DISPMETHOD IAsmClass , get_ClientEdge, 02h, PROPERTYGET, VT_I2
DEFINE_DISPMETHOD IAsmClass , AboutBox, 0FFFFFDD8h, METHOD,
Posted on 2003-07-02 01:24:01 by japheth
For some reason, Comview did not create in Dispatch helper the lines for any of the properties, just for the methods. But when i add the lines there manually, for example

DEFINE_DISPMETHOD IIfcSpace , get_Code, 01h, PROPERTYGET, VT_BSTR

getting a property with

invoke dm(pSpace,IIfcSpace,get_Code),addr Code

works OK.
Posted on 2003-07-02 13:55:52 by Janne
Check your preferences in the ComView tool. I remember a while ago i had something similar until Japheth pointed out there is check box options to filter out some conversions.

Hope it helps (didnt read the entire thread thru)
:NaN:
Posted on 2003-07-02 17:10:13 by NaN
Janne,

thats possibly an error. I will check this.

>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

Just checked it with excel typelib, dispinterface Style:

;--- Style, Type=DISPATCH, GUID={00020852-0000-0000-C000-000000000046}

DEFINE_DISPMETHOD Style , get_Application, 094h, PROPERTYGET, VT_BYREF OR VT_USERDEFINED
DEFINE_DISPMETHOD Style , get_Creator, 095h, PROPERTYGET, VT_USERDEFINED
DEFINE_DISPMETHOD Style , get_Parent, 096h, PROPERTYGET, VT_DISPATCH
DEFINE_DISPMETHOD Style , get_AddIndent, 0427h, PROPERTYGET, VT_BOOL
DEFINE_DISPMETHOD Style , put_AddIndent, 0427h, PROPERTYPUT, , VT_BOOL
DEFINE_DISPMETHOD Style , get_BuiltIn, 0229h, PROPERTYGET, VT_BOOL
DEFINE_DISPMETHOD Style , get_Borders, 01B3h, PROPERTYGET, VT_BYREF OR VT_USERDEFINED
DEFINE_DISPMETHOD Style , Delete, 075h, METHOD, VT_VARIANT
DEFINE_DISPMETHOD Style , get_Font, 092h, PROPERTYGET, VT_BYREF OR VT_USERDEFINED

Seems to work as it should. So the error reported by Janne looks mysterious to me.

Janne, please post your .TLB file (if its not too big, else email it).
Posted on 2003-07-03 01:44:01 by japheth
here's the TLB
Posted on 2003-07-03 02:29:21 by Janne
Thanks Janne,

I see the problem now. Properties of these interfaces are implemented as variables, not functions, which is pretty rare.

I changed comview to support this case and it may be downloaded from here.
Its a preliminary version, please tell about any problems arising.

Japheth
Posted on 2003-07-03 05:22:49 by japheth
Hi,
now the PROPERTYGETs seem to be OK, but the PROPERTYPUTs are still missing?
Posted on 2003-07-03 06:57:50 by Janne
Just updated, now PROPPUTs should be there as well. Use link above.
Posted on 2003-07-03 08:11:52 by japheth