#import COM DLL generate wrong method signature - c++

I'm writing a C++ application which imports a COM DLL as following,
#import "MyLib.dll" no_namespace, raw_interfaces_only
There is a problem using method '_GetObject' which is declared in the idl file like this,
[
object,
uuid(f022c0e0-1234-5678-abcd-c17d63954f4b),
dual,
nonextensible,
helpstring("IStorageProxy Interface"),
pointer_default(unique)
]
interface IStorageProxy : IDispatch
{
[hidden, helpstring("method _GetObject")]
HRESULT _GetObject(
[in] BSTR entryId,
[in] REFCLSID rclsid,
[in] REFIID riid,
[out, iid_is(riid), retval] IUnknown** stgObject);
};
But the generated tlh file has changed the types of the second and third parameters.
struct __declspec(uuid("f022c0e0-1234-5678-abcd-c17d63954f4b"))
IStorageProxy : IDispatch
{
//
// Raw methods provided by interface
//
virtual HRESULT __stdcall _GetObject (
/*[in]*/ BSTR entryId,
/*[in]*/ GUID * rclsid,
/*[in]*/ GUID * riid,
/*[out,retval]*/ IUnknown * * stgObject ) = 0;
};
As I'm coding against the original function signature (defined in the idl), so now the C++ code can't compile. I'm not sure why the types changed to 'GUID *'. Is there any way to stop the compiler from doing this?

No, that's normal. Both REFGUID and REFIID are just a typedef for GUID*. Same kind of idea as a HWND and HDC, typedefs for HANDLE. These typedefs catch mistakes in C++ code, they are not really appropriate in a type library that supplies typeinfo to many languages.
You could technically keep these typedefs but those types will then have to be defined in the type library as well so that the COM client knows what they mean. The component author would have to include WTypes.idl. That's probably too late by now, you can't do anything about it in a COM client.

Related

Implement COM interface registered in system

How can i implement and extend COM interface registered in system. Let's asume it is delivered with some software, not part of OS.
Should i write IDL first ?
I know Microsoft's ATL samples, but none of them shows what i'm looking for.
For example here is idl for Foxit Reader Control, generated with OleView
[odl,
uuid(62F8A765-322B-41E3-B767-2D057829D66D),
helpstring("IFoxitCtl Interface"),
dual,
oleautomation
]
interface IFoxitCtl : IDispatch {
[id(0x00000001), propget, helpstring("property src")]
HRESULT src([out, retval] BSTR* pVal);
[id(0x00000001), propput, helpstring("property src")]
HRESULT src([in] BSTR pVal);
[id(0x00000002), helpstring("method OpenFile")]
HRESULT OpenFile(BSTR strFilePath);
[id(0x00000003), helpstring("method PrintFile")]
HRESULT PrintFile();
[id(0x00000004), helpstring("method SetProgress")]
HRESULT SetProgress(
int nOffset,
int nSum);
[id(0x00000005), helpstring("method postMesage")]
HRESULT postMessage([in] VARIANT strArray);
[id(0x00000006), propget, helpstring("property messageHandler")]
HRESULT messageHandler([out, retval] VARIANT* pVal);
[id(0x00000006), propput, helpstring("property messageHandler")]
HRESULT messageHandler([in] VARIANT pVal);
};
What should i do to implement this interface?
Notice: i took random interface from registered in OS, if you have working example with any other COM interface please share it
I've tried to use "Implement Interface" feature in visual studio but many interfaces are not available there

Smart pointer to atl com interface

I have an atl-com dll that has an interface IMyInterface. I created a client with #import "Project.tlb" and it was generated the correct Project.tlh and Project.tli. So I included Project.tlb in my client. Now I'm trying to call the IMyInterfacePtr that #import generated like this:
IMyInterfacePtr *i;
CLSID clsid = __uuidof(Test);
REFIID iid = __uuidof(IMyInterfacePtr);
HRESULT hr = CoCreateInstance(clsid, NULL, CLSCTX_INPROC_SERVER, iid, (void**) &i);
So using the pointer to interface:
i->MyMethod();
But it didn't recognize "MyMethod", it's only showing the IDispatch interface that is from which my IMyInterface inherits.
What Am I doing wrong?
Thanks!

Using C++ namespaces in IDL files when declaring interfaces

I have a library written in C++ and I want to use structures from it when declaring interfaces in IDL file. Here is the sample:
service.idl
import "..//core//common_structures.h";
[
object,
uuid(13B01AEB-52EC-4546-BDE0-DE91B37337CE),
dual,
pointer_default(unique)
]
interface IDeviceManagement: IUnknown {
HRESULT GetSerialByIndex ([in] uint8_t id, [out] Serial *serial, [out, retval] VARIANT_BOOL *result);
};
Serial structure is defined in imported header under key_api namespace. When building everything goes ok until service_i.h is generated and the following error appears:
error C2061: syntax error : identifier 'Serial' ..\service\service_i.h
near these generated lines:
IDeviceManagement : public IUnknown
{
public:
virtual HRESULT STDMETHODCALLTYPE GetSerialByIndex(
/* [in] */ uint8_t id,
/* [out] */ Serial *serial,
/* [retval][out] */ VARIANT_BOOL *result) = 0;
};
I think it's because of Serial is wrapped under the namespace and service_i.h doesn't know anything about it. One solution is just to get rid of namespace. Is there any variant when we can actually keep the namespace?

Is there a way with MIDL to turn off C-style headers generation?

I have a simple .IDL file (iface.idl) which describes an IUnknown based interface:
import "unknwn.idl";
[
uuid(80DFDD28-F033-431e-B027-CDD2078FC78A)
]
interface ISunPathCalc : IUnknown {
HRESULT Square([in, out] long * pVal);
HRESULT Cube([in, out] long * pVal);
};
When trying to compile it with midl /header iface.h iface.idl I'm getting 3 files: iface.h, iface_i.c and iface_p.c. The iface.h file contains a C++ declaration of ISunpathCalc interface:
#if defined(__cplusplus) && !defined(CINTERFACE)
MIDL_INTERFACE("80DFDD28-F033-431e-B027-CDD2078FC78A")
ISunPathCalc : public IUnknown
{
public:
virtual HRESULT STDMETHODCALLTYPE Square(
/* [out][in] */ long *pVal) = 0;
virtual HRESULT STDMETHODCALLTYPE Cube(
/* [out][in] */ long *pVal) = 0;
};
#else /* C style interface */
The remaining larger part of this file contains needless C stuff.
Q: Is there way to tell MIDL to generate only C++ part of header?
Is it possible to switch off generation of iface_i.c and iface_p.c files and to force MIDL to generate a C++ definition instead?
UPD1:
I tried to add [local] attribute as specified here:
[
local,
uuid(80DFDD28-F033-431e-B027-CDD2078FC78A)
]
but without any success.
Unfortunately there's no way of suppressing the C header generation.

How to specify user defined type parameters in COM interface definition?

One of my COM interface methods needs a parameter of user defined type as below:
[uuid(58ADDA77-274B-4B2D-B8A6-CAB5A3907AE7), object] //Interface
interface IRadio : IUnknown
{
...
HRESULT test_method2(someUDT* p2p_UDT);
...
};
How could fit the definition of the someUDT in the *.idl file? The someUDT type is a user defined struct.
Thanks.
Perhaps this helps you - it's german but the most interesting part is the code.
This is how a Struct is defined there:
[
uuid(62D33614-1860-11d3-9954-10C0D6000000),
version(1.0)
]
typedef struct TPerson
{
BSTR bstrFirstname;
BSTR bstrLastname;
long lAge;
TDepartment Dep;
} TPerson;
// Interface
This is how it is used later:
[
object,
uuid(FC126BCD-1EAC-11D3-996A-4C1671000000),
dual,
helpstring("ICMyUDT Interface"),
pointer_default(unique)
]
interface ICMyUDT : IDispatch
{
[id(1), helpstring("method PassUdtByRef")] HRESULT
PassUdtByRef([ref, in, out] TPerson* pPerson);
[id(2), helpstring("method ReturnUdt")] HRESULT ReturnUdt(
[out, retval] TPerson* pPerson);
[id(3), helpstring("method PassUdtByVal")] HRESULT
PassUdtByVal([in] VARIANT varPerson);
};
I think that you need to define the struct in the idl file. Something like:
[
uuid("..."),
v1_enum,
helpstring("Enum")
]
typedef enum MyEnum {
value_a,
value_b,
value_c
} MyEnum_t;