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

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

Данная статья продолжает серию постов о продукте VMProtect Integration Kit (VMPKit).

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

В данной части будет рассмотрена подсистема протоколирования VMPKit, реализованная для упрощения отладки процесса активации приложений.

Подсистема VMPKit GUI предоставляет несколько функций, упрощающих использование Shell-диалогов WinAPI для выбора файла для сохранения, выбора файла для записи и выбора каталога.

Также в данной части будет описана часть API VMPKit, которая реализует графический интерфейс активации приложения, ввод серийного номера, и отображает гибко настраиваемый диалог «О Программе»

Содержание

Отмазка aka disclaimer

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

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

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

Протоколирование

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

Флаги, используемые при открытии лога

  • VMPIK_LOG_DEFAULT — значение флагов по умолчанию.
  • VMPIK_LOG_OVERWRITE — указывает, что при открытии лог-файла его содержимое следует перезаписать. Используется при вызове функции VMPIK_LogCreate. Если не указаны флаги VMPIK_LOG_OVERWRITE и VMPIK_LOG_APPEND и файл с заданным именем существует, открытие лог-файла завершится ошибкой.
  • VMPIK_LOG_APPEND — указывает, что при открытии лог-файла новое содержимое будет добавляться в конец существующего файла. Используется при вызове функции VMPIK_LogCreate. Если не указаны флаги VMPIK_LOG_OVERWRITE и VMPIK_LOG_APPEND и файл с заданным именем существует, открытие лог-файла завершится ошибкой.
  • VMPIK_LOG_APPPATH — данный флаг указывает использовать путь к исполняемому файлу приложения, если путь не задан аргументом функции VMPIK_LogCreateTemporary.
  • VMPIK_LOG_EXTRACTPATH — данный флаг указывает, что путь, заданный аргументом функции VMPIK_LogCreateTemporary на самом деле является именем файла, и путь к лог-файлу необходимо извлечь из указанного полного имени файла. Данную возможность удобно использовать, когда необходимо создать лог-файл в том же каталоге, что и какой-либо другой файл с известным именем.

Инициализация и закрытие

HANDLE VMPIKAPI VMPIK_LogRelease( );

Функция VMPIK_LogRelease возвращает хэндл лог-файла и очищает внутренние структуры, связанные с протоколированием, не закрывая лог-файл.

BOOL VMPIKAPI VMPIK_LogClose( );

Функция VMPIK_LogClose закрывает лог-файл и очищает внутренние структуры, связанные с протоколированием.

BOOL VMPIKAPI VMPIK_LogSetHandle( HANDLE hLogFile );

Функция VMPIK_LogSetHandle устанавливает хэндл лог-файла и инициализирует внутренние структуры, связанные с протоколированием.

BOOL VMPIKAPI VMPIK_LogCreate( DWORD dwFlags, LPCTWSTR lpszLogFile );

Функция VMPIK_LogCreate создает лог-файл с именем lpszLogFile в соответствии со значениями флагов dwFlags.

BOOL VMPIKAPI VMPIK_LogCreateTemporary( DWORD dwFlags, LPCTSTR lpszLogFilePath, LPCTSTR lpszLogFileNamePrefix, LPCTSTR lpszLogFileNameExt, UINT n, LPTSTR filenameBuf, UINT fnBufSize );

Функция VMPIK_LogCreateTemporary создает временный файл с именем вида «$PATH$PREFIX$NNNN.$EXT», где $NNNN — параметр n, оформатированный как 4х-разрядное шестнадцатеричное число. Если такой файл существует, то значение n будет увеличиваться до тех пор, пока не будет создан новый файл или пока число попыток не превысит 65536.

Если параметр lpszLogFilePath задан как 0 (или указывает на пустую строку), и не заданны флаги VMPIK_LOG_APPPATH и VMPIK_LOG_EXTRACTPATH, то будет использоваться путь для временных файлов, который возвращает функция WinAPI GetTempPath.

Функция VMPIK_LogCreateTemporary может возвращать имя созданного лог-файла, если задан параметр filenameBuf.

Запись сообщений

BOOL VMPIKAPI VMPIK_LogWriteString( LPCSTR str );

Функция VMPIK_LogWriteString производит запись строки в лог-файл. Каждый символ перевода строки 'n' преобразуется в последовательность «rn». После каждого перевода строки в начало новой строки добавляется текущее время. Рекомендуется производить запись строк в виде «nSome message to log» вместо «Some message to logn»; в лог файле строка будет выглядет так — «[2014/03/09 16:18:24] Some message to log»

Unicode версия функции VMPIK_LogWriteString предварительно перекодирует строку в Ansi кодировку.

BOOL VMPIKAPIV VMPIK_LogPrint( LPCTSTR  fmt, ... );

Функция VMPIK_LogPrint осуществляет форматный вывод в лог-файл.

void VMPIKAPI VMPIK_LogWriteSysInfo();

Функция VMPIK_LogWriteSysInfo записывает в лог-файл основные сведения о системе и о приложении.

Пример вывода VMPIK_LogWriteSysInfo

[2014/03/10 21:00:55] Application version: 1.2.3.4
[2014/03/10 21:00:55] Windows version: 6.1/x64, Service Pack 1
[2014/03/10 21:00:55] CPU: 4 X x64
[2014/03/10 21:00:55] Memory: 8155 Mb, used: 55%
[2014/03/10 21:00:55] Is User Administrator: Yes
[2014/03/10 21:00:55] Is Run as Administrator: No
[2014/03/10 21:00:55] Is Process Elevated: No
[2014/03/10 21:00:55] Process Integrity Level: MEDIUM
[2014/03/10 21:00:55] Default Virtualization Status: Enabled

Обертки для shell-функций WinAPI

Если использование функции GetOpenFileName для отображения диалогов сохранения и открытия файлов не слишком сложно, то уже использование SHBrowseForFolder представляет некоторую трудность, с учетом ее различного поведения даже под Windows 2000 и Windows XP.

В современных ОС Windows (Windows Vista+) в Microsoft отошли от использования этих функций, и для отображения аналогичных диалогов предлагают использовать COM-интерфейсы IFileOpenDialog и IFileSaveDialog, при этом отображаемые диалоги довольно сильно отличаются внешним видом от диалогов из предыдущих версий Windows.

Современные GUI-библиотеки в основном предоставляют упрощающие жизнь обертки над shell-функциями, но в каждом случае надо уточнять вопрос с совместимостью с различными версиями Windows. Также возможна ситуация, когда разработка ведется в старых системах разработки с использованием устаревших SDK (например, Delphi 5-7), или необходимо минимизировать использование GUI-библиотек, но хочется, хотя бы частично, придать приложению современный вид, и/или автоматически выбирать вид отображаемых диалогов в зависимости от версии Windows. Последнее требование, так же как и необходимость минимизации использования GUI-библиотек, как раз и имело место быть при создании GUI VMPKit, и было решено вынести эти функции в публичный интерфейс VMPKit.

Еще одним аргументом за использование shell-функций VMPKit является то, что COM-интерфейсы IFileOpenDialog и IFileSaveDialog не имеют версий, работающих с Ansi-строками, и добавление диалогов в стиле Vista+ в старое ANSI-приложение дополнительно затруднено.

Еще одной не слишком важной, но полезной функцией является функция отображения MessageBox'а без звукового сигнала — в случае, если при показе MessageBox'а используется флаг, указывающий использовать какую-либо иконку, стандартная WinAPI функция MessageBox выдает звуковой сигнал. Иногда хочется этого избежать и отключить вывод звука совсем или сделать его вывод опционально.

Флаги shell-функций

Флаги функций VMPIK_OpenFileDialog/VMPIK_SaveFileDialog

  • VMPIK_OSFD_HIDEREADONLY — скрывает чекбокс «только для чтения». Соответствует флагу WinAPI OFN_HIDEREADONLY. Используется по умолчанию, в отличие от OFN_HIDEREADONLY. Не используется в Vista+.
  • VMPIK_OSFD_NOHIDEREADONLY — отображает чекбокс «только для чтения». Отменяет действие флага VMPIK_OSFD_HIDEREADONLY. Не используется в Vista+.
  • VMPIK_OSFD_OVERWRITEPROMPT — выводит запрос на перезапись файла, если он уже существует. Соответствует флагу WinAPI OFN_FILEMUSTEXIST.
  • VMPIK_OSFD_FILEMUSTEXIST — файл с указанным именем должен существовать. Соответствует флагу WinAPI OFN_FILEMUSTEXIST.
  • VMPIK_OSFD_ALLOWMULTISELECT — позволяет выбирать несколько файлов одновременно. Соответствует флагу WinAPI OFN_ALLOWMULTISELECT.
  • VMPIK_OSFD_NOCHANGEDIR — запрещает смену каталога. Соответствует флагу WinAPI OFN_NOCHANGEDIR. Не действует для VMPIK_OpenFileDialog.
  • VMPIK_OSFD_PATHMUSTEXIST — указывает, что пользователь должен вводить только имена существующих файлов и каталогов. Соответствует флагу WinAPI OFN_PATHMUSTEXIST.

Флаги функции VMPIK_BrowseForFolder

  • VMPIK_OSFD_NONEWDIALOGSTYLE — соответствует флагу WinAPI BIF_NEWDIALOGSTYLE. Не используется в Vista+.
  • VMPIK_OSFD_NONEWFOLDERBUTTON — соответствует флагу WinAPI BIF_NONEWFOLDERBUTTON. Не используется в Vista+.
  • VMPIK_OSFD_INCLUDEFILES — соответствует флагу WinAPI BIF_BROWSEINCLUDEFILES. Не используется в Vista+.

Флаги, общие для всех shell-функций

  • VMPIK_OSFD_FORCESHOWHIDDEN — задает опцию показа скрытых файлов и папок вне зависимости от настроек системы. Соответствует флагу WinAPI OFN_FORCESHOWHIDDEN.
  • VMPIK_OSFD_ADDTORECENT — указывает, что выбранный файл/папку следует добавить в список часто используемых.
  • VMPIK_OSFD_CLASSICDIALOG — принудительно отображает диалоги в классическом стиле (W2K/WinXP).

Shell-Функции VMPKit

INT  VMPIKAPI VMPIK_SilentMessageBoxEx( HWND hWnd, LPCTSTR lpText, LPCTSTR lpCaption, UINT uType, BOOL bSilent );
INT  VMPIKAPI VMPIK_SilentMessageBox  ( HWND hWnd, LPCTSTR lpText, LPCTSTR lpCaption, UINT uType );

Вышеприведенные функции полностью аналогичны функции WinAPI MessageBox, но в одной версии вывод звука является опциональным, в другой — отключен совсем.

BOOL VMPIKAPI VMPIK_OpenFileDialog( HWND hWndParent, DWORD osfdFlags, LPCTSTR lpszDialogTitle, LPCTSTR lpszDefExt, LPCTSTR lpszFilter, LPCTSTR lpszInitialDir, LPTSTR lpszFilenameBuf, DWORD dwBufSize, /*out*/ DWORD *pFilterIndex );

Функция VMPIK_OpenFileDialog отображает диалог открытия файла. Можно задать заголовок и каталог, который будет выбран изначально.

BOOL VMPIKAPI VMPIK_SaveFileDialog( HWND hWndParent, DWORD osfdFlags, LPCTSTR lpszDialogTitle, LPCTSTR lpszDefExt, LPCTSTR lpszFilter, LPCTSTR lpszInitialDir, LPTSTR lpszFilenameBuf, DWORD dwBufSize, /*out*/ DWORD *pFilterIndex );

Функция VMPIK_SaveFileDialog отображает диалог сохранения файла. Можно задать заголовок и каталог, который будет выбран изначально.

BOOL VMPIKAPI VMPIK_BrowseForFolder(HWND hWndParent, DWORD osfdFlags, LPCTSTR lpszDialogTitle, LPCTSTR lpszInitialDir, LPTSTR lpszFilenameBuf, DWORD dwBufSize, LPTSTR lpszDisplayBuf, DWORD dwDisplaySize );

Функция VMPIK_BrowseForFolder отображает диалог выбора папки. Можно задать заголовок и каталог, который будет выбран изначально. Помимо пути к выбранному каталогу, может возвращать его отображаемое название, если задан параметр lpszDisplayBuf. Так, для каталога «C:UserAll UsersDocuments» отображаемое название будет — «Общие документы».

Подсистема GUI

VMPKit содержит несколько функций для отображения диалогов: простой диалог ввода серийного номера; диалог активации, поддерживающий различные способы активации; диалог «О Программе», поддерживающий различные режимы отображения.

Скриншоты диалогов

Диалог ввода серийного номера

VMPKit — интеграция протектора VMProtect в Windows приложение. Часть вторая. Протоколирование и GUI
Диалог активации - активация при помощи серийного номера с возможностью offline-активации

VMPKit — интеграция протектора VMProtect в Windows приложение. Часть вторая. Протоколирование и GUI
Диалог активации - активация при помощи серийного номера и активация при помощи ключевого файла лицензии (1)

VMPKit — интеграция протектора VMProtect в Windows приложение. Часть вторая. Протоколирование и GUI
Диалог активации - активация при помощи серийного номера и активация при помощи ключевого файла лицензии (2)

VMPKit — интеграция протектора VMProtect в Windows приложение. Часть вторая. Протоколирование и GUI
Диалог активации - активация при помощи серийного номера и активация при помощи ключевого файла лицензии (3)

VMPKit — интеграция протектора VMProtect в Windows приложение. Часть вторая. Протоколирование и GUI
Диалог активации - активация при помощи серийного номера и активация при помощи ключевого файла лицензии (4)

VMPKit — интеграция протектора VMProtect в Windows приложение. Часть вторая. Протоколирование и GUI
Диалог активации - активация при помощи серийного номера и активация при помощи ключевого файла лицензии (5)

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

VMPKit — интеграция протектора VMProtect в Windows приложение. Часть вторая. Протоколирование и GUI
Диалог 'О Программе' (1)

VMPKit — интеграция протектора VMProtect в Windows приложение. Часть вторая. Протоколирование и GUI
Диалог 'О Программе' (2)

VMPKit — интеграция протектора VMProtect в Windows приложение. Часть вторая. Протоколирование и GUI
Диалог 'О Программе' (3)

VMPKit — интеграция протектора VMProtect в Windows приложение. Часть вторая. Протоколирование и GUI
Диалог 'О Программе' (4

VMPKit — интеграция протектора VMProtect в Windows приложение. Часть вторая. Протоколирование и GUI
Диалог 'О Программе' (5)

VMPKit — интеграция протектора VMProtect в Windows приложение. Часть вторая. Протоколирование и GUI
Диалог 'О Программе' (6)

VMPKit — интеграция протектора VMProtect в Windows приложение. Часть вторая. Протоколирование и GUI

Флаги диалога активации

Диалог активации является очень гибко настраиваемым. Для настройки диалога активации используются одновременно два способа: 1) задание соответствующих значений аргументов при вызове диалоговых функций, и задание флагов диалога активации. В некоторых случаях эти способы могу дополнять друг друга.

Развернуть список флагов

  • VMPIK_AADF_ACTIVATE_SERIAL — включает возможность активации при помощи серийного номера (кода активации). При отображении диалога активации одна из двух опций: VMPIK_AADF_ACTIVATE_SERIAL или VMPIK_AADF_ACTIVATE_KEY_FILE должна быть включена.
  • VMPIK_AADF_ACTIVATE_KEY_FILE — включает возможность активации при помощи ключевого файла лицензии. При отображении диалога активации одна из двух опций: VMPIK_AADF_ACTIVATE_SERIAL или VMPIK_AADF_ACTIVATE_KEY_FILE должна быть включена.
  • VMPIK_AADF_ACTIVATE_TRIAL — включает возможность активации trial лицензии.
  • VMPIK_AADF_ACTIVATE_LATER — включает опцию «активировать позже».
  • VMPIK_AADF_REACTIVATE — включает режим реактивации (деактивация и последующая активация).
  • VMPIK_AADF_DEACTIVATE — включает режим деактивации. При успешной деактивации данные лицензии удаляются с компьютера пользователя.
  • VMPIK_AADF_ACTIVATE_MASK — маска режимов активации.
  • VMPIK_AADF_SELECT_ACTIVATE_MASK — маска изначально выбранного типа активации.
  • VMPIK_AADF_SIMPLE_SERIAL_INPUT — включает режим ввода серийного номера, без активации и каких-либо действий.
  • VMPIK_AADF_OFFLINE — добавляет опцию offline активации/деактивации.
  • VMPIK_AADF_ACTIVATION_TYPE — тип активации — для текущего пользователя/для всех пользователей.
  • VMPIK_AADF_SELECT_USER_GROUP — тоже, что и VMPIK_AADF_ACTIVATION_TYPE.
  • VMPIK_AADF_SELECT_ACTIVATE_SERIAL, VMPIK_AADF_SELECT_ACTIVATE_KEY_FILE, VMPIK_AADF_SELECT_ACTIVATE_TRIAL, VMPIK_AADF_SELECT_ACTIVATE_LATER — задает изначально выбранную опцию активации.
  • VMPIK_AADF_SELECT_ACTIVATION_TYPE_CURRENT_USER, VMPIK_AADF_SELECT_ACTIVATION_TYPE_ALL_USERS — задает изначально выбранный тип активации (для текущего пользователя/для всех пользователей).
  • VMPIK_AADF_DLG_RESIZE — включает возможность изменения размера диалога.
  • VMPIK_AADF_UPPERCASE — ограничивает ввод и приводит вводимые буквы серийного номера к верхнему регистру.
  • VMPIK_AADF_LOWERCASE — ограничивает ввод и приводит вводимые буквы серийного номера к нижнему регистру.
  • VMPIK_AADF_DEACTIVATE_OFFLINE_KEEP_LICENSE — offline при деактивации не удаляет данные лицензии с компьютера.
  • VMPIK_AADF_SERIAL_NUMBER_FORMAT_STR — задаем формат серийного номера в виде форматной строки.
  • VMPIK_AADF_SHOW_CONNECTION_REQUIRED — показывать строку «требуется подключение к интернету» для соответствующих опций.
  • VMPIK_AADF_CLASSIC_FILE_DIALOGS — указывает использовать классические (Win2K/WinXP) диалоги открытия/сохранения файлов в системах Vista+.
  • VMPIK_AADF_VERTICAL_BUTTONS — задает вертикальное расположение кнопок «Ok»/«Cancel»/«Elevate».
  • VMPIK_AADF_BUTTONS_AT_LEFT — задает расположение кнопок по левому краю.
  • VMPIK_AADF_BUTTONS_AT_RIGHT — задает расположение кнопок по правому краю.
  • VMPIK_AADF_SHOW_ELEVATION_BUTTON — указывает всегда показывать кнопку «Elevate».
  • VMPIK_AADF_ALWAYS_SILENT_MESSAGEBOX — при выводе сообщений MessageBox не будет использоваться звуковое сопровождение.
  • VMPIK_AADF_SHOW_OFFLINE_API_ERRORS — указывает показывать ошибки при вызове offline-API.
  • VMPIK_AADF_DONT_SHOW_ACTIVATION_SUCCESS — указывает не показывать сообщение об успешной активации.
  • VMPIK_AADF_DISABLE_LICENSE_DROP_TARGET — указывает не использовать возможности Drag'n'Drop для поля файла лицензии.
  • VMPIK_AADF_BOTTOM_RIGHT_POS — при задании точки, в которой будет отображаться диалог, использовать координаты правого нижнего угла вместо левого верхнего.

Коды возврата диалоговых функций активации

  • VMPIK_AADR_OK — активация прошла успешно, диалог закрыт по кнопке «Ok»/«Close».
  • VMPIK_AADR_SUCCESS — тоже, что и VMPIK_AADR_OK.
  • VMPIK_AADR_CANCELED — пользователь отменил активацию «Cancel»/Escape.
  • VMPIK_AADR_INVALID_PARAM — неверный параметр. В этом случае диалог не показывается пользователю.
  • VMPIK_AADR_ELEVATION_REQUIRED — возвращается, если пользователь нажал кнопку «Elevate».
  • VMPIK_AADR_SAVE_FAILED — активация прошла успешно, но возникла ошибка при сохранении данных лицензии. Данная ситуация теоретически не должна возникать, так как перед активацией возможность записи данных в нужное месторасположение проверяется.

Функция VMPIK_ParseSerialNumberFormat

Вспомогательная функция разбора форматной строки серийного номера. Используется при задании формата серийного номера строкой вместо массива целых чисел. Если часть формата серийного номера начинается с символа '#', то длина этой части является её размером, вне зависимости от остальных символов. Если формата серийного номера состоит из цифр, то они задают длину данной части, но не больше 32. Примеры эквивалентных форматных строк: «8-####-##-6», «8-4-2-6», «8-4-#4-6» ("#4" — 2, считается длина части), "########-####-##-######".

UINT VMPIKAPI VMPIK_ParseSerialNumberFormat( LPCTSTR strFormat, TCHAR sepChar, UINT *pSerialNumberNumChars, UINT *pNumPartsFound);

Функция VMPIK_InputSerialNumberDlg

INT VMPIKAPI VMPIK_InputSerialNumberDlg( HWND     hWndParent
                                    , LPCTSTR  lpcDlgTitle
                                    , HICON    hIcon
                                    , HICON    hIconSmall
                                    , POINT    *pLeftTop
                                    , UINT     serialNumberNumParts
                                    , UINT     serialNumberNumChars
                                    , const UINT *pSerialNumberNumChars
                                    , CHAR     serialNumberSeparator
                                    , LPCTSTR  lpcSerialNumberIncludeCharsMask
                                    , LPCTSTR  lpcSerialNumberExcludeCharsMask
                                    , UINT     fAadFlags
                                    , LPSTR    lpEnteredSerialBuf
                                    , UINT    *pEnteredSerialBufSize
                                    );

Функция VMPIK_InputSerialNumberDlg выводит диалог ввода серийного номера. Поддерживается копирование серийного номера из буфера обмена как целиком во все поля (если серийных номер скопирован целиком), так и в отдельное поле.

Параметры:

  • hWndParent — хэндл родительского окна.
  • lpcDlgTitle — заголовок диалога. Можно задавать 0.
  • hIcon — маленькая иконка. При использовании функции LoadImage следует задавать размер GetSystemMetrics(SM_CXICON). Можно задавать 0.
  • hIconSmall — большая иконка. При использовании функции LoadImage следует задавать размер GetSystemMetrics(SM_CXSMICON). Можно задавать 0.
  • pLeftTop — задает положение верхнего левого угла диалога. Можно задавать 0, в этом случае диалог будет спозиционирован по центру экрана/родительского окна.
  • serialNumberNumParts — количество частей в серийном номере, не более 16.
  • serialNumberNumChars — количество символов в каждой части серийного номера.
  • pSerialNumberNumChars — массив целых чисел, задающих длины отдельных частей серийного номера, при этом параметр serialNumberNumChars игнорируется. Можно задать указатель на строку формата, при этом параметр serialNumberNumParts также будет проигнорирован.
  • serialNumberSeparator — разделитель частей серийного номера. Задание 0 указывает использовать стандартный разделитель — '-'.
  • lpcSerialNumberIncludeCharsMask — строка, задающая фильтр допустимых символов.
  • lpcSerialNumberExcludeCharsMask — строка, задающая фильтр исключаемых символов.
  • fAadFlags — флаги, см Флаги диалога активации.
  • lpEnteredSerialBuf — буфер, в который будет помещен введенный серийный номер.
  • pEnteredSerialBufSize — размер буфера для серийного номера.

Функция VMPIK_ActivateAppDlg

Определение

INT VMPIKAPI VMPIK_ActivateAppDlg  ( HWND     hWndParent
                                    , LPCTSTR  lpcDlgTitle
                                    , HICON    hIcon
                                    , HICON    hIconSmall
                                    , POINT    *pLeftTop
                                    , DWORD    activationSaveLoadFlags
                                    , HKEY     hRootKeyCurrentUser
                                    , LPCTSTR  lpcRegOrFilePathCurrentUser
                                    , HKEY     hRootKeyAllUsers
                                    , LPCTSTR  lpcRegOrFilePathAllUsers
                                    , LPCTSTR  lpcRegValOrFileName
                                    , LPCTSTR  lpcSerialRegValOrFileName
                                    , LPCTSTR  lpcTrialFlagRegValOrFileName
                                    , UINT     serialNumberNumParts
                                    , UINT     serialNumberNumChars
                                    , const UINT *pSerialNumberNumChars
                                    , CHAR     serialNumberSeparator
                                    , UINT     fAadFlags
                                    , LPCTSTR  lpcOnlineActivationUrl
                                    , LPCTSTR  lpcOfflineActivationUrl
                                    , LPCSTR   lpcTrialLicenseSerial
                                    , LPVOID   lpvCallbackParam
                                    , PFN_VMPIK_ActivateOnlineCallback                 ActivateOnlineProc
                                    , PFN_VMPIK_DeactivateOnlineCallback               DeactivateOnlineProc
                                    , PFN_VMPIK_GetOfflineActivationStringCallback     GetOfflineActivationStringProc
                                    , PFN_VMPIK_GetOfflineDeactivationStringCallback   GetOfflineDeactivationStringProc
                                    , PFN_VMPIK_ActivateCheckLicenseCallback           ActivateCheckLicenseProc
                                    );

Функция VMPIK_ActivateAppDlg является упрощенной, по сравнению с VMPIK_ActivateAppDlgEx, версией функции вывода диалога активации.

Параметры:

  • hWndParent — хэндл родительского окна.
  • lpcDlgTitle — заголовок диалога. Можно задавать 0.
  • hIcon — маленькая иконка. При использовании функции LoadImage следует задавать размер GetSystemMetrics(SM_CXICON). Можно задавать 0.
  • hIconSmall — большая иконка. При использовании функции LoadImage следует задавать размер GetSystemMetrics(SM_CXSMICON). Можно задавать 0.
  • pLeftTop — задает положение верхнего левого угла диалога. Можно задавать 0, в этом случае диалог будет спозиционирован по центру экрана/родительского окна.
  • activationSaveLoadFlags — см. флаги сохранения данных лицензии.
  • hRootKeyCurrentUser — задает ветку реестра, куда будут записываться данные лицензии при активации для текущего пользователя. Следует задать 0 для сохранения в файл.
  • lpcRegOrFilePathCurrentUser — задает путь в реестре или файловой системе, по которому будут сохранены данные лицензии при активации для текущего пользователя.
  • hRootKeyAllUsers — задает ветку реестра, куда будут записываться данные лицензии при активации для всех пользователей. Следует задать 0 для сохранения в файл.
  • lpcRegOrFilePathAllUsers — задает путь в реестре или файловой системе, по которому будут сохранены данные лицензии при активации для всех пользователей. Может быть равен 0.
  • lpcRegValOrFileName — задает имя переменной в реестре или имя файла, в котором будут сохранены данные лицензии. Может быть равен 0.
  • lpcSerialRegValOrFileName — задает имя переменной в реестре или имя файла, в котором будет сохранен серийный номер (код активации), использованный при активации. Может быть равен 0.
  • lpcTrialFlagRegValOrFileName — задает имя переменной в реестре или имя файла, в котором будет сохранен Trial признак лицензии, если будет произведена активация пробной версии. Может быть равен 0.
  • serialNumberNumParts — количество частей в серийном номере, не более 16.
  • serialNumberNumChars — количество символов в каждой части серийного номера.
  • pSerialNumberNumChars — массив целых чисел, задающих длины отдельных частей серийного номера, при этом параметр serialNumberNumChars игнорируется. Можно задать указатель на строку формата, при этом параметр serialNumberNumParts также будет проигнорирован.
  • serialNumberSeparator — разделитель частей серийного номера. Задание 0 указывает использовать стандартный разделитель — '-'.
  • fAadFlags — флаги, см Флаги диалога активации.
  • lpcOnlineActivationUrl — задает URL, который используется для online активации. Данный параметр игнорируется в версии для VMProtect (там URL «зашивается» при защите модуля).
  • lpcOfflineActivationUrl — задает URL, который используется для online активации. Данный параметр игнорируется в версии для VMProtect (там URL «зашивается» при защите модуля).
  • lpcTrialLicenseSerial — задает серийный номер (код активации), который будет использоваться для активации пробной версии.
  • lpvCallbackParam — параметр для функций обратного вызова. Может быть равен 0.
  • ActivateOnlineProc — указатель на функцию online активации. Может быть равен 0.
  • DeactivateOnlineProc — указатель на функцию online деактивации. Может быть равен 0.
  • GetOfflineActivationStringProc — указатель на функцию, возвращающую строку данных для offline активации. Может быть равен 0.
  • GetOfflineDeactivationStringProc — указатель на функцию, возвращающую строку данных для offline деактивации. Может быть равен 0.
  • ActivateCheckLicenseProc — указатель на функцию, осуществляющую проверку лицензии. Может быть равен 0.

Для того, чтобы активировать приложение только для текущего пользователя или только для всех пользователей, необходимо задать только параметры hRootKeyCurrentUser и lpcRegOrFilePathCurrentUser. Для того, чтобы включить возможность выбора типа активации, следует указать флаг VMPIK_AADF_SELECT_USER_GROUP (VMPIK_AADF_ACTIVATION_TYPE), а также задать параметры hRootKeyAllUsers и lpcRegOrFilePathAllUsers.

Функции обратного вызова можно не задавать, указав значение 0, при этом будут использоваться встроенные реализации, использующие API VMProtect. Данная возможность добавлена для поддержки сторонних процедур активации.

Адреса (URL) активации и деактивации игнорируются при использовании встроенных реализаций, использующих VMProtect — при защите приложения VMProtect «зашивает» эти адреса в защищаемый модуль.

Поддержка Drag'n'Drop. Функция VMPIK_ActivateAppDlg (также как и функция Функция VMPIK_ActivateAppDlgEx) поддерживает перетаскивание ключевого файла данных лицензии на диалог активации, если данный способ активации разрешен флагами активации. Перетаскивание работает для всего диалога, не только для поля ввода имени файла лицензии. После перетаскивания сразу происходит активация данной лицензии, и выводится сообщение об успехе операции или об ошибке.

Функция VMPIK_ActivateAppDlgEx

Определение

INT VMPIKAPI VMPIK_ActivateAppDlgEx( HWND     hWndParent
                                    , LPCTSTR  lpcDlgTitle
                                    , HICON    hIcon
                                    , HICON    hIconSmall
                                    , POINT    *pLeftTop
                                    , DWORD    activationSaveLoadFlags
                                    , HKEY     hRootKeyCurrentUser
                                    , LPCWSTR  lpcRegOrFilePathCurrentUser
                                    , HKEY     hRootKeyAllUsers
                                    , LPCTSTR  lpcRegOrFilePathAllUsers
                                    , LPCTSTR  lpcRegValOrFileName
                                    , LPCTSTR  lpcSerialRegValOrFileName
                                    , LPCTSTR  lpcTrialFlagRegValOrFileName
                                    , UINT     serialNumberNumParts
                                    , UINT     serialNumberNumChars
                                    , const UINT *pSerialNumberNumChars
                                    , CHAR     serialNumberSeparator
                                    , LPCTSTR  lpcSerialNumberIncludeCharsMask
                                    , LPCTSTR  lpcSerialNumberExcludeCharsMask
                                    , UINT     fAadFlags
                                    , LPCTSTR  lpcOnlineActivationUrl
                                    , LPCTSTR  lpcOfflineActivationUrl
                                    , LPCSTR   lpcTrialLicenseSerial
                                    , LPVOID   lpvCallbackParam
                                    , PFN_VMPIK_ActivateOnlineCallback                 ActivateOnlineProc
                                    , PFN_VMPIK_DeactivateOnlineCallback               DeactivateOnlineProc
                                    , PFN_VMPIK_GetOfflineActivationStringCallback     GetOfflineActivationStringProc
                                    , PFN_VMPIK_GetOfflineDeactivationStringCallback   GetOfflineDeactivationStringProc
                                    , PFN_VMPIK_ActivateCheckLicenseCallback           ActivateCheckLicenseProc
                                    , LPCTSTR  lpcActivationFailedCustomTitle
                                    , LPCTSTR  lpcActivationSuccessCustomTitle
                                    , LPCTSTR  lpcActivationSuccessCustomMessage
                                    , LPCTSTR  lpcDeactivationFailedCustomTitle
                                    , LPCTSTR  lpcDeactivationSuccessCustomTitle
                                    , LPCTSTR  lpcDeactivationSuccessCustomMessage
                                    , INT     *pLastActivationStatus
                                    , LPSTR    lpEnteredSerialBuf
                                    , UINT    *pEnteredSerialBufSize
                                    , LPSTR    lpLicenseBuf
                                    , UINT    *pLicenseBufSize
                                    );

Функция VMPIK_ActivateAppDlgEx является расширенной версией функции вывода диалога активации.

Параметры:

  • hWndParent — хэндл родительского окна.
  • lpcDlgTitle — заголовок диалога. Можно задавать 0.
  • hIcon — маленькая иконка. При использовании функции LoadImage следует задавать размер GetSystemMetrics(SM_CXICON). Можно задавать 0.
  • hIconSmall — большая иконка. При использовании функции LoadImage следует задавать размер GetSystemMetrics(SM_CXSMICON). Можно задавать 0.
  • pLeftTop — задает положение верхнего левого угла диалога. Можно задавать 0, в этом случае диалог будет спозиционирован по центру экрана/родительского окна.
  • activationSaveLoadFlags — см. флаги сохранения данных лицензии.
  • hRootKeyCurrentUser — задает ветку реестра, куда будут записываться данные лицензии при активации для текущего пользователя. Следует задать 0 для сохранения в файл.
  • lpcRegOrFilePathCurrentUser — задает путь в реестре или файловой системе, по которому будут сохранены данные лицензии при активации для текущего пользователя.
  • hRootKeyAllUsers — задает ветку реестра, куда будут записываться данные лицензии при активации для всех пользователей. Следует задать 0 для сохранения в файл.
  • lpcRegOrFilePathAllUsers — задает путь в реестре или файловой системе, по которому будут сохранены данные лицензии при активации для всех пользователей. Может быть равен 0.
  • lpcRegValOrFileName — задает имя переменной в реестре или имя файла, в котором будут сохранены данные лицензии. Может быть равен 0.
  • lpcSerialRegValOrFileName — задает имя переменной в реестре или имя файла, в котором будет сохранен серийный номер (код активации), использованный при активации. Может быть равен 0.
  • lpcTrialFlagRegValOrFileName — задает имя переменной в реестре или имя файла, в котором будет сохранен Trial признак лицензии, если будет произведена активация пробной версии. Может быть равен 0.
  • serialNumberNumParts — количество частей в серийном номере, не более 16.
  • serialNumberNumChars — количество символов в каждой части серийного номера.
  • pSerialNumberNumChars — массив целых чисел, задающих длины отдельных частей серийного номера, при этом параметр serialNumberNumChars игнорируется. Можно задать указатель на строку формата, при этом параметр serialNumberNumParts также будет проигнорирован.
  • serialNumberSeparator — разделитель частей серийного номера. Задание 0 указывает использовать стандартный разделитель — '-'.
  • lpcSerialNumberIncludeCharsMask — строка, задающая фильтр допустимых символов.
  • lpcSerialNumberExcludeCharsMask — строка, задающая фильтр исключаемых символов.
  • fAadFlags — флаги, см Флаги диалога активации.
  • lpcOnlineActivationUrl — задает URL, который используется для online активации. Данный параметр игнорируется в версии для VMProtect (там URL «зашивается» при защите модуля).
  • lpcOfflineActivationUrl — задает URL, который используется для online активации. Данный параметр игнорируется в версии для VMProtect (там URL «зашивается» при защите модуля).
  • lpcTrialLicenseSerial — задает серийный номер (код активации), который будет использоваться для активации пробной версии.
  • lpvCallbackParam — параметр для функций обратного вызова. Может быть равен 0.
  • ActivateOnlineProc — указатель на функцию online активации. Может быть равен 0.
  • DeactivateOnlineProc — указатель на функцию online деактивации. Может быть равен 0.
  • GetOfflineActivationStringProc — указатель на функцию, возвращающую строку данных для offline активации. Может быть равен 0.
  • GetOfflineDeactivationStringProc — указатель на функцию, возвращающую строку данных для offline деактивации. Может быть равен 0.
  • ActivateCheckLicenseProc — указатель на функцию, осуществляющую проверку лицензии. Может быть равен 0.
  • lpcActivationFailedCustomTitle — заголовок сообщения об ошибке активации.
  • lpcActivationSuccessCustomTitle — заголовок сообщения об успешной активации.
  • lpcActivationSuccessCustomMessage — сообщение об успешной активации.
  • lpcDeactivationFailedCustomTitle — заголовок сообщения об ошибке деактивации.
  • lpcDeactivationSuccessCustomTitle — заголовок сообщения об успешной деактивации.
  • lpcDeactivationSuccessCustomMessage — сообщение об успешной деактивации.
  • pLastActivationStatus — статус последней осуществленной попытки активации.
  • lpEnteredSerialBuf — буфер, в который будет помещен введенный серийный номер.
  • pEnteredSerialBufSize — размер буфера для серийного номера.
  • lpLicenseBuf — буфер, в который будет помещены данные активированной лицензии.
  • pLicenseBufSize — размер буфера для данных лицензии.

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

Функция VMPIK_ActivateAppDlgEx позволяет задавать маску допустимых для ввода в поле серийного номера символов (lpcSerialNumberIncludeCharsMask), а также маску недопустимых символов (lpcSerialNumberExcludeCharsMask).

Также функция VMPIK_ActivateAppDlgEx позволяет задать заголовки для сообщений об успешной/неуспешной активации/деактивации.

Дополнительно данная функция позволяет получить введенный серийный номер (код активации) и данные лицензии для дальнейшей обработки. Это может быть полезно, если попытка записи данных лицензии после успешной активации по каким-либо причинам завершилась ошибкой.

Диалог «О Программе»

Создание диалога «О Программе» иногда представляет некоторую сложность — некоторые новые продукты часто в первых версиях не имеют такого диалога вообще. Также, если диалог «О Программе» создан для одной программы, часто переделка его под потребности другой программы занимает некоторое время.

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

Диалог «О Программе», предоставляемый VMPKit, умеет копировать всю отображаемую информацию в буфер обмена (в текстовом виде) по нажатию клавиш Ctrl+C или Ctrl+Ins. Данная функция удобна при поддержке приложения — достаточно дать пользователю простые инструкции, и он без труда предоставит все необходимые сведения о программе в вашу службу поддержки.

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

Флаги диалога «О Программе»

Развернуть

  • VMPIK_ABOUT_CLOSE_BUTTON — задает использовать кнопку «Close» вместо кнопки «Ok».
  • VMPIK_ABOUT_BUTTON_WITH_IMAGE — задает расположить кнопку «Ok»/«Close» непосредственно под изображением.
  • VMPIK_ABOUT_BUTTON_AT_LEFT — указывает разместить кнопку «Ok»/«Close» слева внизу (по умолчанию — справа внизу).
  • VMPIK_ABOUT_BUTTON_AT_CENTER — указывает разместить кнопку «Ok»/«Close» по-центру внизу (по умолчанию — справа внизу).
  • VMPIK_ABOUT_IMAGE_BITMAP — задает тип изображения HBITMAP (по умолчанию — HICON).
  • VMPIK_ABOUT_IMAGE_EMF — задает тип изображения Enhanced Metafile.
  • VMPIK_ABOUT_IMAGE_AT_LEFT — указывает разместить изображение слева от информационной части диалога (по умолчанию — справа).
  • VMPIK_ABOUT_PREPEND_COPYRIGHT_SIGN — указывает предварять при выводе строку копирайта символом копирайта.
  • VMPIK_ABOUT_COMPOSITE_COPYRIGHT_SIGN — указывает использовать символ копирайта как комбинацию — "©".
  • VMPIK_ABOUT_COPYRIGHT_APPEND_ALL_RIGHTS — указывает добавлять строку «All rights reserved» («Все права защищены») к строке копирайта.
  • VMPIK_ABOUT_SYS_INFO_WINDOWS_INFO — добавляет в раздел сведений о системе информацию о текущей версии Windows.
  • VMPIK_ABOUT_SYS_INFO_MEM_INFO — добавляет в раздел сведений о системе информацию об использовании памяти.
  • VMPIK_ABOUT_SYS_INFO_CPU_INFO — добавляет в раздел сведений о системе информацию о процессоре.
  • VMPIK_ABOUT_DISABLE_CLIPBOARD_COPY — запрещает копирование информации в буфер обмена по нажатию клавиш Ctrl+C или Ctrl+Ins.
  • VMPIK_ABOUT_ALWAYS_SHOW_REGISTERED — указывает всегда отображать раздел сведений о регистрации, даже если не указаны имя, email пользователя и срок окончания действия лицензии.
  • VMPIK_ABOUT_CLOSE_ON_URL_EVENT — указывает закрывать диалог при переходе на сайт по клику на соответствующей метке.
  • VMPIK_ABOUT_BOTTOM_RIGHT_POS — указывает использовать правый нижний угол для позиционирования диалога.
  • VMPIK_ABOUT_COPY_ADDITIONAL_INFO — указывает копировать в буфер обмена также и дополнительную информацию (если задана) по нажатию клавиш Ctrl+C или Ctrl+Ins.
  • VMPIK_ABOUT_PURCHASE_BTN_NONE — запрещает отображение кнопки «Купить».
  • VMPIK_ABOUT_PURCHASE_BTN_DEF_SIZE — задает размер кнопки по ширине «Купить» по умолчанию.
  • VMPIK_ABOUT_PURCHASE_BTN_HALF_SIZE — задает размер кнопки по ширине «Купить» в половину вычисленного при адаптации размера диалога.
  • VMPIK_ABOUT_PURCHASE_BTN_FULL_SIZE — задает размер кнопки по ширине «Купить» как размер, вычисленный при адаптации размера диалога.
  • VMPIK_ABOUT_CLOSE_ON_PURCHASE_EVENT — указывает закрывать диалог при нажатии кнопки «Купить».
  • VMPIK_ABOUT_VERSION_SHORT_FROM_APP_MODULE — указывает использовать отображаемую версию как короткую версию модуля приложения («1.0»).
  • VMPIK_ABOUT_VERSION_SHORTEX_FROM_APP_MODULE — указывает использовать отображаемую версию как расширенную короткую версию модуля приложения («1.2.3»).
  • VMPIK_ABOUT_VERSION_LONG_FROM_APP_MODULE — указывает использовать отображаемую версию как версию модуля приложения («1.2.3.4»).
  • VMPIK_ABOUT_VERSION_FILE_VERSION — использовать версию файла модуля приложения вместо версии продукта.

Функция диалога «О Программе»

INT VMPIKAPI VMPIK_AboutAppDlgW( HWND     hWndParent
                               , LPCWSTR  lpcDlgTitle
                               , const VMPIK_ABOUTDLG_FONTS_INFOW *lpcLabelsFonts
                               , UINT     horScale
                               , HICON    hIcon
                               , HICON    hIconSmall
                               , HANDLE   hAppImage
                               , POINT    *pLeftTop
                               , DWORD    aboutFlags
                               /*--------------------------*/
                               , LPCWSTR  lpcAppName
                               , LPCWSTR  lpcAppNameSubtitle
                               , LPCWSTR  lpcAppInfoString
                               , LPCWSTR  lpcAppVersionString
                               /*--------------------------*/
                               , LPCWSTR  lpcAppCopyrightString
                               , LPCWSTR  lpcAppUrlString
                               /*--------------------------*/
                               , BOOL     bTrial
                               , LPCWSTR  lpcRegisteredToNameString
                               , LPCWSTR  lpcRegisteredToEmailString
                               , LPCWSTR  lpcRegistrationExpiresDateString
                               , LPCWSTR  lpcPurchaseButtonText
                               , LPCWSTR  lpcPurchaseUrl
                               /*--------------------------*/
                               , LPCWSTR  lpcAdditionalInfoTextTitle
                               , LPCWSTR  lpcAdditionalInfoText
                               /*--------------------------*/
                               , PFN_VMPIK_AboutBoxImageClickCallback pfnImageClickCallback
                               , LPVOID                               lpvImageClickCallbackParam
                               );

Параметры:

  • hWndParent — хэндл родительского окна.
  • lpcDlgTitle — заголовок диалога. Можно задавать 0.
  • lpcLabelsFonts — указатель на структуру, содержащую информацию о шрифтах, используемых при отображении различных элементов диалога.
  • horScale — при выводе диалога его размеры автоматически адаптируются на основании заданных данных, но адаптация может быть не точной, и часть информации может быть «обрезана», или наоборот, может оставаться пустое пространство. Данный параметр позволяет уменьшить этот эффект, дополнительно масштабируя диалог по горизонтали. Этот коэффициент рекомендуется делать зависимым от локали, так как строки данных диалога для различных могут иметь разную длину. Данные коэффициент задается в процентах. Задание 0 (также как и заданий 100) оставляет ширину диалога без изменений.
  • hIcon — маленькая иконка. При использовании функции LoadImage следует задавать размер GetSystemMetrics(SM_CXICON). Можно задавать 0.
  • hIconSmall — большая иконка. При использовании функции LoadImage следует задавать размер GetSystemMetrics(SM_CXSMICON). Можно задавать 0.
  • hAppImage — изображение, помещаемое на диалог. Расположение и тип изображения задается флагами.
  • pLeftTop — задает положение верхнего левого угла диалога. Можно задавать 0, в этом случае диалог будет спозиционирован по центру экрана/родительского окна.
  • aboutFlags — см. флаги диалога «О Программе».
  • lpcAppName — название приложения, выводится увеличенным шрифтом в самом верху.
  • lpcAppNameSubtitle — подзаголовок, выводится под названием; может отсутствовать.
  • lpcAppInfoString — строка информации о приложении, выводится под подзаголовком; может отсутствовать.
  • lpcAppVersionString — строка версии приложения. Может отсутствовать, при этом может использоваться версия модуля приложения — управляется флагами.
  • lpcAppCopyrightString — строка копирайта, может отсутствовать.
  • lpcAppUrlString — задает домашний URL, подсвечивается цветом ссылки. При клике происходит переход по указанному адресу.
  • bTrial — секция диалога — сведения о регистрации. Задает признак, полная или пробная лицензия активна в данный момент.
  • lpcRegisteredToNameString — секция диалога — сведения о регистрации. Указывает, на кого зарегистрированна программа.
  • lpcRegisteredToEmailString — секция диалога — сведения о регистрации. Указывает, на кого зарегистрированна программа (email).
  • lpcRegistrationExpiresDateString — секция диалога — сведения о регистрации. Дата истечения срока действия текущей лицензии.
  • lpcPurchaseButtonText — секция диалога — сведения о регистрации. Текст кнопки «Купить».
  • lpcPurchaseUrl — секция диалога — сведения о регистрации. Если задан, то отображается кнопка купить, при нажатии которой происходит переход по указанному адресу.
  • lpcAdditionalInfoTextTitle — задает заголовок секции дополнительных сведений.
  • lpcAdditionalInfoText — задает текст дополнительных сведений, помещаемых в многострочный прокручиваемый текстовый элемент.
  • pfnImageClickCallback — задает обработчик клика по изображению. Может использоваться для добавления «пасхалки».
  • lpvImageClickCallbackParam — параметр, передаваемый в обработчик pfnImageClickCallback.

Функция-хелпер для масштабного коэффициента

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

inline
UINT VMPIKAPI VMPIK_AboutAppDlgLoadHorScale( HINSTANCE hInstance, int strId, UINT defVal )
{
    TCHAR buf[32];
    VMPIK_LoadString( hInstance, strId, buf, ARRAYSIZE(buf)-1, _T("0"));
    return _tcstol( buf, 0, 10 );
}

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

Данная статья не является заключительной в серии постов о VMPKit, ожидайте продолжения в скором будущем.

Автор: kruzhevnik

Источник

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


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