1

I'm trying to register a COM class object, which represents the application I want to automate, to the Running Object Table (ROT). However, the returned HRESULT is E_INVALIDARG, though all the supplied arguments match the documented types.

The application type is EXE and it's registered in the Windows Registry with a CLSID and its type there is LocalServer.

The reason of my attempt relates to a similarly asked question.

I usually connect with some applications using the comtypes package of python, most of them succeed with the call to GetActiveObject(). However, when calling GetActiveObject() with the CLSID of this application I get an error

WindowsError: [Error -2147221021] Operation unavailable

The effective part of the code of the MFC Application is the following

CoInitialize(NULL);

IMoniker *appmnk;
CLSID appclsid;
IUnknown* app_ptr = NULL; //in CoGetClassObject, the pointer to the exe application

DWORD dwrdptr;

IRunningObjectTable *rot; //fetch the pointer using GetRunningObjectTable
HRESULT hr;
HRESULT hr0;
HRESULT hr1;
HRESULT hr2;
HRESULT hr3;

hr0 = CLSIDFromProgID(OLESTR("TheApp.Application.1"), &appclsid);
// "TheApp.Application.1" is a hypothetical ProgID
// In the actual code, it's replaced with the actual ProgID

if (SUCCEEDED(hr0))
{
    hr1 = CoGetClassObject(appclsid, CLSCTX_LOCAL_SERVER, NULL, IID_IUnknown, (void **)&app_ptr);
    if (SUCCEEDED(hr1))
    {
        hr2 = CreateItemMoniker(L"!", OLESTR("myappmnk"), &appmnk);
        if (SUCCEEDED(hr2))
        {
            hr3 = GetRunningObjectTable(0, &rot);
            if (SUCCEEDED(hr3))
            {
                hr = rot->Register(ROTFLAGS_REGISTRATIONKEEPSALIVE, app_ptr, appmnk, &dwrdptr);
                rot->Release();
            }
            appmnk->Release();
        }
        app_ptr->Release();
    }
}

CoUninitialize();

The end result I'm seeking is to successfully register the application's COM object to ROT, in order to get a successful result from GetActiveObject.

Any help and any insight will be truly appreciated.

  • You are leaking all of the COM objects returned by `CoGetClassObject()`, `CreateItemMoniker()` and `GetRunningObjectTable()`. You need to call `Release()` on all of them *before* calling `CoUninitialize()`. Also, `app_ptr` needs to be declared as `IUnknown*` and typecasted to `void**` when passed to `CoGetClassObject()`, not declared as `void*` and typecasted to `IUnknown*` when passed to `Register()` – Remy Lebeau Jun 14 '19 at 02:31
  • And you are not doing any error handling to make sure that `CLSIDFromProgID()`, `CoGetClassObject()`, CreateItemMoniker()` and `GetRunningObjectTable()` all succeed before calling `Register()`. – Remy Lebeau Jun 14 '19 at 02:39
  • @RemyLebeau I've edited the code to handle the leaks with `Release()` for every successful step .. changed the declaration of `app_ptr` to `IUnknown*` and typecasted it to `void**` when passed to `CoGetClassObject()` .. However, the same E_INVALIDARG error arises. – Serag Hassouna Jun 14 '19 at 11:19
  • at which step exactly? The `Register()`? – Remy Lebeau Jun 14 '19 at 14:53
  • It's the last step .. `hr = rot->Register(ROTFLAGS_REGISTRATIONKEEPSALIVE, app_ptr, appmnk, &dwrdptr);`.. The value of `hr` is E_INVALIDARG – Serag Hassouna Jun 14 '19 at 15:03
  • Replacing `Register()` with `BindMoniker()` gives the same E_INVALIDARG error .. the line is `hr2 = BindMoniker(appmnk, dwrdptr, IID_IUnknown, (void **)app_ptr);` .. I'm confused about this moniker & app pointer issue, can't find a clean way to connect the object to the moniker in order to enable `Register()` to succeed. – Serag Hassouna Jun 15 '19 at 15:31

0 Answers0