Зарегистрируйте прокси/заглушку в HKEY_CURRENT_USER

Компилятор MIDL генерирует код для прокси/заглушки с процедурами регистрации, которые записываются в HKEY_LOCAL_MACHINE. Есть ли способ (желательно без взлома сгенерированного MIDL кода и без обхода всего этого сгенерированного кода в пользу пользовательского кода) зарегистрировать сгенерированный MIDL p/s в HKEY_CURRENT_USER?

Кроме того: будет ли это работать, если и p/s, и COM-сервер зарегистрированы для каждого пользователя? Я только что обнаружил (после очень разочаровывающих 48 часов), что p/s, зарегистрированный для всей машины, не будет работать правильно, если COM-сервер зарегистрирован для каждого пользователя. В частности, в этих обстоятельствах логика асинхронного вызова (ICallFactory::CreateCall) p/s не будет работать.


person Michael Gunter    schedule 15.05.2015    source источник
comment
Нет, не совсем. Генерация прокси является высокоавтоматизированной, нажатием кнопки, никогда не ошибитесь при построении. Код находится в заголовочном файле <RpcProxy.h> SDK, он использует NdrDllRegisterProxy(). Нет ничего невозможного, но вы должны любить делать ошибки.   -  person Hans Passant    schedule 15.05.2015
comment
Это то, о чем я думал. Я просто вручную настроил свой реестр HKEY_CURRENT_USER, и он работает. Так что пока P/S и COM-сервер зарегистрированы в одном и том же улье, все выглядит хорошо.   -  person Michael Gunter    schedule 15.05.2015
comment
Нельзя было собрать как есть, без модификаций, а потом прописать с перенаправлением на HKCU? Это выглядит самым безопасным, потому что вы действительно не вмешиваетесь в магию внутри P/S и делаете это, переключая реестр.   -  person Roman R.    schedule 15.05.2015
comment
Единственный способ сделать это, насколько мне известно, — использовать ATL::AtlSetPerUserRegistration(true), что влияет только на регистрацию, выполняемую ATL.   -  person Michael Gunter    schedule 15.05.2015
comment
Это возможности ATL, а я говорю о другом. Вы загружаете библиотеку PS, а затем RegOverridePredefKey HKLM куда-то в безопасное место, затем вы делаете DllRegisterServer и перенаправляете регистрацию. Поскольку вы уже добились определенных успехов в ручной регистрации, этот подход к перенаправлению выглядит работоспособным и, что более важно, может автоматизировать перенаправление в целом.   -  person Roman R.    schedule 16.05.2015
comment
Ах, конечно. Я когда-либо использовал этот API только для работы, подобной установке. Рассмотрю это. Спасибо!   -  person Michael Gunter    schedule 16.05.2015


Ответы (1)


Использование RegOverridePredefKey — правильный ответ. Тогда зарегистрируйтесь через:

regsvr32 /n /i:user C:\src\myCode.dll

С /i:user regsvr32 вызывает вашу функцию DllInstall вместо DllRegisterServer.

Пример реализации DllInstall:

extern "C" STDAPI DllInstall(BOOL bInstall, _In_opt_  LPCWSTR pszCmdLine)
{
    HRESULT hr = E_FAIL;
    static const wchar_t szUserSwitch[] = L"user";

    if (pszCmdLine != NULL)
    {
        if (_wcsnicmp(pszCmdLine, szUserSwitch, _countof(szUserSwitch)) == 0)
        {
            ATL::AtlSetPerUserRegistration(true); // is this really needed??
        }
    }

    LSTATUS status = RegCreateKeyEx(HKEY_CURRENT_USER, L"SOFTWARE\\Classes", 0, 0, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, 0, &hkcu_classes, &disposition);
    if (status == ERROR_SUCCESS)
    {
        status = RegOverridePredefKey(HKEY_CLASSES_ROOT, hkcu_classes);
    }
    hr = HRESULT_FROM_NT(status);

    if (SUCCEEDED(hr))
    {
        if (bInstall)
        {
            hr = DllRegisterServer();
            if (FAILED(hr))
            {
                DllUnregisterServer();
            }
        }
        else
        {
            hr = DllUnregisterServer();
        }
    }
}
person joeking    schedule 13.04.2021