VMPKit — интеграция протектора VMProtect в Windows-приложение. Часть первая. Базовые сервисы

в 3:17, , рубрики: активация, защита приложений, протектор, я пиарюсь, метки: , ,

В данной статье я хочу рассказать о нашем продукте — VMProtect Integration Kit, или, сокращенно — VMPKit.

VMPKit создавался как библиотека функций для сохранения и чтения данных лицензии, управления правами пользователя, отображения диалога активации и диалога «О Программе», а также много другого. О некоторых проблемах, возникших у нас при встраивании протектора, можно прочитать в статье «15 проблем, возникающих при интеграции протектора в Windows-приложение». В данной статье я хочу описать и прокоментировать API VMPKit.

Часть функций VMPKit API является оберткой (иногда простой, иногда более сложной) над функциями WinAPI. В таких случаях я буду приводить используемые системные вызовы. Для тех кто не собирается приобретать VMPKit, это поможет найти примеры реализации в интернете (но возможности VMPKit не исчерпываются подобными обертками).

Содержание

Отмазка aka disclaimer

VMPKit является молодым продуктом, и нельзя говорить, что он доведен до совершенства. Если вы обнаружите в нем недоработки или ошибки, пожалуйста, не спешите оставлять гневные коментарии, попробуйте с начала связаться с нами для устранения проблемы.

О данном руководстве

Данная статья является в настоящий момент наиболее полным руководством/справочником по VMPKit. Документация на официальном сайте vmpkit.com в настоящее время отстает по полноте и детализации от данной статьи.

На кого расчитан VMPKit

VMPKit расчитан, в первую очередь, на компании, производящие заказное и полузаказное ПО, продающееся достаточно дорого небольшим тиражом, и желающие его защитить от копирования — в данном случае финансовые затраты на приобретение VMProtect (приобретается отдельно) и VMPKit сравнительно невелики и с лихвой окупятся экономией времени, которое будет сэкономлено при их совместном использовании.

Шароварщики-одиночки тоже могут воспользоваться VMPKit, для них предусмотрена персональная лицензия (для одиночек и маленьких компаний до 5 человек в штате), но, как показала практика, они не слишком заинтересовались. Это связано на наш взгляд с тем, что опытные шароварщики уже прошли все эти шаги по интеграции протектора (не обязательно VMProtect) и у них есть свои отработанные библиотеки, а начинающие предпочитают сэкономить, и считают, что они достаточно быстро сделают все сами. Тем не менее, даже если вы именно такой уверенный в себе начинающий шароварщик, не отвергайте сразу возможность использования VMPKit, а хотя бы ознакомьтесь с его возможностями.

Поддерживаемые версии Windows

VMPKit поддерживает все системы Windows NT, начиная от Windows 2000 и заканчивая последней на текущий момент Windows 8.1. Вопрос поддержки определенных версий Windows должен приниматься разработчиком конкретного приложения, VMPKit не накладывает ограничений на используемые системы.

Замечание: разработчики в основном привыкли работать на достаточно современном оборудовании, в одной из последних операционных систем Windows, и часто недооценивают количество систем, которые работают под управлением ОС Windows 2000/Windows XP. По результатам анализа посещаемости наших сайтов, доля Win2K/WinXP составляет около 15% от посещений с компьютеров с ОС Windows. И если вы ориентированы на корпоративный сектор, то я думаю, что это число можно смело умножить на два — если директор организации и зашел к вам на сайт со своего современного ноутбука с ОС Windows 8, то его подчиненные, которые никогда не заходили и скорее все не зайдут на ваш сайт, очень возможно до сих пор используют Windows XP, и директор (или его заместитель по ИТ) скорее всего обратит внимание на список операционных систем, поддерживаемых вашим приложением.

Поддерживаемые системы разработки

VMPKit прежде всего ориентирован на разработчиков, использующих C++ (MSVC, GCC MinGW и другие компиляторы C++). API VMPKit может быть также использовано из приложений Delphi (требуется адаптация заголовочного файла для языка Pascal). Заголовочные файлы API VMPKit спроектированы таким образом, чтобы поддерживать любую современную систему разработки, а также устаревшие системы разработки (такие как MSVC 6, MSVC 2003, MSVC 2005, Delphi 5-7, и т.п.) без необходимости дополнительно устанавливать Windows SDK новейших версий.

Поддержка ANSI и UNICODE

Хотя современные системы Windows являются внутри полностью юникодными, и ANSI-версии функций WinAPI оставлены только для совместимости со старыми программами, перевод старого приложения с использования ANSI на использование Unicode может быть трудоемкой задачей и не всегда оправдан по финансовым соображениям. Для поддержки подобных программ VMPKit для всех функций, использующих строки, предоставляет две версии — ANSI и UNICODE. Реализации таких функций содержат в конце имени латинскую букву 'A' или 'W', в зависимости от версии; имя функции без суффикса транслируется в соответствующее имя с суффиксом при помощи макросов также, как это принято в WinAPI.

Использование VMPKit совместно с VMProtect

При использовании VMPKit совместно с VMProtect библиотека vmpik32.dll/vmpik64.dll должна быть защищена/обработана при помощи того же ключа, что и защищаемое приложение. При создании проекта VMP следует использовать внешний, общий для обоих модулей файл ключа.

Использование VMPKit без VMProtect

VMPKit может быть использован и без VMProtect — все диалоги, а также другие функции, которые используют функциональность VMProtect по активации и проверке лицензий, принимают в качестве одного из аргументов (или нескольких, при необходимости) указатели на функции обратного вызова. Если вы захотите использовать VMPKit совместно с каким-либо другим протектором, или использовать какую-то собственную подсистему активации и лицензирования, вам необходимо будет реализовать только несколько функций и передавать в VMPKit API их адреса.

Все значения кодов ошибок и флагов статуса лицензии VMPKit приведены в соответствие с соответсвующими кодами VMProtect. При использовании VMPKit отдельно от VMProtect либо с другим протектором, либо с вашей системой активации необходимо производить отображение кодов ошибок и статуса лицензии в коды VMPKit/VMProtect.

Для возможности использования VMPKit без VMProtect в составе дистрибутива VMPKit поставляется три варианта библиотеки (отдельно для x86 и x64): Ultimate — для использования с VMProtect Ultimate + WebLM; Std — для использования с VMProtect Professional и Lite) и VmpFree — для использования без VMProtect. Lite редакция VMPKit содержит только версию библиотеки VmpFree.

VMPKit спроектирован так, что необходимости подключать VMProtect API нет, если вы не используете возможности VMProtect по защите приложений, а используете VMProtect только для лицензирования. По этой причине некоторые функции VMPKit дублируют функции VMProtect API.

Базовые сервисы

В данном разделе я опишу самые низкоуровневые функции VMPKit, на которых, как на фундаменте, строятся остальные, более высокоуровневые функции.

Вспомогательные обертки над WinAPI

BOOL VMPIKAPI VMPIK_IsUserInAdminGroup();

Функция VMPIK_IsUserInAdminGroup проверяет, входит ли текущий пользователь в группу администраторов. Возвращает FALSE, TRUE, или (BOOL)-1 если данные недоступны. Используются функции OpenProcessToken, GetTokenInformation/TokenElevationType, CreateWellKnownSid, CheckTokenMembership.

BOOL VMPIKAPI VMPIK_IsRunAsAdmin();

Функция VMPIK_IsRunAsAdmin проверяет, запущено ли приложение с правами администратора. Возвращает FALSE, TRUE, или (BOOL)-1 если данные недоступны. Используются функции AllocateAndInitializeSid, CheckTokenMembership.

BOOL VMPIKAPI VMPIK_IsProcessElevated();

Функция VMPIK_IsProcessElevated определяет, запущено ли приложение с повышенными правами. Возвращает FALSE, TRUE, или (BOOL)-1 если данные недоступны (Win2K/WinXP). Используются функции OpenProcessToken, GetTokenInformation.

DWORD VMPIKAPI VMPIK_GetProcessIntegrityLevel();

Функция VMPIK_GetProcessIntegrityLevel возвращает integrity level текущего процесса. Константы VMPIK_SECURITY_MANDATORY_UNTRUSTED_RID, VMPIK_SECURITY_MANDATORY_LOW_RID и остальные дублируют константы из Win32 SDK (для использования со старыми системами разработки). В случае ошибки возвращается значение (DWORD)-1.

BOOL VMPIKAPI VMPIK_GetVirtualizationStatus();

Функция VMPIK_GetVirtualizationStatus возвращает состояние режима виртуализации реестра и файловой системы. FALSE — виртуализация выключена, TRUE — виртуализация включена, (BOOL)-1 — состояние неизвестно (ошибка или данные недоступны — Win2K/WinXP). Используются функции OpenProcessToken, GetTokenInformation/TokenVirtualizationEnabled.

BOOL VMPIKAPI VMPIK_SetVirtualizationStatus(BOOL vst); 

Функция VMPIK_SetVirtualizationStatus устанавливает новый режим виртуализации. Значение (BOOL)-1 оставляет текущий режим без изменений.

DWORD VMPIKAPI VMPIK_GetWindowsVersion( DWORD *pMinorVersion /* optional */ );

Функция-помошник, возвращает старший номер версии ОС или 0 при ошибке.

BOOL VMPIKAPI VMPIK_IsWindowsXp();

Функция возвращает TRUE, если текущая ОС — WinXP или выше.

BOOL VMPIKAPI VMPIK_IsWindowsVista();

Функция возвращает TRUE, если текущая ОС — Windows Vista или выше.

BOOL VMPIKAPI VMPIK_IsWindows64();

Функция VMPIK_IsWindows64 возвращает TRUE, если приложение запущено под управлением 64ти-четырех разрядной версиии Windows. Корректно определяется ситуация, когда 32ух-разрядное приложение запущено под управлением Windows x64.

VOID VMPIKAPI VMPIK_GetSystemInfo(LPSYSTEM_INFO lpSystemInfo);

Функция VMPIK_GetSystemInfo использует функцию GetNativeSystemInfo, если она доступна, или GetSystemInfo в противном случае.

BOOL VMPIKAPI VMPIK_RunElevated( HWND hWnd, BOOL bElevated, LPCTSTR lpcExeName, LPCTSTR lpcParams, LPCTSTR lpcDirectory);

Функция VMPIK_RunElevated позволяет запустить приложение с повышенными правами (появляется диалог подтверждения UAC или диалог ввода пароля администратора для систем Win2K/WinXP).

Также данная функция позволяет запустить приложение с пониженными правами — уровень привилегий копируется у процесса Windows Explorer (возможность не поддерживается в системах Win2K/WinXP — будет показан тот же диалог ввода имени пользователя и пароля, что и при повышении прав; не рекомендуется к использованию).

Задание 0 в аргументе lpcExeName запускает исполняемый файл текущего процесса. В последнем случае, если параметр bElevated равен текущему уровню привилегий процесса, запуск не производится.

Используются функции ShellExecuteEx/"runas", GetWindowThreadProcessId, OpenProcess, OpenProcessToken, GetTokenInformation/TokenIntegrityLevel, GetSidSubAuthorityCount, CreateProcessWithToken, LookupPrivilegeValue, AdjustTokenPrivileges.

Краткий справочник вспомогательных и внутренних функций VMPKit

В данном разделе я опишу некоторые вспомогательные функции VMPKit, которые, в основном, используются внутри библиотеки. Также данные функции могут быть использованы при написании пользовательских функций обратного вызова.

Функции обратного вызова

Для сокращения статьи я не привожу полные описания типов функций обратного вызова, а только их имена. Назначение функций должно быть понятно из их названий. Также не приводятся отдельно версии для ANSI и UNICODE с соответствующими суффиксами A и W, как это принято в WinAPI (это замечание справедливо и для всех последующих примеров).

PFN_VMPIK_GetOfflineActivationStringCallback
PFN_VMPIK_GetOfflineDeactivationStringCallback
PFN_VMPIK_ActivateOnlineCallback
PFN_VMPIK_DeactivateOnlineCallback
PFN_VMPIK_ActivateCheckLicenseCallback

Функции формирования текстовых сообщений

UINT VMPIKAPI VMPIK_GetActivationResultCodeMessage(INT activationResCode, LPTSTR  buf, UINT bufSize );

Функция VMPIK_GetActivationResultCodeMessage возвращает текст сообщения для кода ошибки, возникшей в процессе активации.

INT VMPIKAPI VMPIK_ActivationStateBitsToErrorCode( INT Bits );

Функция VMPIK_ActivationStateBitsToErrorCode преобразует значение битов статуса лицензии в код ошибки. В основном используется внутри встроенных функций обратного вызова. Взаимно-однозначного соответствия между значениями битов состояния лицензии и кодами ошибок VMPKit нет.

INT VMPIKAPI VMPIK_ActivationStateBitsGetIndex( INT *pBits );

Функция VMPIK_ActivationStateBitsGetIndex возвращает индекс (номер) первого установленного бита статуса лицензии и сбрасывает этот бит в *pBits. Используется для формирования сообщений о статусе лицензии.

UINT VMPIKAPI VMPIK_GetActivationStateBitMessage(INT bitNo, LPTSTR  buf, UINT bufSize );

Функция VMPIK_GetActivationStateBitMessage возвращает текстовую информационную строку по индексу (номеру) бита статуса лицензии.

UINT VMPIKAPI VMPIK_FormatStateBitsMessage(INT stateBits, LPTSTR lpMsgBuf, UINT bufSize, BOOL bTrial, LPCTSTR infoMessage);

Функция VMPIK_FormatStateBitsMessage формирует сообщение, содержащее полную информацию о статусе лицензии (обо всех битах статуса). Опциональный параметр infoMessage задает строку, предваряющую информацию о статусе лицензии.

INT VMPIKAPI VMPIK_GetCurrentHWID( TCHAR * HWID, UINT nSize);

Функция VMPIK_GetCurrentHWID возвращает текстовую строку идентификатора оборудования (дублирует VMProtectGetCurrentHWID), и возвращает строку «HWID» в версии VMPKit VmpFree. Данная функция реализована в ANSI и UNICODE версиях, в отличии от оригинальной функции VMProtect.

Хранение данных лицензии

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

Флаги

  • VMPIK_ACF_SHARE64FOR32KEY — позволяет хранить данные лицензии в части реестра, общей для 32ух-разрядных и 64х-разрядных приложений. Полезно, когда лицензия позволяет использование обеих версий приложения одновременно.
  • VMPIK_ACF_WOW64_32KEY — то же, что и выше.
  • VMPIK_ACF_DISABLE_VIRTUALIZATION — отключает виртуализацию реестра и файловой системы при обращении к данным лицензии.
  • VMPIK_ACF_USE_APP_PATH — если не задается корневой узел реестра, то задание этого флага указывает использовать путь к исполняемому файлу приложения, как путь, по которому расположены файлы данных лицензии

Общие параметры и соглашения об их использовании

  • acfFlags — флаги, см. выше.
  • hRootKey — корневой узел реестра, обычно HKEY_LOCAL_MACHINE (HKLM) или HKEY_CURRENT_USER (HKCU). Если задан 0, то используется хранение данных в файлах вместо реестра.
  • lpcRegOrFilePath — раздел реестра или путь к данным, по которому хранятся данные лицензии.
  • lpcRegValOrFileName — имя файла или название параметра реестра, в котором хранятся данные лицензии
  • lpcRegValOrFileNameTrial — имя файла или название параметра реестра, в котором хранится признак лицензии (Trial/Full)
  • lpcRegValOrFileNameSerial — имя файла или название параметра реестра, в котором хранится код активации

Признак лицензии Trial/Full — несмотря на то, что VMProtect позволяет добавлять к данным лицензии произвольные пользовательские данные, штатного способа отличить пробную лицензию с ограниченным сроком действия от полной лицензии с также ограниченным сроком действия не существует. При использовании других протекторов такая возможность также может отсутствовать. В признак лицензии Trial/Full записывается значение True, если при помощи VMPKit была активирована пробная лицензия, в противном случае данный параметр отсутствует или содержит False. Несмотря на данную опцию рекомендуется проверять тип лицензии при помощи задания пользовательских данных (для VMProtect) или каким-либо другим способом.

Сохраненный код активации (параметр lpcRegValOrFileNameSerial) — в некоторых случаях полезно сохранить код активации, при помощи которого приложение было активировано. Это может быть полезно, когда лицензия обладает ограниченным сроком действия, и при продлении лицензии действует скидка. Может быть удобно при организации продаж по подписке, когда покупка и первый период использования стоят дороже, чем продление уже приобретенной лицензии.

Замечание: все функции подразумевают, что данные лицензии хранятся в текстовом виде. При необходимости хранить бинарные данные их следует кодировать в base64.

Функции

INT VMPIKAPI 
Read( DWORD acfFlags, HKEY hRootKey, LPCTSTR lpcRegOrFilePath, LPCTSTR lpcRegValOrFileName, LPSTR lpActivationCodeBuf, UINT ActivationCodeBufSize );

Функция VMPIK_ActivationCodeRead читает данные лицензии в указанную область памяти.

INT VMPIKAPI VMPIK_ActivationCodeWrite( DWORD acfFlags, HKEY hRootKey, LPCTSTR lpcRegOrFilePath, LPCTSTR lpcRegValOrFileName, LPCSTR lpcActivationCode );

Функция VMPIK_ActivationCodeWrite производит запись данных лицензии.

BOOL VMPIKAPI VMPIK_ActivationCodeTestIsWritable( DWORD acfFlags, HKEY hRootKey, LPCTSTR lpcRegOrFilePath );

Функция VMPIK_ActivationCodeTestIsWritable проверяет, доступно ли месторасположение, указанное для сохранения данных лицензии, для записи.

INT VMPIKAPI VMPIK_ActivationCodeRemove( DWORD acfFlags, HKEY hRootKey, LPCTSTR lpcRegOrFilePath, LPCTSTR lpcRegValOrFileName );

Функция VMPIK_ActivationCodeRemove удаляет данные лицензии с компьютера пользователя. Может быть использованна при деактивации лицензии. Важно помнить, что деактивация и удаление данных лицензии в общем случае не дают никаких гарантий. Пользователь может схитрить и после деактивации восстановить данные лицензии, например, при помощи функции бэкапирования.

BOOL VMPIKAPI VMPIK_ActivationCodeIsStoredOnComputer( DWORD acfFlags, HKEY hRootKey, LPCTSTR lpcRegOrFilePath, LPCTSTR lpcRegValOrFileName );

Функция VMPIK_ActivationCodeIsStoredOnComputer проверяет, сохранены ли данные лицензии на компьютере в заданном месторасположении.

UINT VMPIKAPI VMPIK_ActivationCodeLocationGetDisplayString( DWORD acfFlags, HKEY hRootKey, LPCTSTR lpcRegOrFilePath, LPCTSTR  lpcRegValOrFileName, LPTSTR locationBuf, UINT locationBufSize );

Функция VMPIK_ActivationCodeLocationGetDisplayString используется в отладочных целях и формирует текстовую строку со сведениями о месторасположении данных лицензии.

BOOL VMPIKAPI VMPIK_ActivationWriteTrialState(DWORD acfFlags, HKEY hRootKey, LPCTSTR lpcRegOrFilePath, LPCTSTR  lpcRegValOrFileName, BOOL bTrialState );

Функция VMPIK_ActivationWriteTrialState записывает признак лицензии Trial/Full (если bTrialState равен FALSE, то параметр реестра или файл просто удаляется, что означает значение Full).

BOOL VMPIKAPI VMPIK_ActivationReadTrialState(DWORD acfFlags, HKEY hRootKey, LPCTSTR lpcRegOrFilePath, LPCTSTR lpcRegValOrFileName );

Функция VMPIK_ActivationReadTrialState производит чтение признака лицензии Trial/Full.

UINT VMPIKAPI VMPIK_FindActiveLicense( DWORD acfFlags, LPCTSTR lpcRegOrFilePath, LPCTSTR lpcRegValOrFileNameLicense, LPCTSTR lpcRegValOrFileNameTrial, BOOL bAllowTrial );

Функция VMPIK_FindActiveLicense производит поиск данных лицензии в реестре в разделах HKEY_LOCAL_MACHINE (HKLM) или HKEY_CURRENT_USER (HKCU).
Возвращает значение VMPIK_FAL_HKLM или VMPIK_FAL_HKCU, возможно в сочетании с VMPIK_FAL_TRIAL. Если лицензия не найдена, возвращается 0.

Инициализация защиты для модуля vmpikXX.dll и сервисные функции расширения API VMProtect

INT VMPIKAPI VMPIK_ActivationCodeSet( LPCSTR lpcActivationCode, INT *pActivationStateBits );

Функция VMPIK_ActivationCodeSet активирует подсистему защиты для модуля vmpik32.dll/vmpik64.dll. Если приложение не просто использует систему лицензирования VMProtect, но также и защищено им, то необходимо вызвать функцию VMProtect API VMProtectSetSerialNumber в коде приложения (а также для каждого защищенного модуля EXE/DLL).

Данная функция для единообразия с остальным API VMPKit возвращает код ошибки, в отличие от VMProtectSetSerialNumber, а битовую маску состояния лицензии возвращает по адресу *pActivationStateBits (опционально).

INT VMPIKAPI VMPIK_ActivationCodeSetStored( DWORD acfFlags, HKEY hRootKey, LPCTSTR lpcRegOrFilePath, LPCTSTR lpcRegValOrFileName, INT *pActivationStateBits );

Функция VMPIK_ActivationCodeSetStored читает данные лицензии из указанного месторасположения и активирует подсистему защиты для модуля vmpik32.dll/vmpik64.dll.

INT VMPIKAPI VMPIK_ActivationGetStateBits( );

Функция VMPIK_ActivationGetStateBits дублирует функцию VMProtectGetSerialNumberState для модуля vmpik32.dll/vmpik64.dll. Перед ее использованием должна быть вызвана функция VMPIK_ActivationCodeSet или функция VMPIK_ActivationCodeSetStored.

BOOL VMPIKAPI VMPIK_IsProtected();

Функция VMPIK_IsProtected возвращает TRUE, если модуль vmpik32.dll/vmpik64.dll был обработан протектором. Основное использование — определение наличия режима работы подсистемы VMProtect — тестовый или рабочий. В тестовом режиме VMProtect использует данные из файла VMProtectLicense.ini, что может быть использовано при отладке.

BOOL VMPIKAPI VMPIK_ActivationGetUserInfo( LPTSTR lpUserName, LPTSTR lpEmail );

Функция VMPIK_ActivationGetUserInfo возвращает имя и email пользователя, на которого зарегистрированна программа. Данная функция является частичным аналогом функции VMProtect API VMProtectGetSerialNumberData, за исключением того, что она предоставляется в версиях ANSI и UNICODE, в отличии от оригинальной функции, доступной только в UNICODE версии. Подсистема защиты должна быть активированна для модуля vmpik32.dll/vmpik64.dll до вызова данной функции.

Буфер, принимающий имя пользователя и буфер для приема email должны быть как минимум размером в 256 байт.

BOOL VMPIKAPI VMPIK_ActivationHasExpirationDate();

Функция VMPIK_ActivationHasExpirationDate возвращает TRUE, если текущая лицензия имеет ограничение по сроку действия.

BOOL VMPIKAPI VMPIK_ActivationGetExpirationDate( SYSTEMTIME *pSysTime );

Функция VMPIK_ActivationGetExpirationDate возвращает дату окончания срока действия лицензии в стандартном формате даты Windows — в структуре SYSTEMTIME (в отличие от VMProtectGetSerialNumberData). Подсистема защиты должна быть активированна для модуля vmpik32.dll/vmpik64.dll до вызова данной функции.

BOOL VMPIKAPI VMPIK_ActivationGetExpiredDateStr( LPTSTR lpDateStrBuf, UINT bufSize, LPCTSTR lpcDateFormat, BOOL bLongDate );

Функция VMPIK_ActivationGetExpiredDateStr форматирует дату окончания срока действия лицензии при помощи WinAPI функции GetDateFormat. Флаг bLongDate отвечает за установку флага функции GetDateFormatDATE_LONGDATE или DATE_SHORTDATE. Подсистема защиты должна быть активированна для модуля vmpik32.dll/vmpik64.dll до вызова данной функции.

BOOL VMPIKAPI VMPIK_LicenseGetDataByte( unsigned byteNo, BYTE *pByte );

VMProtect предоставляет возможность для каждого типа лицензии задать до 255 байт пользовательских данных. Функция VMPIK_LicenseGetDataByte возвращает байт данных по указанному смещению от начала. Функция возвращает FALSE если лицензия не содержит пользовательских данных или номер байта (индекс) вышел за пределы диапазона. Подсистема защиты должна быть активированна для модуля vmpik32.dll/vmpik64.dll до вызова данной функции.

Функции установки локали

Функции установки локали — это вспомогательные функции для установки локали текущего потока, одинакого работающие в Win2K, WinXP и в Windows Vista+. Данные функции используют функции Win32 SetThreadLocale, SetThreadUILanguage, GetThreadUILanguage и SetThreadPreferredUILanguages.

Также данные функции осуществляют преобразование имени локали из строкового представления («ru», «ruRU», «ru-RU», «en», и тд) в числовой идентификатор локали.

Данные функции удобно использовать, когда идентификатор локали задается в текстовом виде, например, при задании локали из командной строки.

Функции установки локали

LANGID VMPIKAPI VMPIK_GetThreadUiLang( );
BOOL VMPIKAPI VMPIK_SetThreadLocaleAndUiLang( WORD langid );
WORD VMPIKAPI VMPIK_GetLangIdByString( LPCTSTR lpszLangId);
BOOL VMPIKAPI VMPIK_SetThreadLocaleAndUiLangByLangName( LPCTSTR lpszLangId );

Использование ресурсов

Данные функции несколько упрощают загрузку и использование строковых ресурсов приложения. Данные функции могут не работать, если при защите модуля использовалась опция VMProtect «защита ресурсов».

BOOL VMPIKAPI VMPIK_LoadString(HINSTANCE hInstance, INT strId, TCHAR *buf, UINT bufSize, LPCTSTR defMessage);

Функция VMPIK_LoadString производит загрузку строки в заданный буфер, Если строка не может быть найдена, то используется строка по умолчанию, заданная параметром defMessage.

UINT VMPIKAPI VMPIK_LoadDialogStrings( HINSTANCE hInstance, LPCTSTR lpTemplate, LPTSTR stringsBuf, UINT stringsBufSize, LPTSTR *lpStrings, UINT numStringsMax );

Функция VMPIK_LoadDialogStrings производит загрузку строк из строкового диалога.

Строковый диалог — это диалог, который никогда не отображается на экране в виде диалога, единственное его назначение — служить контейнером для набора строк.

При создании строкового диалога следует использовать только такие типы элементов управления, которые позволяют задавать свой текст в файле ресурсов. Это могут быть любые типы контролов, но предпочтительнее использовать элементы управления «static» — LTEXT, CTEXT и тп. При добавлении строкового диалога в ресурсы приложения нет необходимости задавать идентификаторы элементов управления — они будут загружены в том порядке, в котором объявлены в описании диалога.

Использование строковых диалогов позволяет производить загрузку набора строк за один вызов функции и избавляет от лишних проверок.

Использование строковых диалогов позволяет избежать назначения каждой строке уникального идентификатора.

Использование строковых диалогов позволяет экономить стековое пространство в памяти потока, что до сих пор актуально для 32ух-разрядных приложений — необходимо задать для всех строк один буфер размером N*(средняя длина строки) + константа резерва, вместо задания N буферов максимального размера для каждой строки.

BOOL VMPIKAPI VMPIK_LoadVersionString(HMODULE hMod, BOOL bProductVersion, UINT verStrLen, TCHAR *buf, UINT bufSize);

Функция VMPIK_LoadVersionString производит загрузку строки версии для заданного модуля из ресурса VERSIONINFO. Флаг bProductVersion задает, какую версию использовать — версию файла или версию продукта.

Номер версии файла или продукта состоит из разделяемых точкой частей — «1.0.4.7.beta». Параметр verStrLen задает количество компонет номера версии — так, задание значения 1 вернет строку «1.0», задание значения 3 вернет строку «1.0.4.7».

Продолжение следует

Как оказалось, VMPKit содержит достаточно много функций, описать которые в одном посте достаточно сложно, и также мы решили, что такой длинный пост будет сложно воспринимать, поэтому мы решили разбить описание на несколько частей.

Мы постараемся не откладывать написание продолжения в долгий ящик.

Автор: kruzhevnik

Источник

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js