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

ATL bug with per user registration of COM component

15 views
Skip to first unread message

stu...@googlemail.com

unread,
Feb 5, 2009, 9:51:34 AM2/5/09
to
I have an exe which I am registering as a COM component. This runs
out of process with an Excel session. Historically we have been
installing this as a machine level component but this causes issues as
it requires administrator access. Recently we began investigating per
user registration but there seems to be a bug in atlbase.h that is
preventing it.

We are deriving our application class from CAtlExeModuleT, which takes
responsibility for the command line parsing and the class
registration.

When doing this as a permissoned user we have no issue doing machine
wide registration, into HKEY_LOCAL_MACHINE. However, when we run this
as either a permissoned user or a user that has no write access to
HKEY_LOCAL_MACHINE the registration fails silently.

I've tracked this down to a method on a class in atlbase.h,
ATL::CAtlServiceModuleT<T,nServiceNameID>::RegisterAppId, which always
attempts to write the registry key to HKCR. When per user
registration is set, via AtlSetPerUserRegistration, this fails.

MSDN states:

“To change the settings for the interactive user, store the changes
under KEY_CURRENT_USER\Software\Classes rather than
HKEY_CLASSES_ROOT.”

So, it seems as if the registration code in the ATL library is not
correctly handling this flag, and the fix is simply to redirect to the
current user registry space based upon the result of
AtlGetPerUserRegistration(). I fancy this shouldn’t be necessary but
experimentation has demonstrated that this change is sufficient and
necessary.

Has anyone encountered this problem and is there and 'official' fix or
a workaround available that doesn't involving hacking atlbase.h?


<snip>
CRegKey keyAppID;
LONG lRes = keyAppID.Open(HKEY_CLASSES_ROOT, _T("AppID"),
KEY_WRITE);
if (lRes != ERROR_SUCCESS)
return AtlHresultFromWin32(lRes);

</snip>

becomes:

<snip>
CRegKey keyAppID;
bool isPerUser;
AtlGetPerUserRegistration(&isPerUser);
if (lRes != ERROR_SUCCESS)
return AtlHresultFromWin32(lRes);

LONG lRes;
if (isPerUser == true)
{
//Bug in atlbase.h!!!!!
lRes = keyAppID.Open(HKEY_CURRENT_USER, _T("Software\\Classes\
\AppID"), KEY_WRITE);
}
else
{
lRes = keyAppID.Open(HKEY_CLASSES_ROOT, _T("AppID"), KEY_WRITE);
}
if (lRes != ERROR_SUCCESS)
return AtlHresultFromWin32(lRes);
</snip>

Igor Tandetnik

unread,
Feb 5, 2009, 10:42:47 AM2/5/09
to

stu...@googlemail.com wrote:
> We are deriving our application class from CAtlExeModuleT, which takes
> responsibility for the command line parsing and the class
> registration.
>
> When doing this as a permissoned user we have no issue doing machine
> wide registration, into HKEY_LOCAL_MACHINE. However, when we run this
> as either a permissoned user or a user that has no write access to
> HKEY_LOCAL_MACHINE the registration fails silently.

Use RegOverridePreDefKey to redirect HKCR to HKCU\Software\Classes
--
With best wishes,
Igor Tandetnik

With sufficient thrust, pigs fly just fine. However, this is not
necessarily a good idea. It is hard to be sure where they are going to
land, and it could be dangerous sitting under them as they fly
overhead. -- RFC 1925


Roman Ryl...

unread,
Feb 5, 2009, 1:42:36 PM2/5/09
to
Hi,

> Use RegOverridePreDefKey to redirect HKCR to HKCU\Software\Classes

It is very powerful, esp. for the mentioned purpose but should be used
with care because it prevents from reading from actual HKCR. For
instance, as a part of registration it is necessary to read from
registry (e.g. to read a value which then used to build path to
another key) and HKCR is redefined so the existing value is
inaccessible.

Roman

Igor Tandetnik

unread,
Feb 5, 2009, 2:03:18 PM2/5/09
to

I don't know when or why it would be necessary to read from HKCR when
registering your server. In any case, HKCR (when not redirected) is just
a blended view of HKCU\Software\Classes and HKLM\Software\Classes. When
you read from HKCR, the system tries HKCU first, then if the value is
not there falls back to HKLM. Writes always go to HKLM.

Redirecting HKCR prevents reads from falling back to
HKLM\Software\Classes. But of course you can always read from
HKLM\Software\Classes explicitly.

Roman Ryl...

unread,
Feb 5, 2009, 2:18:58 PM2/5/09
to
Igor,

> I don't know when or why it would be necessary to read from HKCR when
> registering your server.

Suppose you need to add a shell property page handler to .dll files as
a part of DLL registration process. First step is to read default
value from HKCR\.dll (which is typically "dllfile") in order to build
registry key HKCR\dllfile. It is going to fail if the key was
redefined...

Of course you are correct about blending, and this is my point that
registration would generally work on redefined key but still there
might be issues in special cases.

Roman

stu...@googlemail.com

unread,
Feb 5, 2009, 5:40:21 PM2/5/09
to
Thanks for all the advise, redirecting the key will work nicely in
this case.

Glad I don't have to start version controlling atl files, *phew*.

0 new messages