Предотвращение переполнений стека в обертке DLLs

У меня есть программа, к которой я добавляю полноэкранные эффекты последующей обработки. У меня нет источника для программы (это является собственным, хотя разработчик действительно отправлял мне копию отладочных символов, .map формат). У меня есть код для записанных эффектов и работа, никакие проблемы.

Моя проблема теперь связывает два.

Я попробовал два метода до сих пор:

Используйте Обходы для изменения таблицы импорта исходной программы. Это работает отлично и, как гарантируют, будет стабильно, но пользователь, с которым я говорил, не доволен им, это требует установки (вне извлечения архива), и существует некоторый вопрос, если исправление программы с Обходами допустимо в соответствии с EULA. Так, та опция отсутствует.

Другая опция является традиционной заменой DLL. Я перенес OpenGL (opengl32.dll), и мне нужна программа для загрузки, мой DLL вместо системной копии (просто отбрасывают его в папке программы с правильным именем, это легко).

Мне затем нужен мой DLL для загрузки платформы Cg и времени выполнения (который полагается на OpenGL), и несколько других вещей. Когда Cg загружается, он вызывает некоторые мои функции, которые вызывают функции Cg, и я склонен получать переполнения стека и бесконечные циклы. Я должен смочь любому, включают Cg DLLs в подкаталог и все еще используют их функции (не уверенный, если возможно иметь мою точку таблицы импорта DLLs к DLL в подкаталоге), или я должен динамично связать их (который я не сделал бы, только для упрощения процесса сборки), что-то, чтобы вынудить их обратиться к файлу системы (не моя пользовательская замена).

Вся цепочка: Загрузки программы DLL (названный opengl32.dll). DLL загрузки Cg.dll и динамично связывается (GetProcAddress) с sysdir/opengl32.dll. Мне теперь нужен Cg.dll, чтобы также обратиться к sysdir/opengl32.dll, не DLL A.

Как это было бы сделано?Править: Как это было бы сделано легко, не используя GetProcAddress? Если ничто иное не работает, я готов отступить к этому, но я быть бы если вообще возможный.

Edit2: Я просто споткнулся через функциональный SetDllDirectory в документах MSDN (на полностью несвязанном поиске). На первый взгляд это похоже на то, в чем я нуждаюсь. Это правильно, или я недооцениваю? (прочь для тестирования его теперь)

Edit3: я решил эту проблему путем выполнения вещи немного по-другому. Вместо того, чтобы отбросить OpenGL32.dll, я переименовал свой DLL к DInput.dll. Мало того, что это имеет преимущество необходимости экспортировать одну функцию вместо хорошо более чем 120 (для программы, Cg и GLEW), я не должен волноваться о функциях, отбегающих в (я могу связаться с OpenGL, как обычно). Для вхождения в вызовы, я должен прервать, я использую Обходы. В целом, это работает намного лучше. Этим вопросом, тем не менее, является все еще интересная проблема (и надо надеяться будет полезно для кого-либо еще пытающегося сделать сумасшедшие вещи в будущем). Оба ответы хороши, таким образом, я еще не уверен, чтобы выбрать...

6
задан ssube 4 May 2010 в 03:30
поделиться

2 ответа

SetDllDirectory, вероятно, не будет работать. Cg.dll, скорее всего, просто ссылается на OpenGL.dll. Когда ОС загружает Cg.dll, она видит, что уже есть загруженный модуль с таким именем (ваш), поэтому она связывает Cg с ним, а не отправляется на поиски другой копии. То есть, порядок поиска, который изменяет SetDllDirectory, даже не вступает в игру, потому что ОС не делает никакого поиска.

Я подозреваю, что лучшим вариантом для вас будет обнаружение реентерабельных вызовов вашей библиотеки. Когда вы обнаружите такой вызов, вместо того, чтобы делать свою собственную обработку, перенаправьте вызов непосредственно в настоящую библиотеку OpenGL, на которую у вас есть ссылка благодаря вызову LoadLibrary, а затем GetProcAddress для каждой из функций библиотеки.

1
ответ дан 17 December 2019 в 20:29
поделиться

Вы можете использовать магию контекстов активации, чтобы попытаться решить вашу проблему.

Многое зависит от того, есть ли у сторонних компонентов в вашей системе манифесты - и насколько вмешательство в эти манифесты может быть нарушением лицензии.

Чтобы решить проблемы с версией dll, в Windows XP появилась технология, называемая контекстами активации. Иногда они известны как сборки side-by-side, или даже как нечто ужасное вроде Application Isolation

Чтобы подытожить много прочитанного на небольшом пространстве: манифесты - это куски XML-данных, которые могут описывать сборку или описывать зависимость от сборок. Сборка - это манифест, плюс его dll.

Причина, по которой это существует, заключается в том, что сборка может принимать простую dll. "comctl32.dll" и номер ее версии (v6), и создать вещь с большим более уникальным именем, так что несколько версий простой dll могут быть установлены в одном и том же месте безопасно. Сборки предназначены для установки в C:\Windows\WinSxS.

Когда файл манифеста описывает dll в сборке, он называется манифестом сборки. И обычно имеет другое имя, чем dll.

Когда файл манифеста описывает сборки, которые использует dll или exe, он называется манифестом приложения, и обычно встраивается как ресурс RT_MANIFEST - в EXE с res id 1, в Dll с res id 2 - или на диске как файл с именем "appname.exe.manifest" / "dllname.dll.2.manifest". Манифесты приложений определяют вещь, называемую контекстом активации - по сути, это пространство имен, в котором windows будет искать нужные вещи. Каждый манифест создает контекст активации. Каждый контекст активации имеет отображение простых имен dll на сборки.

Так, если вы создадите сборку с вашим файлом opengl32.dll, и создадите контекст активации для app.exe, ссылающегося на (локальный opengl32.dll) файл, то, потенциально, все остальные dll могут (и будут) продолжать использовать системный opengl32.dll файл, несмотря на то, что имена очень похожи coff.

Проблема в том, что res-id манифеста приложения - 1 - означает, что он используется для создания контекста активации процесса по умолчанию - поэтому ВСЕ dll, которые не имеют собственных явных манифестов (Cg?), будут искать в пространстве процесса по умолчанию и найдут opengl32. dll

Поэтому вам нужно создать манифесты для каждой dll, которая еще не имеет своего манифеста, убедившись, что они просто НЕ ссылаются на вашу сборку opengl32.dll, что должно позволить вернуться к порядку поиска по умолчанию и найти ее в обычном месте system32.

это означает, что ваша opengl32.dll не может быть в папке exe'шника, так как эта папка ищется для dll до system32 (факт, на который вы полагаетесь для хука).

Нас спасает довольно простой порядок поиска сборок, который использует система. сначала она ищет в WinSxS. Вашей Opengl32.dll там не будет, установить ее - сложная проблема. Затем она ищет в папке exe, в подпапке с именем сборки, ПОТОМ она ищет в папке exe непосредственно манифест сборки.

Это означает, что вы можете создать сборку с названием, например: "OpenGLHook". И ваша структура папок будет выглядеть так:

\appfolder\
  app.exe
  app.exe.manifest                  - contains a dependentAssembly node to OpenGLHook
  OpenGLHook\OpenGLHook.manifest    - contains a file name=opengl32.dll
  OpenGLHook\opengl32.dll           - your hook dll
  yourimpl.dll                      - your implementation dll that linkgs to cg.dll
  cg.dll                            - cg libraries
  cg.dll.2.manifest                 - a stub manifest you put together to ensure cg
                                      doesnt use the app default activation ctx.

Хм, удачи?

1
ответ дан 17 December 2019 в 20:29
поделиться
Другие вопросы по тегам:

Похожие вопросы: