Why are all references to my IDispatch object not released? - c++

I'm hosting an IWebBrowser2 control in my C++ program using nothing but plain Win32 (no mfc, atl, wtl etc). On DISPID_NAVIGATECOMPLETE2 I add a custom object to be accessed from javascript running on the displayed webpage.
To add the custom object I call InvokeEx with DISPATCH_PROPERTYPUT and a DISPPARAMS structure with a pointer to my custom object.
During the call to InvokeEx the AddRef function of my custom object is called and I increment its reference counter. But the object never gets a call to its Release function, so the reference counter never decreases down to zero again.
Who is responsible for calling Release() after AddRef() has been called in InvokeEx?
EDIT: (Adding some code)
This is the code that adds my custom object to the IHTMLWindow2. custObj points to my custom object
IHTMLWindow2 *win = NULL;
GetDoc()->get_parentWindow(&win);
IDispatchEx *winEx = NULL;
win->QueryInterface(&winEx);
DISPID dispid;
HRESULT hr = winEx->GetDispID(objName, fdexNameEnsure, &dispid); //objName is "JSObject"
DISPID namedArgs[] = {DISPID_PROPERTYPUT};
DISPPARAMS params;
params.rgvarg = new VARIANT[1];
params.rgvarg[0].pdispVal = custObj;
params.rgvarg[0].vt = VT_DISPATCH;
params.rgdispidNamedArgs = namedArgs;
params.cArgs = 1;
params.cNamedArgs = 1;
hr = winEx->InvokeEx(dispid, LOCALE_USER_DEFAULT, DISPATCH_PROPERTYPUT, &params, NULL, NULL, NULL);
This is the object that I'm adding (some private members have been left out for brevity)
class JSObject : public IDispatch {
private:
long ref;
public:
JSObject();
// IUnknown
virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void **ppv);
virtual ULONG STDMETHODCALLTYPE AddRef();
virtual ULONG STDMETHODCALLTYPE Release();
// IDispatch
virtual HRESULT STDMETHODCALLTYPE GetTypeInfoCount(UINT *pctinfo);
virtual HRESULT STDMETHODCALLTYPE GetTypeInfo(UINT iTInfo, LCID lcid,
ITypeInfo **ppTInfo);
virtual HRESULT STDMETHODCALLTYPE GetIDsOfNames(REFIID riid,
LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId);
virtual HRESULT STDMETHODCALLTYPE Invoke(DISPID dispIdMember, REFIID riid,
LCID lcid, WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult,
EXCEPINFO *pExcepInfo, UINT *puArgErr);
};
EDIT 2:
Now that it seems to be working like it should I decided to put it on github.
https://github.com/Tobbe/CppIEEmbed. Please fork and improve if you can :)

Well, you are assigning a property, aren't you? As long as this property exists and refers to your object, it will have a reference added.
If you want the remote object to release your reference you should assign NULL to the property, or some other object.

Related

What is a Direct X Virtual Table?

I have a question about virtual table.
The virtual table as i know is the function address arrays which can find
the function address when the polymorphism object call virtual function.
But In directx, some people mentioned about dx vtable that the table of d3d9.dll
's import function address arrays.
Why they call the import function address arrays to directx vtable?
It seems to not relevant with a vtable.
Did My knowledge was incorrect? May i know about vtable in detail?
Thanks!
When exporting COM objects from a DLL, there are usually two parts at work. First is the 'factory'. The factory can be a standard C-callable function exported from the DLL (which is the case with Direct3D), or a class registered with the system registry in which case you'd use CoCreateInstance to create the COM interface instance. An example of the first is creating a Direct3D device:
ID3D11Device* d3dDevice = nullptr;
hr = D3D11CreateDevice(
nullptr,
D3D_DRIVER_TYPE_HARDWARE,
0,
0,
nullptr,
0,
D3D11_SDK_VERSION,
&d3dDevice,
nullptr,
nullptr);
After this call, the d3dDevice interface points to an allocated COM interface object. The DLL that contains D3D11CreateDevice has to be implicitly linked to the calling program--or you can use LoadLibrary to do explicitly linking in which case you'd use a pointer to the function D3D11CreateDevice which amounts to much the same thing . This is derived from the 'import table' for the DLL.
An example of the second is what you do when using Windows Imaging Component (WIC):
IWICImagingFactory* factory = nullptr;
hr = CoCreateInstance(
CLSID_WICImagingFactory,
nullptr,
CLSCTX_INPROC_SERVER,
__uuidof(IWICImagingFactory),
&factory);
This has the COM system look up the class GUID in the registry, load up the referenced DLL, and then invoke the factory methods in there to create a COM interface object which it returns to you.
In both cases, the actual thing pointed to by the interface is of the form:
typedef struct IUnknownVtbl
{
BEGIN_INTERFACE
HRESULT ( STDMETHODCALLTYPE *QueryInterface )(
IUnknown * This,
/* [in] */ REFIID riid,
/* [annotation][iid_is][out] */
_COM_Outptr_ void **ppvObject);
ULONG ( STDMETHODCALLTYPE *AddRef )(
IUnknown * This);
ULONG ( STDMETHODCALLTYPE *Release )(
IUnknown * This);
END_INTERFACE
} IUnknownVtbl;
which is contrived to exactly map to the Visual C++ implementation of virtual:
MIDL_INTERFACE("00000000-0000-0000-C000-000000000046")
IUnknown
{
public:
BEGIN_INTERFACE
virtual HRESULT STDMETHODCALLTYPE QueryInterface(
/* [in] */ REFIID riid,
/* [annotation][iid_is][out] */
_COM_Outptr_ void **ppvObject) = 0;
virtual ULONG STDMETHODCALLTYPE AddRef( void) = 0;
virtual ULONG STDMETHODCALLTYPE Release( void) = 0;
END_INTERFACE
};
COM doesn't really have a notion of inheritance, but again it's a convenience for ID3D11Device1 to use C++ public inheritance from ID3D1Device which only works because the language type has no data members declared. COM "inheritance" of interfaces is really just concatenation of the methods which you can see if you look at the C definitions in the headers:
#if defined(__cplusplus) && !defined(CINTERFACE)
MIDL_INTERFACE("cc86fabe-da55-401d-85e7-e3c9de2877e9")
ID3D11BlendState1 : public ID3D11BlendState
{
public:
virtual void STDMETHODCALLTYPE GetDesc1(
/* [annotation] */
_Out_ D3D11_BLEND_DESC1 *pDesc) = 0;
};
#else /* C style interface */
typedef struct ID3D11BlendState1Vtbl
{
BEGIN_INTERFACE
HRESULT ( STDMETHODCALLTYPE *QueryInterface )( /* ... */ );
ULONG ( STDMETHODCALLTYPE *AddRef )( ID3D11BlendState1 * This);
ULONG ( STDMETHODCALLTYPE *Release )( ID3D11BlendState1 * This);
void ( STDMETHODCALLTYPE *GetDevice )( /* ... */ );
HRESULT ( STDMETHODCALLTYPE *GetPrivateData )( /* ... */ );
HRESULT ( STDMETHODCALLTYPE *SetPrivateData )( /* ... */ );
HRESULT ( STDMETHODCALLTYPE *SetPrivateDataInterface )( /* ... */ );
void ( STDMETHODCALLTYPE *GetDesc )(
ID3D11BlendState1 * This,
/* [annotation] */
_Out_ D3D11_BLEND_DESC *pDesc);
void ( STDMETHODCALLTYPE *GetDesc1 )(
ID3D11BlendState1 * This,
/* [annotation] */
_Out_ D3D11_BLEND_DESC1 *pDesc);
END_INTERFACE
} ID3D11BlendState1Vtbl;
#endif
It's important to note this only works for the case of pure virtual (i.e. abstract) C++ classes with no data members and only virtual methods using public inheritance (i.e. interfaces). Constructors and destructors are ignored as COM life-time is managed through reference-counting via IUnknown.
The calling signatures of methods also take a pointer to the COM object as the first parameter which maps to the C++ calling convention for this.
COM interfaces are therefore designed to work like C++ virtual methods so you can use C++ syntax to call them, but they aren't necessarily C++ class objects at all.
From IUnknown there is a known standard way in COM to get a specific interface, which is QueryInterface. The Direct3D factory functions take care of this for you as well, and just return the base interface. In the case of Direct3D 11, that's a ID3D11Device.
If you want to get an interface to say 11.1, you then use QueryInterface on the ID3D11Device asking for a ID3D11Device1. It would fail on a DirectX 11.0 system, but works on a DirectX 11.1 or later system.
For a C++ programmer using Direct3D, the design purposely keeps the "COM" to a minimum (colloquially known as "COM lite"). Really just enough COM is used to make it easier to deal with interface changes over time and to provide a reasonable ABI. The Direct3D factory functions are simple C-callable exports from a known DLL, so you don't even have to muck about with the standard COM factories and in fact the API isn't designed to work if you try to use CoCreateInstance. You can technically use C via some macros that the standard MIDL compiler generates along with the C++ definitions, but it's a bit challenging to do and isn't particularly well tested these days.
Really all you need to know as a consumer of Direct3D COM is the basics of IUnknown reference counting and querying--which today is best done by using the Microsoft::WRL::ComPtr smart-pointer--and how to properly check HRESULT values--see ThrowIfFailed.
See The Component Object Model and Reference Counting (Direct3D 10)

Context menu methods in shell extension aren't being used

I am trying to write a shell extension that adds a menu item to the context menu for all file types. The code for the extension (in its entirety) is located here but I'll include some of the relevant parts below as I describe the problem.
The ContextMenu class implements the IShellExtInit and IContextMenu interfaces:
class ContextMenu : public IShellExtInit, IContextMenu
{
public:
// [...]
// IShellExtInit methods
STDMETHODIMP Initialize(PCIDLIST_ABSOLUTE pidlFolder,
IDataObject *pdtobj, HKEY hkeyProgID);
// IContextMenu methods
STDMETHODIMP GetCommandString(UINT_PTR idCmd, UINT uType, UINT *pReserved,
LPSTR pszName, UINT cchMax);
STDMETHODIMP InvokeCommand(LPCMINVOKECOMMANDINFO pici);
STDMETHODIMP QueryContextMenu(HMENU hmenu, UINT indexMenu, UINT idCmdFirst,
UINT idCmdLast, UINT uFlags);
}
All of the methods are rigged with MessageBox() calls to indicate when they are called. There is only one small problem — they are never called.
The extension includes another class that implements IClassFactory. The implementation for IClassFactory::CreateInstance() is as follows:
STDMETHODIMP ClassFactory::CreateInstance(IUnknown *pUnkOuter, REFIID riid,
LPVOID *ppvObject)
{
if (pUnkOuter) {
return CLASS_E_NOAGGREGATION;
}
if (!ppvObject) {
return E_INVALIDARG;
}
*ppvObject = NULL;
ContextMenu *contextMenu = new ContextMenu;
HRESULT hResult = contextMenu->QueryInterface(riid, ppvObject);
contextMenu->Release();
return hResult;
}
I can confirm that this method is being called and I can also confirm that ContextMenu::QueryInterface() is then being called with riid set to IID_IContextMenu.
However, nothing happens after that. None of the IContextMenu methods are called. Neither is IShellExtInit::Initialize(). Why is this happening?
Test Environment
Visual Studio 2013 Express
Windows 7 Home Premium x64
Edit: I completely forgot to describe how the extension is being registered. The DllRegisterServer() function creates the following registry keys/values and checks the error codes to confirm that they are created:
Key: HKCR\CLSID\{CLSID}, Value: NULL, Data: NitroShellExt
Key: HKCR\CLSID\{CLSID}\InprocServer32, Value: NULL, Data: [path to DLL]
Key: HKCR\CLSID\{CLSID}\InprocServer32, Value: ThreadingModel, Data: Apartment
Key: HKCR\*\ShellEx\ContextMenuHandlers\NitroShellExt, Value: NULL, Data: {CLSID}
Key: HKLM\Software\Microsoft\Windows\CurrentVersion\Shell Extensions\Approved, Value: {CLSID}, Data: NitroShare Context Menu
...where {CLSID} is {52A10783-C811-4C45-9A3D-221A962C8640}. I then use regsvr32 to register the extension and regedit to confirm that the keys/values do indeed exist.

Call IConnectionPoint::Advise cause a crash

In my project, I wrote a component which will be called in a service(COM server). There is another process will get this component's interface and register a callback interface through connection point. So the service could use the callback interface to do some feedback.
But I found that when I use the IConnectionPoint::Advise to register my callback interface cause a crash.
I implement the connection point manually. Here are part of my code:
class ATL_NO_VTABLE CUploadManager :
public CComObjectRootEx<CComMultiThreadModel>,
public CComCoClass<CUploadManager, &CLSID_UploadManager>,
public IUploadManager,
public IConnectionPointContainer,
public IConnectionPoint
...
// IConnectionPointContainer Functions
STDMETHODIMP EnumConnectionPoints(IEnumConnectionPoints **ppEnum);
STDMETHODIMP FindConnectionPoint(REFIID riid, IConnectionPoint **ppCP);
// IConnectionPoint Functions
STDMETHODIMP GetConnectionInterface(IID *pIID);
STDMETHODIMP GetConnectionPointContainer(IConnectionPointContainer **ppCPC);
STDMETHODIMP Advise(IUnknown *pUnkSink, DWORD *pdwCookie);
STDMETHODIMP Unadvise(DWORD dwCookie);
STDMETHODIMP EnumConnections(IEnumConnections **ppEnum);
In the client, I have get the component interface already, then I get the connection point and try to call function Advise:
...
CComPtr<IConnectionPointContainer> pCPC;
hr = pUnknown->QueryInterface(IID_IConnectionPointContainer, (LPVOID *)&pCPC);
if (FAILED(hr))
{
return ;
}
CComPtr<IConnectionPoint> pConnectionPoint;
hr = pCPC->FindConnectionPoint(__uuidof(_IEvents), &pConnectionPoint);
if (SUCCEEDED(hr))
{
DWORD dwCookie = 0;
CDataCallback* pCallback = new CDataCallback();
IUnknown* pUnknown = NULL;
pCallback->QueryInterface(IID_IUnknown, (void**)&pUnknown);
hr = pConnectionPoint->Advise(pUnknown, &dwCookie);
...
All interface pointers could be got successfully, but when I call Advise, the crash occurs. The strange thing is the crash is not happened in the Advise implementation, it seems occurs in the RPC call process, the call stack is like this:
003d0070() <----crash here
combase.dll!76eea3ab()
[Frames below may be incorrect and/or missing, no symbols loaded for combase.dll]
combase.dll!76ee9d00()
rpcrt4.dll!7612a53d()
mfc90ud.dll!CDialog::OnCmdMsg
...
But if the first parameter of Advise is NULL, the function Advise could be executed.
Here is the Sink code implemented in client:
class CDataCallback : public _IEvents
{
public:
CDataCallback() {}
~CDataCallback() {}
HRESULT __stdcall QueryInterface(REFIID iid, LPVOID* ppInterface)
{
*ppInterface = this;
return S_OK;
}
ULONG STDMETHODCALLTYPE AddRef()
{
return 1;
}
ULONG STDMETHODCALLTYPE Release()
{
return 0;
}
HRESULT __stdcall TestFunc()
{
...
return S_OK;
}
};
The interface _IEvents is generated in the component which will be used as a callback in the connection point. I just use this class to test the connection point, so the implementation is very simple.
I have no idea about how this crash occurs.
Thanks for all your help!
The problem is likely to be in your CDataCallback class. It's QueryInterface implementation is unsafe and returns interface pointer incorrectly.
class CDataCallback : public _IEvents
HRESULT __stdcall QueryInterface(REFIID iid, LPVOID* ppInterface)
{
*ppInterface = this;
return S_OK;
}
You have to check iid and return E_NOINTERFACE in case requested interface is not _IEvents. Basically you can set a breakpoint there and see if you have a call there prior to crash and check the arguments.
Your sink might be queried for other interfaces (IMarhsal etc) and you have to properly indicate that you are not implementing them, instead of returning unmatching pointer, use of which leads to undefined behavior.

Direct3D 9 functions return value

Since the function's return value is utilized for error message, how do the functions return the necessary information back to the caller?
For example:
IDirect3D9::CreateDevice method
So if you take a look at that link you'll notice that it has some parameters marked Out this is important because this denotes what will be returned to the caller.
HRESULT CreateDevice(
[in] UINT Adapter,
[in] D3DDEVTYPE DeviceType,
[in] HWND hFocusWindow,
[in] DWORD BehaviorFlags,
[in, out] D3DPRESENT_PARAMETERS *pPresentationParameters,
[out, retval] IDirect3DDevice9 **ppReturnedDeviceInterface
);
In the above sample (copied and pasted from the MSDN link), you'll notice a parameter ppReturnedDeviceInterface is marked as being ** or a pointer to a pointer, the caller would pass in a the address of their pointer and would be returned a pointer at that address. Also the D3DPRESENT_PARAMETERS structure passed in to pPresentationParameters will be updated on return, as noted by the out annotation.
Ex:
IDirect3DDevice9 *pDevice = NULL;
HRESULT hr = pD3D->CreateDevice(
D3DADAPTER_DEFAULT,
D3DDEVTYPE_HAL,
hwnd,
pPresentationParams,
&pDevice);
if(SUCCEEDED(hr))
{
//pDevice should be non null at this point
}

Providing an IDispatch implementation for a connection point client

I've written a simple COM DLL inproc server with a single simple COM object. The COM object implements a connection point.
I know how to create an ATL client that derives from IDispEventImpl, and uses a sink map to simplify this process.
But, for the purposes of demonstration, I'd like to create a win32 console application that uses a class that calls my simple COM object, then acts as a connection point sink.
I've got no idea how to provide an implementation of IDispatch - can someone recommend documentation on this, as I can't find any (I've got ATL Internals, but this doesn't seem to cover what I need ).
Here's the class I've already got:
#pragma once
#include <iostream>
using namespace std;
// Because we're implementing a connection points sink (_IPogFarmEvents)
// in a non-ATL class, we must provide implementations for IUnknown and IDispatch.
class KidWithAPogFarm : public _IPogFarmEvents
{
private:
DWORD m_dwRefCount;
LONG m_lNumPogs;
public:
KidWithAPogFarm() :
m_dwRefCount (0),
m_lNumPogs (0)
{
}
~KidWithAPogFarm()
{
}
// -- IUnknown
HRESULT STDMETHODCALLTYPE QueryInterface(REFIID iid, void **ppvObject)
{
if (iid == DIID__IPogFarmEvents)
{
m_dwRefCount++;
*ppvObject = (void *)this;
return S_OK;
}
if (iid == IID_IUnknown)
{
m_dwRefCount++;
*ppvObject = (void *)this;
return S_OK;
}
return E_NOINTERFACE;
}
ULONG STDMETHODCALLTYPE AddRef()
{
m_dwRefCount++;
return m_dwRefCount;
}
ULONG STDMETHODCALLTYPE Release()
{
ULONG l;
l = m_dwRefCount--;
if ( 0 == m_dwRefCount)
delete this;
return l;
}
// -- IDispatch
STDMETHODIMP GetTypeInfoCount(UINT *pctinfo)
{
return E_NOTIMPL;
}
STDMETHODIMP GetTypeInfo( UINT iTInfo, LCID lcid, ITypeInfo **ppTInfo )
{
return E_NOTIMPL;
}
STDMETHODIMP GetIDsOfNames(const IID &riid, LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId )
{
return E_NOTIMPL;
}
STDMETHODIMP Invoke(DISPID dispIdMember, const IID &riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr )
{
return E_NOT_IMPL;
}
// -- IAntFarmEvents
STDMETHODIMP OnFarmCreated(LONG lInitialPopulation)
{
m_lNumPogs = lInitialPopulation;
cout << "The kid has a pog farm with " << m_lNumPogs << " pogs " << endl;
return S_OK;
}
};
Since you already have ATL you can examine its sources and see how IDispatchImpl does all that stuff. IDispatch methods are implemented therehby reading data from the type library in the same module since it's the easiest and most reliable way when a type library is already present.
It's also worth noting that it's a rather hard topic for making a demonstration on it - you'll need to write a lot of code that doesn't really bring any insight. IMO you'll be much better off if you implement an events interface that doesn't inherit from IDispatch but rather inherits directly from IUnknown - this will demonstrate how events work without dragging too much of attention to IDispatch inner workings.
I think the easiest way of doing this is through CreateStdDispatch
You can use this IDispatch implementation.
It's not exactly what you're looking for, but FireBreath uses IDispatchEx and connection points to provide an ActiveX control that runs in IE. Because FireBreath is an abstraction to allow plugins to be written once and used in all major browsers, the IDispatch interface needed to be written by hand -- including connection points.
The code may be a little confusing, since there is a templated mixin class used to provide IDispatch and ConnectionPoints to two different COM object classes, but it may help.
Mixin class
ActiveX Control
Second COM control (not OLE)
You've already accepted an answer, but perhaps it will still help. Sorry I didn't see the question sooner.