Я могу использовать 2010-е Visual Studio компилятор C++ с Библиотекой времени выполнения C++ 2008 Visual Studio?

У меня есть приложение, которое должно воздействовать на Windows 2000. Я также хотел бы использовать Visual Studio 2010 (главным образом из-за изменения формулировки auto ключевое слово). Однако я нахожусь в чем-то вроде, связывают, потому что мне нужно приложение, чтобы смочь воздействовать на более старую ОС, а именно:

  • Windows 2000
  • Windows XP RTM
  • Windows XP SP1

Библиотека времени выполнения 2010-х Visual Studio зависит от EncodePointer / DecodePointer API, который был представлен в Windows XP SP2.

Если пользование альтернативной библиотекой времени выполнения возможно, будет это взламывать код, который полагается на C++ 0x опции, добавленные в VS2010, как std::regex?

36
задан John Saunders 20 March 2010 в 23:56
поделиться

7 ответов

Решение Сумы выглядело многообещающе, но оно не работает: символы __imp__*@4 должны быть указателями на функции, а не сами функции. К сожалению, я не знаю, как заставить Visual C++ выдавать указатель с такой генерацией имени... (ну, __declspec(naked) в сочетании с __stdcall делает свое дело , но тогда я не знаю, как выдать указатель).

Если использование ассемблера во время сборки допустимо, решение довольно тривиально — соберите следующий код с помощью FASM и свяжите с созданным объектным файлом, и вуаля — никаких ссылок EncodePointer/DecodePointer в exe:

use32
format ms coff

section ".data" data
public __imp__DecodePointer@4
__imp__DecodePointer@4 dd dummy

public __imp__EncodePointer@4
__imp__EncodePointer@4 dd dummy

section ".text" code
dummy:
mov eax, [esp+4]
retn 4
11
ответ дан 27 November 2019 в 05:39
поделиться

Вариант 1 - создайте измененную версию среды выполнения 2010, которая перенаправляет вызовы проблемного API в предоставленную вами библиотеку DLL. Я не знаю, насколько это будет легко или сложно - надеюсь, это всего лишь небольшая настройка таблицы символов, но это зависит от формата файла - и, конечно, вы, скорее всего, столкнетесь с оговоркой о реверс-инжиниринге лицензии. .

Вариант 2 - Сравните экспортированные символы в двух разных версиях библиотек времени выполнения. Если символы совпадают, у вас хорошие шансы на совместимость, но никаких гарантий. Возможно даже, что форматы файлов lib разные.

Вариант 3 - Проверьте, можете ли вы получить доступ к источникам среды выполнения через MSDN или аналогичный, особенно для создания исправленной версии.

Вариант 4. Проверьте, можете ли вы использовать компилятор 2010, но более старый компоновщик, возможно, настроенный в ваших решениях как настраиваемый шаг сборки. Опять же, это зависит от того, имеют ли файлы obj и lib один и тот же формат, но вы можете написать небольшую утилиту для исправления простых различий, таких как номера версий в заголовке. У старого компоновщика не должно возникнуть проблем с компоновкой в ​​старой среде выполнения - при условии, что объекты нового компилятора совместимы с ним.

Вариант 5 - создать в 2010 году библиотеки DLL, которым не нужна собственная среда выполнения, но которые загружаются и размещаются приложением, созданным с использованием более старого компилятора.Выполнение требования «без времени выполнения» для ваших DLL может означать, что многие ваши библиотеки, конечно же, должны быть встроены в хост-приложение, и вам может потребоваться предоставить свои собственные интерфейсы (через хост-приложение) для библиотечных функций, которые вам нужны для работы. with - особенно материал о распределении памяти.

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

3
ответ дан 27 November 2019 в 05:39
поделиться

Это было бы намного проще, если бы вам разрешили использовать DLL. По сути, напишите EXE, который вообще не требует функций времени выполнения C, используя функцию компоновщика / ENTRYPOINT. После того, как вы проверили, что ваши основные предварительные требования выполнены, и сообщили о любых проблемах пользователю с помощью только предоставляемых Windows API, доступных во всех целевых ОС (например, MessageBox), затем вызовите LoadLibrary, чтобы запустить DLL, которая содержит основную часть вашей логики. . Эта DLL может использовать среду выполнения VS2010 как обычно. Вы даже можете избежать развертывания двух отдельных файлов, распаковав DLL из ресурса, содержащегося в вашем основном .EXE, при запуске. (Вы можете сделать это полностью в памяти, не записывая .DLL на диск, но не в том случае, если вы хотите воспользоваться загрузчиком Windows PE для исправления всего вашего импорта).

3
ответ дан 27 November 2019 в 05:39
поделиться

Создайте .LIB, который реализует недостающую функциональность, и свяжите его перед KERNEL32.LIB.

Вам нужно будет использовать параметр компоновщика /NODEFAULTLIB:kernel32.lib, чтобы вы могли поместить свой w2kcompat.lib перед kernel32.lib.

0
ответ дан 27 November 2019 в 05:39
поделиться

Обычный способ решения этой проблемы - создать собственную версию CRT. Инструкции для него можно найти здесь . Вам просто нужно отредактировать код, чтобы игнорировать EncodePointer и DecodePointer . (Для этого уже должен быть #define .)

Есть еще две незначительные вещи, которые вам нужно сделать:

  • Перейдите в настройку Linker-> Additional Library Directories и установите C: \ Microsoft Visual Studio 9.0 \ VC \ lib в качестве первого пути для поиска. (Я предполагаю, что вы использовали каталог установки по умолчанию, в противном случае измените при необходимости.)
  • Измените версию подсистемы в заголовке PE на 5.00 (используйте бесплатный CFF Explorer Suite , если вы этого не сделаете. у меня под рукой есть другой инструмент).

Это должно позволить вашей программе работать как в Windows 2000, так и в более поздних версиях.

4
ответ дан 27 November 2019 в 05:39
поделиться

Самое простое решение - просто установить для набора инструментов платформы в настройках проекта в VS2010 значение v900, при котором будут использоваться библиотеки и компилятор Visual Studio 2008. Это также означает, что вы теряете функции C ++ 0x, такие как auto , но, честно говоря, обойти это с некоторыми typedef , вероятно, проще, чем создавать свою собственную версию CRT или другие более сложные решения. В качестве альтернативы просто используйте VS2008! Я не знаю, есть ли другие функции C ++ 0x, которые имеют решающее значение для вашего приложения, но вы не упомянули, кроме std :: regex , который, как мне кажется, все еще присутствует в наборе инструментов v900. в пространстве имен технического отчета 1 ( std :: tr1 :: regex ).

Исходя из моего впечатления, я могу предсказать, что неудобство запуска библиотек VS2010 на XP SP1 больше, чем удобство функций C ++ 0x, так что в целом это того не стоит.

24
ответ дан 27 November 2019 в 05:39
поделиться

Вы не можете использовать 2008 CRT, но можете запретить связывание новых функций DecodePointer / EncodePointer из ядра. Заменить новые функции заглушками довольно просто.

Можно попробовать следующее: Поместите такой код в исходный код main.cpp:

extern "C" {

  void *__stdcall _imp__DecodePointer(void *x) {return x;}
  void *__stdcall _imp__EncodePointer(void *x) {return x;}

};

Вышеупомянутое не работает. Хотя основная идея верна, исполнение должно быть немного другим. Как описано snemarch в комментарии и в другом ответе , __ imp __ не может быть вызовом функции, только указателем на нее. Поскольку создание указателя напрямую компилятором не представляется возможным, вам необходимо собрать следующий код с помощью MASM и связать его с созданным объектным файлом.

.model flat

.data
__imp__EncodePointer@4 dd dummy
__imp__DecodePointer@4 dd dummy
EXTERNDEF __imp__EncodePointer@4 : DWORD
EXTERNDEF __imp__DecodePointer@4 : DWORD

.code
dummy proc
mov eax, [esp+4]
ret 4
dummy endp

end

Символы из проекта имеют преимущество перед символами из библиотек. Библиотеки DLL связаны с использованием частей .lib, которые содержат только __ imp __ «векторы», переходящие в реальные функции. Заменяя __ imp __ «векторы», вы не касаетесь связывания DLL, вы заменяете часть .lib. Я подтвердил, что больше нет зависимости exe от DecodePointer / EncodePointer.

Предпосылки

Статически связанная библиотека добавляет в приложение только используемые функции. Можно найти, какая конкретная функция CRT привносит в этот новый API, используя подробный вывод о ходе работы компоновщика:

Found __imp__EncodePointer@4
  Referenced in LIBCMT.lib(crtmboxw.obj)
  Referenced in LIBCMT.lib(invarg.obj)
  Referenced in LIBCMT.lib(handler.obj)
  Referenced in LIBCMT.lib(onexit.obj)
  Referenced in LIBCMT.lib(cmiscdat.obj)
  Referenced in LIBCMT.lib(tidtable.obj)
  Referenced in LIBCMT.lib(hooks.obj)
  Referenced in LIBCMT.lib(winsig.obj)
  Referenced in LIBCMT.lib(rand_s.obj)

Found __imp__DecodePointer@4
  // ... same list, only order differs ... 

Это показывает, что новые API используются в некоторых CRT для обеспечения большей безопасности для некоторых функций, которые, как считается, обеспечивают частые векторы атак. .

Приложив некоторые усилия, можно было бы использовать LoadLibrary / GetProcAddress для обеспечения реальной функциональности, которую предлагает ОС, но я не думаю, что это действительно что-то принесет. Функции времени выполнения, которые используют DecodePointer / EncodePointer, на самом деле не нуждаются в нем для обеспечения какой-либо кодировки, все, что им нужно, - это симметричное кодирование. Вам действительно не нужна повышенная безопасность (среда выполнения VS 2008 также не предоставит вам ее).

Надеюсь, вас не ждут другие препятствия - у меня нет доступа к системе Win2k или XP pre SP2, поэтому я не могу попробовать. Если есть какие-либо флаги заголовка exe, препятствующие даже попытке запустить exe в таких системах, их должно быть легко изменить.

24
ответ дан 27 November 2019 в 05:39
поделиться
Другие вопросы по тегам:

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