Как вы инициализируете незарегистрированную COM DLL?

Недавно некоторые наши клиенты потеряли свои файлы XAudio2_7.dll из своего каталога C:/Windows/System32, и теперь они не могут слышать звук. Переустановки DirectX или регистрации DLL обычно достаточно для решения этой проблемы, но мы ищем решение, которое не требует прав администратора. Это для Windows 7. Приложения написаны на CPP, и некоторые из них являются 32-разрядными, а остальные - 64-разрядными.

Локальная копия XAudio2_7.dll находится в том же каталоге exe, но она не загружается, если эта dll не зарегистрирована, поскольку это COM dll. Регистрация для текущего пользователя (с использованием "Regsvr32.exe /n /i:user XAudio2_7.dll") не работает, так как DLL не реализует требуемый интерфейс "DllInstall".

Один из подходов, которые я попробовал, состоит в том, чтобы статически связать.lib XAudio вместо использования динамической ссылки. Microsoft не распространяет XAudio2_7.lib с DirectX SDK. "Никакие версии DirectX SDK не содержат библиотеку импорта xaudio2.lib. Версии DirectX SDK используют COM для создания нового объекта XAudio2". msdn.microsoft.com/en-us/library/windows/desktop/microsoft.directx_sdk.xaudio2.xaudio2create%28v=vs.85%29.aspx

Конечно, это говорит о том, что может быть невозможно использовать статическую библиотеку XAudio, даже если я ее создал, поскольку она звучит так, как будто она зависит от внешних объектов, определенных в других библиотеках. Это все еще стоило проверить на случай, если моя гипотеза неверна.

Выполните шаги, указанные в этой ссылке: adrianhenke.wordpress.com/2008/12/05/create-lib-file-from-dll/

Я не очень далеко продвинулся с этим методом. За исключением статей, которые были датированы, с этим была пара проблем. Ссылка MS в блоге упоминает, что это для 32-битных библиотек. Даже для 32-битных библиотек dumpbin не работал, поскольку он экспортировал только функции интерфейса. Дамп файла C:\XAudioTest\32Bit\XAudio2_7.dll

File Type: DLL

  Section contains the following exports for xaudio2.dll

    00000000 characteristics
    4C064181 time date stamp Wed Jun 02 07:33:21 2010
        0.00 version
           1 ordinal base
           4 number of functions
           4 number of names

    ordinal hint RVA      name

          1    0 00030AA0 DllCanUnloadNow
          2    1 00031150 DllGetClassObject
          3    2 00031470 DllRegisterServer
          4    3 000314D0 DllUnregisterServer

  Summary

        C000 .data
        1000 .no_bbt
        4000 .reloc
        1000 .rsrc
       7B000 .text

Позже я нашел эту цитату из другой статьи MSDN. "Стандарт COM требует, чтобы библиотеки DLL DLL экспортировали DllCanUnloadNow, DllGetClassObject, DllRegisterServer и DllUnregisterServer. Обычно они больше ничего не экспортируют. Это означает, что вы не можете получить информацию об объекте или методе COM с помощью dumpbin.exe". msdn.microsoft.com/en-us/library/aa446532.aspx

Я также пытался использовать стороннюю программу, которая утверждает, что она способна создать.lib из COM DLL. www.binary-soft.com/dll2lib/dll2lib.htm

Хотя это сгенерировало 32-битный файл.lib, компиляция с файлом lib генерировала неразрешенные внешние символы. Эта утилита поставляется с методами для обработки неразрешенных символов, но ввод чего-либо в Symbol Finder или Advanced Conversion Options может привести к сбою. Просматривая последние заметки о выпуске (3.00), я обнаружил, что они добавили поддержку Vista и не упоминают о Windows 7. Также это не работает для 64-битных DLL.

Я попробовал другой подход, чтобы изменить последовательность инициализации для использования незарегистрированной COM DLL, описанной в этой ссылке: Использовать COM-объект из DLL без регистрации Код инициализации выглядит примерно так:

    HMODULE audioLib = LoadLibrary(TEXT("XAudio2_7.dll"));
    if (audioLib == NULL)
    {
        debugf(TEXT("Failed to create COM object.  Unable to load XAudio2_7.dll library.  GetLastError:  %d"), GetLastError());
        return;
    }

    typedef HRESULT (WINAPI* Function_DllGCO) (REFCLSID, REFIID, LPVOID*);
    Function_DllGCO processAddress = (Function_DllGCO)GetProcAddress(audioLib, "DllGetClassObject");

    if (processAddress == NULL)
    {
        debugf(TEXT("COM DLL failed to find the process address to interface function 'DllgetClassObject' within the XAudio2_7.dll.  GetLastError:  %d"), GetLastError());
        return;
    }

    class __declspec(uuid("{5a508685-a254-4fba-9b82-9a24b00306af}")) xAudioGUID;
    REFCLSID classID = __uuidof(xAudioGUID);

    class __declspec(uuid("{00000001-0000-0000-c000-000000000046}")) classFactoryGUID;
    REFIID classFactoryID = __uuidof(classFactoryGUID);

    IClassFactory* ClassFactory = NULL;
    if (processAddress(classID, classFactoryID, reinterpret_cast<LPVOID*>(&ClassFactory)) != S_OK)
    {
        debugf(TEXT("Failed to execute function pointer to DLLGetClassObject.  GetLastError:  %d"), GetLastError());
    return;
    }

    class __declspec(uuid("{00000000-0000-0000-C000-000000000046}")) unknownGUID;
    REFIID unknownID = __uuidof(unknownGUID);
    if (ClassFactory->CreateInstance(NULL, unknownID, reinterpret_cast<void**>(&ClassFactory)) != S_OK)
    {
        debugf(TEXT("Class factory for XAudio2_7 failed to create an object instance.  GetLastError:  %d"), GetLastError());
        ClassFactory->Release();
        return;
    }

    if( XAudio2Create( &XAudio2, 0, AUDIO_THREAD) != S_OK ) //Fails here with error number:  1008 (An attempt was made to reference a token that does not exist.)
    {
        debugf( NAME_Init, TEXT( "Failed to create XAudio2 interface:  GetLastError:  %d" ), GetLastError());
        return;
    }
    //Do other things

Все вызовы функций WinAPI прошли, кроме функции XAudio2Create. Я не уверен, почему XAudio2Create не использует объект, созданный на фабрике, и я не знаю, что мне нужно сделать, чтобы заставить его использовать этот объект. Я все еще исследую, что я могу сделать здесь, но трудно отлаживать библиотеки с закрытым исходным кодом.

До того, как я узнал о COM DLL, я пытался использовать метод перенаправления DLL, чтобы заставить приложение использовать определенную DLL. Используя описанный здесь процесс: перенаправление DLL с использованием манифестов XAudio2Create все еще не удалось. У меня нет сильной стратегии в определении того, что не так с манифестом. Я также не нашел много современной документации относительно манифестов для перенаправления DLL. Судя по всему, это в основном используется для загрузки определенной версии DLL. Я не думаю, что перенаправление DLL- это метод, который мне нужен, так как локальная копия XAudio2_7 уже есть в том же каталоге exe, что означает, что она должна иметь приоритет над XAudio2_7 в системном каталоге в соответствии с: msdn.microsoft.com/en-us/library/windows/desktop/ms682586%28v=vs.85%29.aspx

Примечание. Я удалил гиперссылки для некоторых адресов, поскольку у меня недостаточно очков репутации, чтобы опубликовать более 2 ссылок.

1 ответ

Решение
Другие вопросы по тегам