How does COM select how to marshal an interface? - windows

As I get it there're three ways to implement marshalling in COM:
typelib marshalling
proxy/stub marshalling
implementing IMarshal by the object
now how does the component consumer (user) choose which one will be used? Does it decide on its own and use the preferred way or does it call some built-in function and it solves the problem for it?
I currently experience the following: my component implements a custom interface ICustomInterface that is also implemented by a component from another company. My component doesn't have a typelib and doesn't implement IMarshal. The system registry contains the HKCR\Interface{uuidof(ICustomInterface)}\ProxyStubClsid32 key with a GUID of the proxy/stub that can be traced to a library provided by that other company.
Now when my component consumer initializes my component it calls QueryInterface() requesting IMarshal from my component and when returned E_NOINTERFACE it just does nothing. Why is this - why doesn't proxy/stub library from the other company kick in?

The COM runtime will use typelib (oleautomation) marshalling if you mark your interface as using the standard marshaler by adding its CLSID {00020424-0000-0000-C000-000000000046} under HKCR\Interfaces\{iid}\ProxyStubClsid (where {iid} is the GUID of your interface). You'll need to have a typelibrary registered too, in order for the runtime to extract the parameter information, and you can only use a certain subset of types. There's some more (old) information here and here.
If you want to use a custom proxy/stub, as generated by the MIDL compiler from your IDL, then you'll need to change the interface registry entry to be the CLSID of that proxy object instead. This enables you to use a wider range of types, e.g. "raw" arrays.
If you support IMarshal then that's what'll be used in preference to either of these mechanisms. This means you can change your object to aggregate the free-threaded marshaler (using its implementation of IMarshal) without having to change anything in the registry. This will avoid any proxies being created.
Hope this helps.

I am a bit rusty at this, but do you have a function named blindquery in your project ? (its usually declared by the wizard if you created a C++ ATL project). Breakpoint inside the function. The function is generated by the wizard often has problems with queryinterface returning E_NOINTERFACE due to buggy code.
edit (found sample code) from my old project _blindquery
class ATL_NO_VTABLE CChildEvents :
public CComObjectRootEx <CComSingleThreadModel>,
public CComCoClass<CChildEvents, &CLSID_ChildEvents>,
public IDispatchImpl<IChildEvents, &IID_IChildEvents, &LIBID_XXX>
{
public:
CChildEvents(void) :
m_pItfMgr(0)
{
}
/* called from internalQI to tear off a new blind interface */
static HRESULT WINAPI _BlindQuery(void *pvThis, REFIID riid, void **ppv, DWORD dw);
DECLARE_REGISTRY_RESOURCEID(IDR_CHILDEVENTS)
DECLARE_PROTECT_FINAL_CONSTRUCT()
BEGIN_COM_MAP(CChildEvents)
COM_INTERFACE_ENTRY(IChildEvents)
COM_INTERFACE_ENTRY(IDispatch)
COM_INTERFACE_ENTRY_FUNC_BLIND(0, _BlindQuery)
END_COM_MAP()
};
HRESULT WINAPI CChildEvents::_BlindQuery(void *pvThis, REFIID riid, void **ppv, DWORD /* dw */ )
{
HRESULT hr = E_NOINTERFACE;
USES_CONVERSION;
try
{
if(pvThis == NULL)
{
ATLASSERT(FALSE);
}
else
{
/*
* cast the pvThis pointer to the actual class £
* so we can use it here £
* reinterpret_cast should be safe since we're calling ourself
*/
CChildEvents *pThis = reinterpret_cast < CChildEvents * > (pvThis);
if(pThis == NULL)
{
ATLASSERT(FALSE);
}
else
{
/* check to see if it matches on of our children's DIID */
if(memcmp(&riid,&l_someotherguid,sizeof(GUID)) == 0) {
/* if so cast to a IDispatch -- the standard for event interfaces */
*ppv = reinterpret_cast < IDispatch * > (pvThis);
/* addref */
pThis->AddRef();
/* reply */
hr = S_OK;
}
}
}
}
catch(...)
{
ATLASSERT(FALSE);
}
/* must not be in our map - tell them to GO FISH */
return(hr);
}

Related

Which Windows API in C++ will help me in identifying which Dialog Class the Current ComboBox is using?

How can I know that for a particular ComboBox which Dialog Style is being used? Is there any Win32 API which can give me that information?
I am using CDialog for a few ComboBox, CDialogEx for some, and an in-house Dialog class, let's say Ctl3dDialogEx, for others. GetClassName() will return the Class name of the ComboBox (if I am passing a ComboBox Handler) which can be "CComboBox".
Is there any Win32 API where I will pass the ComboBox Handler and it will return back to me the Dialog class name, for eg : "CDialog", "CDialogEx", "Ctl3dDialogEx", etc?
Below code will help to understand maybe:
void ComboBox_DoSomeManipulation( HWND hldg , int n )
{
/*"hldg" is the handler of the Current ComBobox */
LPTSTR lpClassName;
int nMaxCount = 256;
/*This will return "CComboBox" as value in lpClassName */
GetClassName(hldg , lpClassName , _count_of(nMaxCount));
/*Is there any WIN API like above which can give */
/* Dialog class information like CDialog, CDialogEx */
/* which the ComboBox is using ? */
}
If your combo-box can somehow get hold of a genuine pointer to its parent window, then you can use dynamic_cast<CDialogEx*>(pParent) to see if it's CDialogEx (returns nullptr if not). You will need several separate checks, starting from the most derived class! So, if your Ctl3dDialogEx is derived from CDialogEx, then:
. . .
CWnd *pParent = pCombo->GetParent(); // This, as is, is not valid code!
if (dynamic_cast<Ctl3dDialogEx*>(pParent) != nullptr) {
// It's a Ctl3dDialogEx parent
}
else if (dynamic_cast<CDialogEx*>(pParent) != nullptr) {
// It's a CDialogEx
}
else { // Assuming no other options …
// It's a CDialog
}
I would recommend making an accessible (static?) copy of the parent window's this pointer during initialisation, if you can. But there are other ways …
For example, assuming you have control over the definition of ComboBox_DoSomeManipulation and when it's called, change the first argument from an HWND to a CWnd* and, when you call it, use this rather than this->m_hwnd. (But this depends on the structure of your code!)
There is no Windows API help since all those dialogs will be subclassing the Windows DIALOG class. If this is all in process, and you are using the same MFC instance, you might be able to do this:
CWnd* pWnd = CWnd::FromHandlePermanent(hdlg);
if (pWnd != NULL)
{
if (pWnd->GetRuntimeClass() == RUNTIME_CLASS(CDialog))
{
}
else if (pWnd->GetRuntimeClass() == RUNTIME_CLASS(CDialogEx))
{
}
else if (pWnd->GetRuntimeClass() == RUNTIME_CLASS(CDialogxyz))
{
}
}
Back in the old days, MS compilers used with MFC didn't play well with dynamic_cast<>, so generally, when using MFC, I don't use it. I probably should have more trust in it, but I was stuck using Visual C++ 6 until 2008, so I am probably a little jaded. The more "standard" "MFC way" is to use the MFC macros...
Another possible ways is something like:
if (CDialogxyz* pDlgxyz = DYNAMIC_DOWNCAST(CDialogxyz, pWnd))
{
}
else if (CDialogEx* pDlgEx = DYNAMIC_DOWNCAST(CDialogEx, pWnd))
{
}
else if (CDialog* pDlg = DYNAMIC_DOWNCAST(CDialog, pWnd))
{
}

Retrieve DISPID of outgoing dispinterface member

I'm stuck on this one.
Given three variables:
an IDispatch* to a connectable object
the IID (DIID) of an outgoing dispinterface on that object
the name of a member defined by the dispinterface
How can resolve the name to a DISPID?
pDispatch->GetIDsOfNames(...) returns DISP_E_UNKNOWNNAME, as I would expect (outgoing interfaces aren't implemented by the connectable object)
I need to support scenarios where 0 clients have yet connected to the outgoing interface, so I can't enumerate the existing connection points in order to call GetIDsOfNames on one of them (I'm not even sure this would work)
In order to perform manual reflection, I would need the dispinterface's ITypeInfo. I could get this from the coclass's ITypeInfo. However pDispatch->GetTypeInfo(0, ...) returns the ITypeInfo for the IDispatch implementation (as per the documentation), not the ITypeInfo for the coclass. (And there are no other ITypeInfos exposed by this object's IDispatch implementation.)
If the object is "quite standard", then it should be possible.
From the object/IDispatch interface, you should be able to get to the TLB (type library). From the type library, you should be able to browse all coclasses, and get interfaces that these coclasses implement. You need to get to interface you have the IID for, browse the member and get the one you're interested.
There are many cases where this just won't work. Here is a console sample I've put up that works with a shell object. I've written it in C# because it's easier, but there's nothing you can't do with a decent language. I've used an old TLBINF32.DLL com utility library (only x86 unfortunately) I talk about in my answer to this question here on SO: How to read COM TypeLib with C# or C++?
static void Main(string[] args)
{
// create a sample object every one has
object o = Activator.CreateInstance(Type.GetTypeFromProgID("shell.application")); // for example
TLIApplication app = new TLIApplication();
// not sure, but I believe in pure COM it's calling IDispatch::GetTypeInfo & ITypeInfo::GetContainingTypeLib
TypeLibInfo tli = app.InterfaceInfoFromObject(o).Parent;
// this is the guid for DShellFolderViewEvents
int dispid = GetDispId(tli, new Guid("{62112AA2-EBE4-11CF-A5FB-0020AFE7292D}"), "SelectionChanged");
Console.WriteLine("dispid:" + dispid); // should display 200
}
public static int GetDispId(TypeLibInfo tlb, Guid diid, string memberName)
{
// browse all coclasses
// in pure COM this is ITypeLib::GetTypeInfo
foreach (CoClassInfo ti in tlb.CoClasses)
{
// browse all interfaces in those coclasses
// in pure COM this is ITypeInfo::GetRefTypeOfImplType
foreach (InterfaceInfo itf in ti.Interfaces)
{
// only select [source] interfaces (events)
// this test is optional since the diid is unique
// in pure COM this is ITypeInfo::GetImplTypeFlags
if (((ImplTypeFlags)itf.AttributeMask & ImplTypeFlags.IMPLTYPEFLAG_FSOURCE) != ImplTypeFlags.IMPLTYPEFLAG_FSOURCE)
continue;
if (new Guid(itf.GUID) == diid)
{
// in pure COM this is ITypeInfo::GetTypeAttr & ITypeInfo::GetFuncDesc
foreach (MemberInfo mi in itf.Members)
{
if (mi.Name == memberName)
return mi.MemberId;
}
}
}
}
return -1;
}

Is it must to change COM interface UID when adding new functions

I have a COM interface exposed from my application which is used by the third party plugins. Now, I need to add a new method to this interface but can not change the GUID of the interface as it will break all the existing plugins. I was told that if I add the new methods at the end of the interface it will work without issues as finally COM interface is a table of function pointers. These new methods will only be used by newly written plugins. I read this post and the first comment in Raymond Chen's blog: http://blogs.msdn.com/b/oldnewthing/archive/2005/11/01/487658.aspx but the situation mentioned in comment won't happen in my case as it is Windows only application. I know theoretically I should change the interface GUID. What would be the correct solution in this case? or will this approach work?
You can usually get away with adding new methods to the end of an existing interface without breaking compatibility. But as you have been reading, there are subtle cases where this can break. Especially when multiple inheritance is already being used.
The correct solution is to simply declare a new interface for the new methods. Leave your existing interfaces alone. Then have your existing objects implement both interfaces or use inheritance to have the new interface inherit from the old.
For example, if this is our original code. (I'll pretend this is done without IDL files for brevity).
Original code:
class IPublicInterface : public IUnknown
{
public:
virtual void M1() = 0;
virtual void M2() = 0;
}
class MyPublicClass : IPublicInterface
{
public:
// IPublicInterface
void M1();
void M2();
// IUnknown
HRESULT QueryInterface(...);
ULONG AddRef();
ULONG Release();
};
Now let's say we want to add a new method to this object called M3 without breaking users of the existing interface and object. The correct solution would be to add a new interface. For convenience, it can just inherit from the original interface.
class IPublicInterface2 : public IPublicInterface
{
public:
virtual void M3() = 0;
};
Now modify the class to inherit from both this new derived interface:
class MyPublicClass : public IPublicInterface2
{
public:
// IPublicInterface
void M1();
void M2();
// IPublicInterface2
void M3();
// IUnknown
HRESULT QueryInterface(...);
ULONG AddRef();
ULONG Release();
};
Update QueryInterface to support both calls for both the original UUID of IPublicInterface as well as IPublicInterface2.
HRESULT MyPublicClass::QueryInterface(GUID& iid, void** ppv)
{
// QI request for original interface
if ((iid == uuidof(IPublicInterface) || (iid == uuidof(IUnknown))
{
*ppv = (IPublicInterface*)this;
AddRef();
return S_OK;
}
else if (iid == uuidof(IPublicInterface2)
{
*ppv = (IPublicInterface2*)this;
AddRef();
return S_OK;
}
return E_NOINTERFACE;
}
Alternatively, IPublicInterface2 does not need to inherit from the original IPublicInterface. In that case, the implementing class inherits from both interfaces. In the QueryInterface implementation, you will need to be consistent about how you handle a possible ambiguous cast to IUnknown.

Calling a managed delegate from an x64 callback? (parameter in rdx is getting trashed)

I have a library which exposes callback functions, and needs to be called from both managed and native code. I implemented this by doing:
typedef struct { DWORD blah; } MY_STRUCT;
class ICallbackInterface
{
public:
virtual HRESULT CallbackFunc1(const MY_STRUCT* pStruct) { return S_OK; }
// helper for overriding the vtable (used later on by the managed code)
class VTable
{
public:
void* pfnCallbackFunc1;
};
};
The native code receives a pointer to an ICallbackInterface, and calls CallbackFunc1.
In C++/CLI code, I'm allocating an ICallbackInterface, and overriding its vtable to point to delegates of the managed functions I want to call. (The following snippet is from the constructor):
public ref class MyManagedClass
{
...
m_pCallbackClass = new ICallbackInterface;
if (!m_pCallbackClass)
return E_OUTOFMEMORY;
m_pNewCallbackVtable = new ICallbackInterface::VTable;
if (!m_pNewCallbackVtable)
{
delete m_pCallbackClass;
m_pCallbackClass = nullptr;
return E_OUTOFMEMORY;
}
// Get the (hidden) pointer to the vtable
ICallbackInterface::VTable** ppAddressOfInternalVtablePointer =
(ICallbackInterface::VTable**)m_pCallbackClass;
ICallbackInterface::VTable* pOldVtable = *ppAddressOfInternalVtablePointer;
// Copy all the functions from the old vtable that we don't want to override
*m_pNewCallbackVtable = *pOldVtable;
// Manually override the vtable entries with our delegate functions
m_pNewCallbackVtable->pfnCallbackFunc1 = Marshal::GetFunctionPointerForDelegate(gcnew delCallbackFunc1(this, &MyManagedClass::CallbackFunc1)).ToPointer();
...
And here's the callback function & its delegate
[UnmanagedFunctionPointer(CallingConvention::StdCall)]
delegate HRESULT delCallbackFunc1(const MY_STRUCT* pMyStruct);
HRESULT CallbackFunc1(const MY_STRUCT* pMyStruct)
{
// do something with pMyStruct.
}
}
When I compile the native library for x86, all works well.
(I don't know why CallingConvention::StdCall is used there, but the alternatives seem to cause problems with esp.)
When I compile it for x64, the callback function gets called, and rsp is fine when I return, but pMyStruct is trashed. It appears the native code likes to pass things in to rdx, but somewhere in the native->managed transition (which the debugger won't let me step into), rdx is being filled with garbage.
Is there some attribute I can use to on my delegate to fix this on x64? Or do I need to do something less pleasant like wrap my entire managed class in a native class to do the callbacks? Or did I just find a managed codegen bug?
you're invoking undefined bwhavior left and right, and relying on implementation details such as vtable layout and virtual member function calling convention. it's no wonder that things broke when you changed platforms.
you need to write derived vl lass if the native interface. the implementation can call function pointers or managed delegates directly. and stop messing with the vtsble pointer.
Found the problem.
The managed code has its "this" pointer that comes when initializing the delegate.
But the native function has its own "this" pointer which is being passed along too. Changing the managed signatures to the following totally fixes the bug, and now the function gets access to both "this" pointers.
[UnmanagedFunctionPointer(CallingConvention::ThisCall)]
delegate HRESULT delCallbackFunc1(ICallbackInterface* NativeThis, const MY_STRUCT* pMyStruct);
HRESULT CallbackFunc1(ICallbackInterface* NativeThis, const MY_STRUCT* pMyStruct)
{
// do something with pMyStruct.
}
This works on x86 and x64.

Make IWebBrowser2 Control safe for scripting

I'm using IWebBrowser2 control in my application to display external web pages.
The problem is that the object is not safe for scripting and calls to get_Document fails (with S_FALSE as return value).
I've implemented a new class, IScriptableWebBrowser2 that inherits both from IWebBrowser2 & IObjectSafety, and tried to use it instead of IWebBrowser2 but that didn't do the trick.
How do I make my IWebBrowser2 control safe for scripting ?
class IScriptableWebBrowser2 :
public CComObjectRootEx<CComSingleThreadModel>,
public IWebBrowser2,
public IObjectSafety
{
BEGIN_COM_MAP(IScriptableWebBrowser2)
COM_INTERFACE_ENTRY(IObjectSafety)
END_COM_MAP()
// IObjectSafety implementation
STDMETHODIMP GetInterfaceSafetyOptions(REFIID riid,
DWORD *pdwSupportedOptions,
DWORD *pdwEnabledOptions )
{
*pdwSupportedOptions = INTERFACESAFE_FOR_UNTRUSTED_CALLER |
INTERFACESAFE_FOR_UNTRUSTED_DATA;
*pdwEnabledOptions = *pdwSupportedOptions;
return S_OK;
}
STDMETHODIMP SetInterfaceSafetyOptions(REFIID riid, DWORD dwOptionSetMask, DWORD dwEnabledOptions)
{
return S_OK;
}
};
I guess you created the browser in a thread and passed it on to another thread.
If that's the case, here's what you should do:
Before passing the IWebBrowser2 instance to another thread, in the creating thread, call CoMarshalInterThreadInterfaceInStream, that will marshal (convert) it to a thread-safe IStream object, and only then pass it to the tagert thread.
Later, in the target thread, you should call CoGetInterfaceAndReleaseStream with the previously marshaled IStream instance, which will unmarshal it back to your original object in the target thread (and release the IStream object along the way).
CoMarshalInterThreadInterfaceInStream in MSDN
CoGetInterfaceAndReleaseStream in MSDN
Hope that helps.
Well, I finally had some time to come back to this one..
It turns out that get_Document fails if you call it BEFORE the page completely loaded but the return value (S_FALSE) indicates a completely different error ("not safe for scripting")
btw, Loading local pages will give you the desirable behavior.
Therefore, calling get_Document after the page was loaded (DISPID_NAVIGATECOMPLETE2, DISPID_DOWNLOADCOMPLETE, DISPID_DOCUMENTCOMPLETE) will do the trick.
Hope this helps.

Resources