Две версии API в одной DLL
Добрый день!
Наше приложение защищается через API, автозащита не используется (например, потому, что приложение должно работать и без ключа, получив лицензию от Web-сервера или вообще работать в режиме без защиты).
Сотрудничаем с Guardant давно, начинали еще с Fidusов. Новые ключи (Sign, Code, Time) не используем т.к. их функциональность нам не нужна, покупаем, как старые клиенты, Stealth II и его сетевой вариант. Поэтому сидели на API 5 версии и соответственно использовали сервер 5-версии.
Все было хорошо, пока один из клиентов не обратился к нам с просьбой реализовать поддержку 7 сервера – у них все виртуализировано, железка для проброса USB одна, она подключена к виртуалке, где живут все их серверы ключей. Там уже стоит сервер 7, т.к. есть приложение, требующее именно эту версию сервера. Поставить 5 сервер вместе с 7 на один компьютер невозможно (вот интересно, почему?), 7 сервер не виден из приложения, защищенного 5 версией API, покупать вторую железку для проброса и заводить еще одну виртуалку клиент, естественно не хочет. В общем вот такая совместимость версий.
Пересобрать приложение с новой версией API не проблема, но в этом случае старые клиенты, использующие 5 версию сервера после обновления (а приложение довольно часто обновляется) просто не смогут подключиться к серверам, завалят нас вопросами и не будут счастливы от перспективы писать запросы в IT-отделы об обновлении сервера, и получить возможность работать дней через 10, пока там вся бюрократия сработает.
В общем появилось желание собрать программу с ОБОИМИ версиями API. Все обращения к API происходят из DLL, написанной на C++. DLL линкуется с GrdFWMC.obj, использовать DLL-версию API не хочется (мне кажется, слишком легко ее подменить). Слинковать приложение с GrdFWMC.obj 5 версии одновременно с GrdFWMC.obj 7 версии не получается. Заводить отдельную новую DLL для 5 версии API и линковать старую DLL с 7 версией не хочется, т.к. лень напрягаться над тем, как передать из этой новой DLL информацию о найденном ключе каким-то скрытым образом (иначе ее также легко подменят).
В итоге я в простом текстовом редакторе (FAR) поменял имена функций Guardant API в GrdFWMC.obj 5 версии, а сам файл переименовал в GrdFWMC_v5_renamed.obj. Переименовал вот так:
016 00036DD6 SECT1 notype () External | _Gr5SetWorkMode@12
051 0003F756 SECT1 notype () External | _ns5FindNext@4
073 000402B6 SECT1 notype () External | _nn5Check@4
Т.е. заменил префикс _Grd на _Gr5, _nsk на _ns5 и _nnk на _nn5.
После этого DLL стала успешно линковаться c GrdFWMC.obj 7 версии и GrdFWMC_v5_renamed.obj.
После этого я внес соответствующие исправления в GrdAPI_v5_renamed.h и при тестировании убедился, что DLL успешно обращается (в зависимости от задаваемой в настройках опции) к 5 или к 7 версии API и находит соответственно сервера 5 и 7 версии.
Конечно, перед обращением к 5 версии вызывается Shutdown для 7 версии и наоборот. Только GrdDllMain() и Gr5DllMain остаются вызванными одновременно все время жизни приложения.
В общем, все работает, но конечно есть вопрос поводу возможных проблем с таким одновременным использованием двух версий API в одной DLL. Хотелось бы услышать ответ от разработчиков защиты, но не в духе «мы это не поддерживаем».
Ну и в конце хочется сказать по поводу совместимости. Это очень важный момент для любого ПО – в том числе и для Вашего. За все время мы купили у Вас 1700 ключей, и вот делать нам и нашим клиентам больше нечего, как разруливать несовместимости версий чужого ПО.
Очень бы хотелось в качестве обеспечения совместимости получить возможность использовать обе версии сервера 5 и 7 на одном компьютере (что там сложного?) или работу 7 сервера в режиме совместимости с 5 версией ПО.
С уважением,
Алексей