COM - [in] parameter as SAFEARRAY(STRUCT) - com

I am able to call a COM interface method using SAFEARRAY(BSTR) as input. If I define instead a simple (containing only some BSTR-s fields) STRUCT to pass into the COM I get
"[System.ArgumentException] = {"The parameter is incorrect. (Exception from HRESULT: 0x80070057 (E_INVALIDARG))"
The call to my COM server is not made because as it seems the arguments from client does not match the expected arguments on server: E_INVALIDARG
Here is my declaration in IDL:
typedef enum UserEntityType
{
User,
Group,
IPAddress
} UserEntityType;
[
uuid(4786F77E-BA5F-4806-B224-12AA8601A5B1)
]
typedef struct UserEntity
{
UserEntityType EntityType;
BSTR Value;
} UserEntity;
[id(9)] HRESULT SetUsers([in] SAFEARRAY(UserEntity) input);
The exception is thrown at run-time when a C# 4 client calls SetUsers().

The problem was in the C# client that was using the exe COM server where
SetUsers([in] SAFEARRAY(UserEntity) input)
was defined.
In order to fix this (at least for .NET 4.0) one has to change the following property of the imported COM server: Embed Interop Types = False

Related

Use native function pointer for listening to managed event / marshaling issue

I'm writing a mixed mode C++/CLI assembly bridge in order to be able to call into my .NET class library from old C++ application.
In one of my classes in the .NET library one can attach to an event whenever some message needs to be displayed (to console or whatever depending on calling application).
class NetApi
{
public event EventHandler<MessageEventArgs> MessageReported;
}
To call this from native C++ application, I defined the following pointer/delegate bridge:
typedef void(*MessageHandler)(const char* msg);
delegate void ManagedMessageHandler([MarshalAs(UnmanagedType::LPStr)] String^ msg);
Omitting from glue for connecting everything (attaching to MessageReported, removing sender from EventHandler, etc...), here is how I create managed delegate from native function pointer:
class NetApiBridge
{
public:
void SetMessageHandler(MessageHandler handler)
{
wrappedListener = (ManagedMessageHandler^)Marshal::GetDelegateForFunctionPointer((IntPtr)handler, ManagedMessageHandler::typeid);
}
private:
msclr::auto_gcroot<NetApi^ > wrappedApi;
msclr::auto_gcroot<ManagedMessageHandler^ > wrappedListener;
// In another helper ref class in fact, but here pseudo code to simplify
void onMessageReported(Object^ sender, MessageEventArgs^ e)
{
if (!wrappedListener) { return; }
wrappedListenter(e->Message); // Send message to native function pointer
}
}
And I'm almost there when creating dummy C++ test code:
void messageHandler(const char* s)
{
cout << s;
}
void main()
{
NetApiBridge api = new NetApiBridge();
api->SetMessageHandler(&messageHandler);
api->Measure();
delete api;
}
Everything goes fine, events are reported correctly except .... except I receive a PInvokeStackImbalance from Managed Debugging Assistant when leaving the native handler and I clearly don't know why ?
What's wrong with marshaling const char* as UnmanagedType::LPStr here with GetDelegateForFunctionPointer ?
NB: C++ bridge is compiled in x86 if it is important to know here.
typedef void(*MessageHandler)(const char* msg);
delegate void ManagedMessageHandler([MarshalAs(UnmanagedType::LPStr)] String^ msg);
Your delegate declaration is not compatible with the function pointer declaration in 32-bit code. The default calling convention in native code is almost always __cdecl. The default for delegates is __stdcall. A somewhat quirky choice but inspired because interop was assumed to be useful to make OS calls, Windows and COM use __stdcall.
The mismatch right now causes the delegate stub to pop the arguments off the stack. So does the native code so the stack gets imbalanced by 4 bytes. The MDA is there to help you diagnose this common mishap.
You'll have to help and get them to agree. Either with the delegate declaration:
using namespace System::Runtime::InteropServices;
...
[UnmanagedFunctionPointer(CallingConvention::Cdecl)]
delegate void ManagedMessageHandler(String^ msg);
Or the function pointer declaration:
typedef void (__stdcall * MessageHandler)(const char* msg);

Using Directx members between c++\CLI assemblies C3767

I am trying to call a member function from a C++/CLI assembly from another one, but when I start using DirectX struct I get C3767 error : candidate function not accessib
from Utilities.dll
#pragma once
#include "define.h"
namespace Utilities
{
public ref class Data
{
public:
BOOL CreateBuffer( LPDIRECT3DDEVICE9 dev)
{
...
return TRUE;
}
{
}
And using it from a renderer
#include "Renderer.h"
namespace SomeNamespace
{
SceneRenderer::SceneRenderer(void)
{
}
void SceneRenderer::Render(LPDIRECT3DDEVICE9 dev)
{
...
m_vbo->CreateBuffer(dev); //error C3767: 'Utilities::Data::CreateBuffer': candidate function(s) not accessible
...
}
}
I know that using the address of the device int* (&dev) I can cast back to a LPDIRECT3DDEVICE9, but im looking for a better solution
A managed C++ assembly will not export unmanaged types in its public interface by default. LPDIRECT3DDEVICE9 is an unmanaged type, so your CreateBuffer method will be marked private, regardless of the access specifier provided (kind of stupid that the compiller isn't even generating a warning about this).
Use #pragma make_public or, better yet, do not use unmanaged types in managed interfaces.
Suggestion: Use slimDx or Xna if you want to use DirectX in managed code. These libraries already provide managed wrappers for everything.

C++/CLI wrapper not working (LoaderLock exception)

I've made very simple wrapper for unmanaged C++ library (to be used with C#). Wrapper has one unmanaged class and one managed class. Managed class has private member that is of unmanaged class and uses it like that.
I've done very simple setup - I've created wrapper for only one function to see if everything is working. But as soon as I create an instance of wrapper, my application get's exception "LoaderLock was detected" with following message:
DLL 'c:\path\CPPWrapper.dll' is
attempting managed execution inside OS Loader lock. Do not attempt to
run managed code inside a DllMain or image initialization function
since doing so can cause the application to hang.
If I turn off breaking for "LoaderLock" exception, I get "FileLoadException was unhandled":
Could not load file or assembly 'CPPWrapper.dll' or one of its dependencies. Exception from HRESULT: 0xE0434352
Any idea what I am doing wrong and how can I fix this problem?
CPPWrapper.h
// CPPWrapper.h
#pragma once
#include "Native.h"
using namespace System;
namespace CPPWrapper {
public ref class Class1
{
public:
Class1() : mnt(new Native)
{
}
~Class1(void)
{
// call the finalize method
this->!Class1();
}
// Finalize (for garbage collection)
!Class1(void)
{
// Remove unmanaged class
delete mnt;
mnt = NULL;
}
void Napravi()
{
mnt->CreatePK();
}
private:
Native *mnt;
};
}
I found that the correct way to fix this is by adding #pragma unmanaged in the dllmain.c Don't turn off breaking for "LoaderLock" exception.
See Initialization of Mixed Assemblies and scroll down to the DllMain section for details. Basically what is happening is that the project is compiling the DllMain function as managed (MSIL) but it only runs in unmanaged code. This #pragma unmanaged forces the function to be compiled as an unmanaged function.
So my dllmain.c is now:
// dllmain.cpp : Defines the entry point for the DLL application.
#include "stdafx.h"
#pragma unmanaged
BOOL APIENTRY DllMain( HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
Another potential cause for LoaderLock is initialization of global static objects. In my case, I was compiling a boost::xpressive regex globally and it didn't like doing that when my C++/CLI wrapper was initializing DllMain. I'm not sure why, because it shouldn't have been managed code, but moving it to a function static object fixed it.

Passing custom data through predefined COM interface

I'm using 3-rd party COM service. It's exposed from .NET assembly. There are several interfaces this service provides that actually I can use in my C++ application (using early binding). Actually I would like to know if it's possible to pass custom data through using these interfaces, i.e. for me it's not enough what these interfaces provide and I want to add some additional data/methods there (though interface is not mine thus I can't change it). Please advice if it's possible, if not might be there're some workaround (example would be very helpfull)?
I'm trying to understand if it's possible to pass custom data from my producer to my consumer through 3-rd party COM service. Might be I need to create my own interface that includes my methods and that inherites 3-rd party ISomething and use it?
Below is the code that illustrates the problem. Many thanks for your help...
1) Class that I'm using to pass data from producer to consumer (through 3-rd party COM service):
//ISomething is 3-rd party interface with some limited # of data and methods
//Something is my class that will be used to pass data where ISomething is asked
//and it contains some methods that I need and they are not defined in ISomething
class Something: public CComObjectRootEx<CComSingleThreadModel>, public IDispatch
{
private:
bstr_t Name;
bstr_t MyData;
public:
//COM map omitted
//Method defined in ISomething
STDMETHOD(get_Name)(BSTR * pRetVal)
{
*pRetVal = ::SysAllocString(Name);
return S_OK;
}
//Method defined in ISomething
STDMETHOD(put_Name)(BSTR pRetVal)
{
Name = pRetVal;
return S_OK;
}
**//Method that is NOT defined in ISomething**
STDMETHOD(get_MyData)(BSTR * pRetVal)
{
MyData= pRetVal;
return S_OK;
}
**//Method that is NOT defined in ISomething**
STDMETHOD(put_MyData)(BSTR pRetVal)
{
MyData = pRetVal;
return S_OK;
}
}
2) My data producer fills the data and passes it to 3-rd party COM service
CComObject<Something> *Obj = NULL;
CComObject<Something>::CreateInstance(&Obj);
//Calling method defined in ISomething
Obj->put_Name(_bstr_t("Some data"));
**//Calling method that is NOT defined in ISomething**
Obj->put_MyData(_bstr_t("My data"));
//Passing data to COM service
CComPtr<ISomething> iObj;
Obj->QueryInterface(__uuidof(ISomething),(void **) &iObj);
CComPtr<ICommand> command = //init omitted, it's another 3-rd party object;
//Setting data
command->do(iObj);
3) My data consumer tries to get both defined and non-defined data but succeeds only in getting defined one, non-defined contains garbage
class SomethingEventSink : public CComObjectRootEx<CComSingleThreadModel>,
public IDispatch
{
//COM map omitted
STDMETHOD(SomethingEventHandler)(VARIANT sender, struct _SomethingEventArgs *args)
{
ISomething* obj;
Something* extObj;
args->get_Something(&obj);
BSTR Name, Name1, MyData;
//Works fine
obj->get_Name(&Name);
//Casting to my object pointer
extObj = reinterpret_cast<Something*>(obj)
//Works fine
extObj->get_Name(&Name1);
**//Works, but NO DATA I've set at producer step**
**//HOW TO MAKE IT WORK?**
extObj->get_MyData(&MyData);
return S_OK;
}
}
What your trying to do isn't possible the way you are doing it. However you may be able to get it to work if you can declare your own new interface?
In this case your object can implement ISomething & IMyInterface and you can define IMyInterface to have any new methods you want.

Passing reference to COM interface from COM library

How do I pass reference to a COM interface as an argument from within a COM library?
Here's the sample:
1) Client code successfully creates coclass and receives the interface pointer in pFunctionDiscovery as below:
hr = CoCreateInstance(
__uuidof(FunctionDiscovery),
NULL,
CLSCTX_INPROC_SERVER,
__uuidof(IFunctionDiscovery),
(LPVOID*)&pFunctionDiscovery );
if (FAILED(hr))
{
TRACE_MESSAGE(Error,"Failed to get IFunctionDiscovery COM %08x\n",hr);
goto Exit;
}
2) Now calling member function of pFunctionDiscovery as below gives error message: 800706f4, which corresponds to A null reference pointer was passed to the stub.
hr = pFunctionDiscovery->GetInstanceCollection(
FCTN_CATEGORY_DEVICEDISPLAYOBJECTS,
NULL,
FALSE,
&pFICollection );
3) COM library is written with aid of ATL library and the code is as below:
// The module attribute is specified in order to implement DllMain,
// DllRegisterServer and DllUnregisterServer
[ module(dll, name = "MyServer", helpstring = "MyServer 1.0 Type Library") ];
[ emitidl ];
/////////////////////////////////////////////////////////////////////////////
// IFunctionInstanceCollection interface
[
object,
uuid("F0A3D895-855C-42A2-948D-2F97D450ECB1"),
oleautomation,
helpstring("IFunctionInstanceCollection Interface"),
pointer_default(unique)
]
__interface IFunctionInstanceCollection : IUnknown
{
public:
virtual HRESULT STDMETHODCALLTYPE GetCount(__RPC__out DWORD *pdwCount) = 0;
};
// IFunctionDiscovery interface
[
object,
uuid("4df99b70-e148-4432-b004-4c9eeb535a5e"),\
oleautomation,
helpstring("IFunctionDiscovery Interface"),
pointer_default(unique)
]
__interface IFunctionDiscovery : IUnknown
{
virtual HRESULT GetInstanceCollection(
__RPC__in_string const WCHAR* functionCategory,
__RPC__in_opt_string const WCHAR* subcategory,
BOOL fIncludeAllSubCategories,
__RPC__deref_out_opt IFunctionInstanceCollection **ppIFunctionInstanceCollection
) = 0;
};
/////////////////////////////////////////////////////////////////////////////
// FunctionDiscovery class
[
coclass,
threading(apartment),
vi_progid("FunctionDiscovery.Discovery"),
progid("FunctionDiscovery.Discovery.1"),
version(1.0),
uuid("C72BE2EC-8E90-452c-B29A-AB8FF1C071FC"),
helpstring("FunctionDiscovery Class")
]
class ATL_NO_VTABLE FunctionDiscovery :
public IFunctionDiscovery
{
public:
FunctionDiscovery() {};
virtual ~FunctionDiscovery(){};
virtual HRESULT GetInstanceCollection(
__RPC__in_string const WCHAR* functionCategory,
__RPC__in_opt_string const WCHAR* subcategory,
BOOL fIncludeAllSubCategories,
__RPC__deref_out_opt IFunctionInstanceCollection **ppIFunctionInstanceCollection
)
{
printf("GetInstanceCollection called");
return 0;
}
DECLARE_PROTECT_FINAL_CONSTRUCT()
HRESULT FinalConstruct()
{
return S_OK;
}
void FinalRelease()
{
}
static BOOL DllMainAttach();
static void DllMainDetach();
};
Please let me know where the problem is?
Thanks
Nick
Ok, passing a non null string in the call from client, worked fine. The way I am assigning object to *ppIFunctionInstanceCollection is as below:
On the Server side, I declare a new class like this and create an object from within GetInstanceCollection. When client calls GetInstanceCOllection, this created object is returned. I do get a valid instance on the server side, but on the client side, it shows up as NULL.
1)
class CFunctionInstanceCollection : public IFunctionInstanceCollection
{
public:
HRESULT STDMETHODCALLTYPE QueryInterface(REFIID IID, void **pv) throw()
{ return 0; };
ULONG STDMETHODCALLTYPE AddRef(void) throw()
{ return 0; };
ULONG STDMETHODCALLTYPE Release(void) throw()
{ return 0; };
virtual HRESULT STDMETHODCALLTYPE GetCount(__RPC__out DWORD *pdwCount)
{ return 10; };
};
2) From within GetInstanceCollection, I am doing:
*ppIFunctionInstanceCollection = new CFunctionInstanceCollection();
I was hoping that the above assignment valid instance of CFunctionInstanceCollection into last parameter of GetInstanceCollection() method, which is *ppIFunctionInstanceCollection. I have verified this on the server side and it prints valid pointer, with size of class as 4 (presence of virtual functions yields class size as 4).
But on the client side, value is NULL. I think there is something more in passing of parameters between client/server. If you see anything else, please let me know that too. Thanks!!!
Apologies if I'm telling you things you already know.
In RPC (and COM), a proxy is the piece of code the client actually invokes when it calls a remote procedure. The proxy generally marshals the input parameters and then sends the request to the server where a piece of code called the stub unmarshals the parameters and then uses them to invoke the actual procedure being called.
When the called procedure returns a result, the stub marshals the out parameters and the result and sends the response back to the proxy which in turn unmarshals the out parameters etc. and hands them back to the client.
That's the general model anyway, things are sometimes optimised away (e.g., in the case of in process COM objects) in which case there may not be an actual stub and an actual proxy. Still, that's the background we can use to understand what a "proxy" and a "stub" are.
The "A null reference pointer was passed to the stub" error suggests that the problem is happening at the stub (i.e., server) side. The two pieces of code that might be passing things to the stub are the proxy and the implementation of GetInstanceCollection with GetInstanceCollection being the more likely culprit.
I suspect your problem is that the GetInstanceCollection implementation does not assign a value to *ppIFunctionInstanceCollection.
Try adding code to assign *ppIFunctionInstanceCollection before GetInstanceCollection returns.
updated 3/15
Your updated implementation of GetCount returns the value 10. But, that will be interpreted as the HRESULT 10 not the count value 10. The implementation of GetCount should really look something like this...
virtual HRESULT STDMETHODCALLTYPE GetCount(__RPC__out DWORD *pdwCount)
{
*pdwCount = 10;
return S_OK;
};
That said, it really isn't a good idea to dummy up the IUnknown methods (QueryInterface, AddRef and Release) because you can break all sorts of things unexpectedly. For example, every time you call GetInstanceCollection your program is going to leak a CFunctionInstanceCollection instance because one is created and never destroyed.
The code you have is okay for an experiment but it would be better to use ATL to do a full implementation of IUnknown for CFunctionInstanceCollection just as you did for your FunctionDiscovery class.
Updated 3/16
For completeness, I should probably also have mentioned that assigning *ppIFunctionInstanceCollection the way you do is valid but potentially risky in general.
You've written the CFunctionInstanceCollection class, so you know it implements the IFunctionInstanceCollection interface directly, so you know your assignment is safe. But in the more general case where you didn't write the class, the CFunctionInstanceCollection class might do something less straight forward - for example it might aggregate some other class that implements the interface. To be really really safe you should use QueryInterface to retrieve the IFunctionInstanceCollection interface pointer.
This blog post explains why you have this problem, pointer_default(unique) does not do what you think it does. Attribute the subcategory argument with [unique].