Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Calling RegisterActiveObject from within a windows service

415 views
Skip to first unread message

Andy Johnson

unread,
Oct 3, 2008, 5:56:12 AM10/3/08
to
Hi,

Summary: Is there any reason why a windows service shouldn't be able
to add a com object to the running object table?


Details:

I have a c++ console app that can run either standalone or as a
windows service. When it starts-up it instantiates (using
CoCreateInstance) an inproc COM object and adds it to the running
object table by calling RegisterActiveObject.

This works ok when the app runs standalone. I can use the irotview
utility to verify that the object is in the ROT, and can run another
app that successfully locates the object in the ROT.

However, when I run the app as a service, the com objects _doesn't_
seem to get added to the rot. irotview doesn't show it, and my other
app can't fint it either. The service uses extensive logging, and I am
confident that all RegisterActiveObject is being called and that COM
calls are returning S_OK. I have tried running the service as both
local system and my normal (admin) user.

The com object is created and registered on a seperate thread, not on
the main thread (when running standalone) or the thread supplied by
the service control manager (when running as a service).

I'm going to try simplifying the code down into a simpler test case,
but does anyone know any reason why a service shouldn't be able to
register an active com object?

Thanks,

Andy

René König

unread,
Oct 3, 2008, 8:26:28 AM10/3/08
to
Hello Andy!

Andy Johnson schrieb:


> Summary: Is there any reason why a windows service shouldn't be able
> to add a com object to the running object table?

Yes, an object registered is only visible to the user that registered
the object. Since your service is not running under the account of the
interactive user, it is invisible for you.

However, you can make it visible to other users, but you need to
reimplement RegisterActiveObject then. The key is the flag
ROTFLAGS_ALLOWANYCLIENT, for example:

HRESULT MyRegisterActiveObject(IUnknown* pUnk, REFCLSID rclsid, DWORD
dwFlags, DWORD* pdwRegister)
{
IRunningObjectTable* pROT = NULL;
IMoniker* pMoniker = NULL;
HRESULT hr;
OLECHAR szCLSID[MAX_PATH];

if(!StringFromGUID2(rclsid, szCLSID, (sizeof(szCLSID) /
sizeof(szCLSID[0]))))
return(E_UNEXPECTED);

if(FAILED((hr = GetRunningObjectTable(0, &pROT))))
return(hr);

if(SUCCEEDED((hr = CreateItemMoniker(L"!", szCLSID, &pMoniker))))
{
hr = pROT->Register(((dwFlags & ACTIVEOBJECT_WEAK) ? 0 :
ROTFLAGS_REGISTRATIONKEEPSALIVE ) | ROTFLAGS_ALLOWANYCLIENT, pUnk,
pMoniker, pdwRegister);
pMoniker->Release();
}

pROT->Release();
return(hr);
}


Hope this helps,
Rene

Andy Johnson

unread,
Oct 3, 2008, 10:51:29 AM10/3/08
to

Rene,

Thanks for your very helpful response! I tried your code.

Running the app stand-alone, the call to IRunningObjectTable::Register
(in your code) fails with hr = 0x80004015. This seems to be
WBEMMOF_E_TYPE_MISMATCH, which visual studio says means "The class is
configured to run as a security ID different from the caller". I don't
understand this, as have not configured any security settings (either
in the registry or by calling CoInitializeSecurity). MSDN says the
hresult means "The value specified cannot be made into the appropriate
type.", which is more likely but I still don't understand why I'm
seeing this.

If I change the call to CreateItemMoniker to CreatePointerMoniker then
IRunningObjectTable::Register fails with E_NOTIMPL.

Running the app as a service, it appears to fail in the same way.

I call MyRegisterActiveObject almost immediately after creating the
object - same function, same thread.

Can you offer any advice about why this might be happening?

Thanks,

Andy

René König

unread,
Oct 3, 2008, 11:56:59 AM10/3/08
to
Hi Andy!

Andy Johnson schrieb:


> Running the app stand-alone, the call to IRunningObjectTable::Register
> (in your code) fails with hr = 0x80004015. This seems to be

It's most likely that you did not register your executable's name under
the AppID key. As you can see in the documentation of
IRunningObjectTable::Register, you have to do so: "A server registered
as either LocalService or RunAs can set the ROTFLAGS_ALLOWANYCLIENT flag
in its call to Register to allow any client to connect to it. A server
setting this bit must have its executable name in the AppID section of
the registry that refers to the AppID for the executable."

See:
http://msdn.microsoft.com/en-us/library/ms680747.aspx

Rene

Andy Johnson

unread,
Oct 6, 2008, 6:05:44 AM10/6/08
to

Hi René,

Thanks for the response. I was away from home over the weekend and had
no net access.

The COM object is actually an inproc server dll. The windows service
instantiates it using CoCreateInstance(... ,
CLSCTX_INPROC_SERVER, ...) and adds it to the ROT. The windows service
itself isn't a com server.

The server does have an AppID entry in the registry (created by the
ATL wizard) but its empty. My understanding is that this is normal for
a dll server. The only documentation I can find for AppID values seem
to relate to .exe servers. Am I missing something here?

Do I need to explicitly call CoInitializeSecurity in the server (and
client?) to allow communication across window station boundaries?

Andy

Alexander Nickolov

unread,
Oct 30, 2008, 2:23:49 PM10/30/08
to
Well, ROT is not intended to be used for in-proc objects, it's
designed for use by out-of-proc servers. You may have to make
your executable a fake COM server for the COM object in your
DLL.

--
=====================================
Alexander Nickolov
Microsoft MVP [VC], MCSD
email: agnic...@mvps.org
MVP VC FAQ: http://vcfaq.mvps.org
=====================================

"Andy Johnson" <andyjo...@gmail.com> wrote in message
news:99271322-6038-4de3...@h60g2000hsg.googlegroups.com...

0 new messages