«О Царстве Теней я могу сказать только одно: есть реальность и есть её Тень; в этом суть всего. В реальном Мире существует лишь Амбер, реальный город на реальной Земле, в котором собрано всё. А Царство Теней — лишь бесконечность ирреальности. Здесь тоже можно обнаружить всё — но то будут тени, искажённое отражение реальности. Царство Теней окружает Амбер со всех сторон. А за его пределами царит хаос. На пути из Амбера в Царство Хаоса возможно всё.»
Роджер Желязны. «Девять принцев Амбера»


Всё началось с нeoбxодимocти работать с одним и тем же ключом на etoken c разных, значительно удалённых друг от друга рабочих мест (USB Over IP ради пары токенов дороговато будет) и моего большого желания открыть этот закрытый мир. Мне попалась работа habr.com/post/276057 за что её автору большой респект, в моём проекте использована значительная часть отреверсеных им функций (код ведь открытый). Правда как выяснилось всё что работает с etsdk.dll работает только с синими рыбками. Поэтому для JaCarta новые функции пришлось писать заново, а часть отредактировать.

В результате долгих изысканий появился JaCarta Editor — программа показывающая и позволяющая редактировать сущности (именно так в официальной документации называют объекты файловой системы токенов, видимо намекая на их эфемерность и ирреальность) на токенах от Аладдина, в том числе самых современных.

Аналогичное приложение для Rutoken есть в открытом доступе в составе Rutoken SDK (Rutoken Editor), но для Аладдина, по крайней мере в открытом доступе нет, хотя лет 15 назад, судя по документации которую удалось найти в интернете, такое было (ETEditor).

Программа написана на Autoit, тестировалась с EToken PRO Java 72 K, JaCarta LT, JaCarta Pro, JaCarta ГОСТ-2.

Программа не будет работать, если на компьютере установлены драйвера Rutoken (требуется чтобы EToken или Ja Carta имели номер ридера 0).

По этой же причине для корректной работы должен быть подключен только один токен.

Скрипт использует системные вызовы Window$, и тестировался только с этим семейством ОС.

Для работы требуется установка «Единого клиента JaCarta» (бесплатно скачивается с сайта производителя), при установке которого в системную папку windows устанавливается в том числе и значительно более новая версия etsdk.dll а также jcFS.dll содержащая функции JaCarta File System (очень похожие на те что в etsdk.dll, но в jcFS появилось значительно больше функций без которых работа с некоторыми современными джакартами, например ГОСТ-2, будет невозможна). При установленном Едином клиенте искать и ложить в папку с программой эту dll естественно не нужно, в ином случае при установленном драйвере конкретного вида токена эта dll должна быть в папке с программой.

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

Для того, чтобы получить доступ к корневой директории токена необходимо вызвать функцию ETRootDirOpen или JCRootDirOpen (что одинаково, так как первая в dll вызывает вторую, это справедливо почти для всех функций, но есть несколько исключений) с идентификатором вендора равным 0 (константы типа 0xF007 позволят увидеть только отдельные директории в основном старых eToken на которых хранятся банковские ключи сгенерированные с помощью утилит типа PKIAdmin и MessagePRO).

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

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

Вся информация выводится в окно вывода расположенное под деревом директорий.
Реализован ввод пин кода, выводится также информация об оставшихся попытках его ввода.
Выводится содержание директорий и краткие сведения о файлах: имя, является ли файл приватной информацией закрытой пин кодом — буква p: (ноль после неё файл публичный, единица приватный) и размер файла в байтах после «s:». Файл открывается по двойному клику.

Можно просмотреть и при необходимости скопировать в буфер содержимое файлов токена в шестнадцатеричном виде или сохранить в бинарном виде на компьютер.

Можно также изменить содержимое файла и выбрать в меню «Сохранить изменения» (предварительно должен быть введён пин код, если не был введён, то будет выведено соответствующее сообщение, в этом случае отредактированные данные можно выделить и скопировать в буфер обмена).

Для удаления файла необходимо его выделить и нажать «Удалить», после чего появится окно для подтверждения.

У JaCarta File System есть занятная особенность, которая пристутствует на всех токенах которые я тестировал. Если создать на токене директорию или несколько директорий без файлов, при следующей сессии работы с токеном они исчезнут, видимо таким образом файловая система заботится о сохранении объёма памяти токена и чистит от всякого мусора.

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

Очень важное замечание об именах директорий!

На токенах, где содержимое создано средствами производителя вы никогда не встретите директорий с одинаковыми именами, где бы они не были. Это связано с особенностями файловой системы.

Предположим, у нас на токене есть следующая сущность: //0001/A001/0008 (то есть в корневой директории находится папка 0001, в ней папка А001, а в ней файл 0008) и мы создаём на токене новую сущность: //СС00/0001/1010. При обращении к файлу 1010 начнётся поиск директории 0001, которая находится в корне и будет найдена первой, но такого файла в ней нет. В результате функция возвращает False и cущность становится потерянной, как либо обратиться к ней и удалить тоже нельзя. Поможет только инициализация токена.

Особое замечаеме про EToken PRO и JA Carta Pro, отличие у которых только во внешнем виде, у них в корневой директории находятся системные файлы (именно они показаны на скрине), в одном из которых хранится судя по всему хэш пин кода, изменение этих файлов приводит к тому что авторизация становится невозможной (пин код становится неверным) и после этого поможет только инициализация.

Относительно закрытых ключей удалось установить следующее: если на токене хранится контейнер, созданный сторонним криптопровайдером, например CryptoPro, то всё его содержимое, включая закрытые ключи будет доступно, это просто флэшка с пин кодом (что и показано на картинке). Если же ключевая пара была сгенерирована на борту токена средствами PKCS11, то будут доступны только сертификат и открытый ключ.

Поскольку это экспериментальная программа я не рекомендую использовать её с токенами содержащими действующие ключи ЭЦП, все операции выполняются на страх и риск экспериментирующего. Особенно это касается создания новых сущностей, в ряде случаев результат труднопредсказуем.

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

Собственно скрипт

JACartaEditor.au3
#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>
#include <EditConstants.au3>
#include <TreeViewConstants.au3>
#include <GuiTreeView.au3>
#include <GuiMenu.au3>
#include <MsgBoxConstants.au3>
#include <StaticConstants.au3>
#include <GuiButton.au3>
#NoTrayIcon

;функции из jcFS.dll
Dim $ETSdkDll=DllOpen('jcFS.dll')


Func ETTokenLock($BindId)
	Local $CallRes=DllCall($ETSdkDll,'WORD','ETTokenLock', _
		'DWORD',$BindId _
	)
	Return $CallRes[0] _
		?SetError($CallRes[0],0,False) _
		:True
EndFunc

Func ETTokenUnLock($BindId)
	Local $CallRes=DllCall($ETSdkDll,'WORD','ETTokenUnLock', _
		'DWORD',$BindId _
	)
	Return $CallRes[0] _
		?SetError($CallRes[0],0,False) _
		:True
EndFunc


Func ETReadersEnumOpen()
	Local $Out=DllStructCreate('DWORD')
	Local $CallRes=DllCall($ETSdkDll,'WORD','ETReadersEnumOpen', _
		'PTR',DllStructGetPtr($Out) _
	)
	Return $CallRes[0] _
		?SetError($CallRes[0],0,False) _
		:DllStructGetData($Out,1)
EndFunc

Func ETReadersEnumNext($EnumId)
	Local $Reader=DllStructCreate('CHAR name[260]; BYTE etoken;')
	Local $CallRes=DllCall($ETSdkDll,'WORD','ETReadersEnumNext', _
		'DWORD',$EnumId, _
		'PTR',DllStructGetPtr($Reader) _
	)
	Local $Result[2]=[	DllStructGetData($reader,'name'), _
						DllStructGetData($reader,'etoken')]
	Return $CallRes[0] _
		?SetError($CallRes[0],0,False) _
		:$Result
EndFunc

Func ETReadersEnumClose($EnumId)
	Local $CallRes=DllCall($ETSdkDll,'WORD','ETReadersEnumClose', _
		'DWORD',$EnumId _
	)
	Return $CallRes[0] _
		?SetError($CallRes[0],0,False) _
		:True
EndFunc

Func ETTokenBind($ReaderName)
	Local $In=DllStructCreate('BYTE['&(StringLen($ReaderName)+1)&']')
	Local $Out=DllStructCreate('DWORD')
	DllStructSetData($In,1,$ReaderName)
	Local $CallRes=DllCall($ETSdkDll,'WORD','ETTokenBind', _
		'PTR',DllStructGetPtr($Out), _
		'PTR',DllStructGetPtr($In) _
	)
	Return $CallRes[0] _
		?SetError($CallRes[0],0,False) _
		:DllStructGetData($Out,1)
EndFunc

Func ETTokenRebind($BindId)
	Local $CallRes=DllCall($ETSdkDll,'WORD','ETTokenRebind', _
		'DWORD',$BindId _
	)
	Return $CallRes[0] _
		?SetError($CallRes[0],0,False) _
		:True
EndFunc

Func ETTokenUnbind($BindId)
	Local $CallRes=DllCall($ETSdkDll,'WORD','ETTokenUnbind', _
		'DWORD',$BindId _
	)
	Return $CallRes[0] _
		?SetError($CallRes[0],0,False) _
		:True
EndFunc

Func ETTokenLogin($BindId,$Pin='')
	Local $In=DllStructCreate('BYTE['&(StringLen($Pin)+1)&']')
	DllStructSetData($In,1,$Pin)
	Local $CallRes=DllCall($ETSdkDll,'WORD','ETTokenLogin', _
		'DWORD',$BindId, _
		'PTR',DllStructGetPtr($In) _
	)
	Return $CallRes[0] _
		?SetError($CallRes[0],0,False) _
		:True
EndFunc

Func ETTokenPinChange($BindId,$Pin)
	Local $In=DllStructCreate('CHAR['&(StringLen($Pin)+1)&']')
	DllStructSetData($In,1,$Pin)
	Local $CallRes=DllCall($ETSdkDll,'WORD','ETTokenPinChange', _
		'DWORD',$BindId, _
		'PTR',DllStructGetPtr($In) _
	)
	Return $CallRes[0] _
		?SetError($CallRes[0],0,False) _
		:True
EndFunc

Func ETTokenLogout($BindId)
	Local $CallRes=DllCall($ETSdkDll,'WORD','ETTokenLogout', _
		'DWORD',$BindId _
	)
	Return $CallRes[0] _
		?SetError($CallRes[0],0,False) _
		:True
EndFunc

Func ETRootDirOpen($BindId,$Dir=0xF007)
	Local $Out=DllStructCreate('DWORD')
	Local $CallRes=DllCall($ETSdkDll,'WORD','ETRootDirOpen', _
		'PTR',DllStructGetPtr($Out), _
		'DWORD',$BindId, _
		'DWORD',$Dir _
	)
	Return $CallRes[0] _
		?SetError($CallRes[0],0,False) _
		:DllStructGetData($Out,1)
EndFunc

Func ETDirOpen($Dir,$DirId)
	Local $Out=DllStructCreate('DWORD')
	Local $CallRes=DllCall($ETSdkDll,'WORD','ETDirOpen', _
		'PTR',DllStructGetPtr($Out), _
		'DWORD',$Dir, _
		'DWORD',$DirId _
	)
	Return $CallRes[0] _
		?SetError($CallRes[0],0,False) _
		:DllStructGetData($Out,1)
EndFunc

Func ETDirCreate($Dir,$DirId)
	Local $Out=DllStructCreate('DWORD')
	Local $CallRes=DllCall($ETSdkDll,'WORD','ETDirCreate', _
		'PTR',DllStructGetPtr($Out), _
		'DWORD',$Dir, _
		'DWORD',$DirId, _
		'DWORD',0 _
	)
	Return $CallRes[0] _
		?SetError($CallRes[0],0,False) _
		:DllStructGetData($Out,1)
EndFunc

Func ETDirGetInfo($DirId)
	Local $Out=DllStructCreate('WORD wDirName; WORD wSize')
	Local $CallRes=DllCall($ETSdkDll,'WORD','ETDirGetInfo', _
		'DWORD',$DirId, _
		'PTR',DllStructGetPtr($Out) _
	)
Local $Result[2]=[	DllStructGetData($Out,'wDirName'), _
						DllStructGetData($Out,'wSize')]

	Return $CallRes[0] _
		?SetError($CallRes[0],0,False) _
		:$Result

EndFunc

Func ETDirClose($DirId)
	Local $CallRes=DllCall($ETSdkDll,'WORD','ETDirClose', _
		'DWORD',$DirId _
	)


	Return $CallRes[0] _
		?SetError($CallRes[0],0,False) _
		:True
EndFunc

Func ETDirDelete($DirId)
	Local $CallRes=DllCall($ETSdkDll,'WORD','ETDirDelete', _
		'DWORD',$DirId _
	)
	Return $CallRes[0] _
		?SetError($CallRes[0],0,False) _
		:True
EndFunc

Func ETDirEnumOpen($DirId)
	Local $Out=DllStructCreate('DWORD')
	Local $CallRes=DllCall($ETSdkDll,'WORD','ETDirEnumOpen', _
		'PTR',DllStructGetPtr($Out), _
		'DWORD',$DirId _
	)
	Return $CallRes[0] _
		?SetError($CallRes[0],0,False) _
		:DllStructGetData($Out,1)
EndFunc

Func ETDirEnumNext($EnumId)
	Local $Out=DllStructCreate('DWORD')
	Local $CallRes=DllCall($ETSdkDll,'WORD','ETDirEnumNext', _
		'DWORD',$EnumId, _
		'PTR',DllStructGetPtr($Out) _
	)
	Return $CallRes[0] _
		?SetError($CallRes[0],0,False) _
		:DllStructGetData($Out,1)
EndFunc

Func ETDirEnumClose($EnumId)
	Local $CallRes=DllCall($ETSdkDll,'WORD','ETDirEnumClose', _
		'DWORD',$EnumId _
	)
	Return $CallRes[0] _
		?SetError($CallRes[0],0,False) _
		:True
EndFunc

Func ETFileOpen($File,$DirId)
	Local $Out=DllStructCreate('DWORD')
	Local $CallRes=DllCall($ETSdkDll,'WORD','ETFileOpen', _
		'PTR',DllStructGetPtr($Out), _
		'DWORD',$DirId, _
		'DWORD',$File _
	)
	Return $CallRes[0] _
		?SetError($CallRes[0],0,False) _
		:DllStructGetData($Out,1)
EndFunc

Func ETFileCreate($File,$DirId,$Size,$Private=0)
	Local $Out=DllStructCreate('DWORD')
	Local $CallRes=DllCall($ETSdkDll,'WORD','ETFileCreate', _
		'PTR',DllStructGetPtr($Out), _
		'DWORD',$DirId, _
		'DWORD',$File, _
		'DWORD',$Size, _
		'DWORD',$Private _
	)
	Return $CallRes[0] _
		?SetError($CallRes[0],0,False) _
		:DllStructGetData($Out,1)
EndFunc

Func ETFileGetInfo($FileId)
	Local $Out=DllStructCreate('WORD name;WORD private;WORD;WORD size')
	Local $CallRes=DllCall($ETSdkDll,'WORD','ETFileGetInfo', _
		'DWORD',$FileId, _
		'PTR',DllStructGetPtr($Out) _
	)
	Local $Result[3]=[	DllStructGetData($Out,'name'), _
						DllStructGetData($Out,'private'), _
						DllStructGetData($Out,'size')]
	Return $CallRes[0] _
		?SetError($CallRes[0],0,False) _
		:$Result
EndFunc

Func ETFileRead($FileId)
	Local $FileInfo=ETFileGetInfo($FileId)
	If @error Then Return SetError(@error,0,False)
	Local $Out=DllStructCreate('BYTE ['&$FileInfo[2]&']')
	Local $CallRes=DllCall($ETSdkDll,'WORD','ETFileRead', _
		'DWORD',$FileId, _
		'DWORD',0, _
		'DWORD',0xFFFF, _
		'PTR',DllStructGetPtr($Out), _
		'DWORD',$FileInfo[2] _
	)
	Return $CallRes[0] _
		?SetError($CallRes[0],0,False) _
		:DllStructGetData($Out,1)
EndFunc

Func ETFileWrite($FileId,$Data,$Pos=0)
	$Data=Binary($Data)
	Local $DataSize=BinaryLen($Data)
	Local $In=DllStructCreate('BYTE['&$DataSize&']')
	DllStructSetData($In,1,$Data)
	Local $CallRes=DllCall($ETSdkDll,'WORD','ETFileWrite', _
		'DWORD',$FileId, _
		'DWORD',$Pos, _
		'PTR',DllStructGetPtr($In), _
		'DWORD',$DataSize _
	)
	Return $CallRes[0] _
		?SetError($CallRes[0],0,False) _
		:True
EndFunc

Func ETFileClose($FileId)
	Local $CallRes=DllCall($ETSdkDll,'WORD','ETFileClose', _
		'DWORD',$FileId _
	)
	Return $CallRes[0] _
		?SetError($CallRes[0],0,False) _
		:True
EndFunc

Func ETFileDelete($FileId)
	Local $CallRes=DllCall($ETSdkDll,'WORD','ETFileDelete', _
		'DWORD',$FileId _
	)
	Return $CallRes[0] _
		?SetError($CallRes[0],0,False) _
		:True
EndFunc

Func ETFilesEnumOpen($DirId)
	Local $Out=DllStructCreate('DWORD')
	Local $CallRes=DllCall($ETSdkDll,'WORD','ETFilesEnumOpen', _
		'PTR',DllStructGetPtr($Out), _
		'DWORD',$DirId _
	)

	Return $CallRes[0] _
		?SetError($CallRes[0],0,False) _
		:DllStructGetData($Out,1)
EndFunc

Func ETFilesEnumNext($EnumId)
	Local $Out=DllStructCreate('DWORD')
	Local $CallRes=DllCall($ETSdkDll,'WORD','ETFilesEnumNext', _
		'DWORD',$EnumId, _
		'PTR',DllStructGetPtr($Out) _
	)
	Return $CallRes[0] _
		?SetError($CallRes[0],0,False) _
		:DllStructGetData($Out,1)
EndFunc

Func ETFilesEnumClose($EnumId)
	Local $CallRes=DllCall($ETSdkDll,'WORD','ETFilesEnumClose', _
		'DWORD',$EnumId _
	)
	Return $CallRes[0] _
		?SetError($CallRes[0],0,False) _
		:True
EndFunc

Func ETTokenLabelGet($BindId)
	Local $Out1=DllStructCreate('DWORD')
	Local $CallRes=DllCall($ETSdkDll,'WORD','ETTokenLabelGet', _
		'DWORD',$BindId, _
		'PTR',0, _
		'PTR',DllStructGetPtr($Out1) _
	)
	If $CallRes[0] Then Return SetError($CallRes[0],0,False)
	Local $Out2=DllStructCreate('CHAR['&DllStructGetData($Out1,1)&']')
	$CallRes=DllCall($ETSdkDll,'WORD','ETTokenLabelGet', _
		'DWORD',$BindId, _
		'PTR',DllStructGetPtr($Out2), _
		'PTR',DllStructGetPtr($Out1) _
	)
	Return $CallRes[0] _
		?SetError($CallRes[0],0,False) _
		:DllStructGetData($Out2,1)
EndFunc

Func ETTokenIDGet($BindId)
	Local $Out1=DllStructCreate('DWORD')
	Local $CallRes=DllCall($ETSdkDll,'WORD','ETTokenIDGet', _
		'DWORD',$BindId, _
		'PTR',0, _
		'PTR',DllStructGetPtr($Out1) _
	)
	If $CallRes[0] Then Return SetError($CallRes[0],0,False)
	Local $Out2=DllStructCreate('CHAR['&DllStructGetData($Out1,1)&']')
	$CallRes=DllCall($ETSdkDll,'WORD','ETTokenIDGet', _
		'DWORD',$BindId, _
		'PTR',DllStructGetPtr($Out2), _
		'PTR',DllStructGetPtr($Out1) _
	)
	Return $CallRes[0] _
		?SetError($CallRes[0],0,False) _
		:DllStructGetData($Out2,1)
EndFunc

Func ETTokenMaxPinGet($BindId)
	Local $Out=DllStructCreate('DWORD')
	Local $CallRes=DllCall($ETSdkDll,'WORD','ETTokenMaxPinGet', _
		'DWORD',$BindId, _
		'PTR',DllStructGetPtr($Out) _
	)
	Return $CallRes[0] _
		?SetError($CallRes[0],0,False) _
		:DllStructGetData($Out,1)
EndFunc

Func ETTokenMinPinGet($BindId)
	Local $Out=DllStructCreate('DWORD')
	Local $CallRes=DllCall($ETSdkDll,'WORD','ETTokenMinPinGet', _
		'DWORD',$BindId, _
		'PTR',DllStructGetPtr($Out) _
	)
	Return $CallRes[0] _
		?SetError($CallRes[0],0,False) _
		:DllStructGetData($Out,1)
EndFunc



Func ETSelectApplet($BindId, $Applet)

Local $In=DllStructCreate('DWORD')
	DllStructSetData($In,1,$Applet)
	Local $CallRes=DllCall($ETSdkDll,'WORD','ETSelectApplet', _
		'DWORD',$BindId, _
		'PTR',DllStructGetPtr($Applet) _
	)
	Return $CallRes[0] _
		?SetError($CallRes[0],0,False) _
		:True

EndFunc

Func JCSelectApplet($BindId, $Applet)

Local $In=DllStructCreate('WORD')
	DllStructSetData($In,1,$Applet)
	Local $CallRes=DllCall($ETSdkDll,'WORD','JCSelectApplet', _
		'DWORD',$BindId, _
		'WORD',$Applet _
	)
	Return $CallRes[0] _
		?SetError($CallRes[0],0,False) _
		:True

EndFunc



Func JCReadersEnumOpen()
	Local $Out=DllStructCreate('DWORD')
	Local $CallRes=DllCall($ETSdkDll,'WORD','JCReadersEnumOpen', _
		'PTR',DllStructGetPtr($Out) _
	)
	Return $CallRes[0] _
		?SetError($CallRes[0],0,False) _
		:DllStructGetData($Out,1)
EndFunc

Func JCReadersEnumNext($EnumId)
	Local $Reader=DllStructCreate('CHAR name[260]; BYTE etoken;')
	Local $CallRes=DllCall($ETSdkDll,'WORD','JCReadersEnumNext', _
		'DWORD',$EnumId, _
		'PTR',DllStructGetPtr($Reader) _
	)
	Local $Result[2]=[	DllStructGetData($reader,'name'), _
						DllStructGetData($reader,'etoken')]
	Return $CallRes[0] _
		?SetError($CallRes[0],0,False) _
		:$Result
EndFunc

Func JCReadersEnumClose($EnumId)
	Local $CallRes=DllCall($ETSdkDll,'WORD','JCReadersEnumClose', _
		'DWORD',$EnumId _
	)
	Return $CallRes[0] _
		?SetError($CallRes[0],0,False) _
		:True
EndFunc

Func JCTokenBind($ReaderName)
	Local $In=DllStructCreate('CHAR['&(StringLen($ReaderName)+1)&']')
	Local $Out=DllStructCreate('DWORD')
	DllStructSetData($In,1,$ReaderName)
	Local $CallRes=DllCall($ETSdkDll,'WORD','JCTokenBind', _
		'PTR',DllStructGetPtr($Out), _
		'PTR',DllStructGetPtr($In) _
	)
	Return $CallRes[0] _
		?SetError($CallRes[0],0,False) _
		:DllStructGetData($Out,1)
EndFunc

Func JCTokenRebind($BindId)
	Local $CallRes=DllCall($ETSdkDll,'WORD','JCTokenRebind', _
		'DWORD',$BindId _
	)
	Return $CallRes[0] _
		?SetError($CallRes[0],0,False) _
		:True
EndFunc

Func JCTokenUnbind($BindId)
	Local $CallRes=DllCall($ETSdkDll,'WORD','JCTokenUnbind', _
		'DWORD',$BindId _
	)
	Return $CallRes[0] _
		?SetError($CallRes[0],0,False) _
		:True
EndFunc

Func JCTokenLogin($BindId,$Pin)
	Local $In=DllStructCreate('CHAR['&(StringLen($Pin)+1)&']')
	DllStructSetData($In,1,$Pin)
	Local $CallRes=DllCall($ETSdkDll,'WORD','JCTokenLogin', _
		'DWORD',$BindId, _
		'PTR',DllStructGetPtr($In) _
	)
	Return $CallRes[0] _
		?SetError($CallRes[0],0,False) _
		:True
EndFunc

Func JCTokenPinChange($BindId,$Pin)
	Local $In=DllStructCreate('CHAR['&(StringLen($Pin)+1)&']')
	DllStructSetData($In,1,$Pin)
	Local $CallRes=DllCall($ETSdkDll,'WORD','JCTokenPinChange', _
		'DWORD',$BindId, _
		'PTR',DllStructGetPtr($In) _
	)
	Return $CallRes[0] _
		?SetError($CallRes[0],0,False) _
		:True
EndFunc

Func JCTokenLogout($BindId)
	Local $CallRes=DllCall($ETSdkDll,'WORD','JCTokenLogout', _
		'DWORD',$BindId _
	)
	Return $CallRes[0] _
		?SetError($CallRes[0],0,False) _
		:True
EndFunc

Func JCRootDirOpen($BindId,$Dir=0)
	Local $Out=DllStructCreate('DWORD')
	Local $CallRes=DllCall($ETSdkDll,'WORD','JCRootDirOpen', _
		'PTR',DllStructGetPtr($Out), _
		'DWORD',$BindId, _
		'WORD',$Dir _
	)
	Return $CallRes[0] _
		?SetError($CallRes[0],0,False) _
		:DllStructGetData($Out,1)
EndFunc

Func JCDirOpen($Dir,$DirId)
	Local $Out=DllStructCreate('DWORD')
	Local $CallRes=DllCall($ETSdkDll,'WORD','JCDirOpen', _
		'PTR',DllStructGetPtr($Out), _
		'DWORD',$Dir, _
		'DWORD',$DirId _
	)
	Return $CallRes[0] _
		?SetError($CallRes[0],0,False) _
		:DllStructGetData($Out,1)
EndFunc

Func JCDirCreate($Dir,$DirId)
	Local $Out=DllStructCreate('DWORD')
	Local $CallRes=DllCall($ETSdkDll,'WORD','JCDirCreate', _
		'PTR',DllStructGetPtr($Out), _
		'DWORD',$Dir, _
		'DWORD',$DirId, _
		'DWORD',0 _
	)
	Return $CallRes[0] _
		?SetError($CallRes[0],0,False) _
		:DllStructGetData($Out,1)
EndFunc

Func JCDirGetInfo($DirId)
	Local $Out=DllStructCreate('BYTE[8]')
	Local $CallRes=DllCall($ETSdkDll,'WORD','JCDirGetInfo', _
		'DWORD',$DirId, _
		'PTR',DllStructGetPtr($Out) _
	)
	Return $CallRes[0] _
		?SetError($CallRes[0],0,False) _
		:DllStructGetData($Out,1)
EndFunc

Func JCDirClose($DirId)
	Local $CallRes=DllCall($ETSdkDll,'WORD','JCDirClose', _
		'DWORD',$DirId _
	)
	Return $CallRes[0] _
		?SetError($CallRes[0],0,False) _
		:True
EndFunc

Func JCDirDelete($DirId)
	Local $CallRes=DllCall($ETSdkDll,'WORD','JCDirDelete', _
		'DWORD',$DirId _
	)
	Return $CallRes[0] _
		?SetError($CallRes[0],0,False) _
		:True
EndFunc

Func JCDirEnumOpen($DirId)
	Local $Out=DllStructCreate('DWORD')
	Local $CallRes=DllCall($ETSdkDll,'WORD','JCDirEnumOpen', _
		'PTR',DllStructGetPtr($Out), _
		'DWORD',$DirId _
	)
	Return $CallRes[0] _
		?SetError($CallRes[0],0,False) _
		:DllStructGetData($Out,1)
EndFunc

Func JCDirEnumNext($EnumId)
	Local $Out=DllStructCreate('DWORD')
	Local $CallRes=DllCall($ETSdkDll,'WORD','JCDirEnumNext', _
		'DWORD',$EnumId, _
		'PTR',DllStructGetPtr($Out) _
	)
	Return $CallRes[0] _
		?SetError($CallRes[0],0,False) _
		:DllStructGetData($Out,1)
EndFunc

Func JCDirEnumClose($EnumId)
	Local $CallRes=DllCall($ETSdkDll,'WORD','JCDirEnumClose', _
		'DWORD',$EnumId _
	)
	Return $CallRes[0] _
		?SetError($CallRes[0],0,False) _
		:True
EndFunc

Func JCFileOpen($File,$DirId)
	Local $Out=DllStructCreate('DWORD')
	Local $CallRes=DllCall($ETSdkDll,'WORD','JCFileOpen', _
		'PTR',DllStructGetPtr($Out), _
		'DWORD',$DirId, _
		'DWORD',$File _
	)
	Return $CallRes[0] _
		?SetError($CallRes[0],0,False) _
		:DllStructGetData($Out,1)
EndFunc

Func JCFileCreate($File,$DirId,$Size,$Private=0)
	Local $Out=DllStructCreate('DWORD')
	Local $CallRes=DllCall($ETSdkDll,'WORD','JCFileCreate', _
		'PTR',DllStructGetPtr($Out), _
		'DWORD',$DirId, _
		'DWORD',$File, _
		'DWORD',$Size, _
		'DWORD',$Private _
	)
	Return $CallRes[0] _
		?SetError($CallRes[0],0,False) _
		:DllStructGetData($Out,1)
EndFunc

Func JCFileGetInfo($FileId)
	Local $Out=DllStructCreate('WORD name;WORD private;WORD;WORD size')
	Local $CallRes=DllCall($ETSdkDll,'WORD','JCFileGetInfo', _
		'DWORD',$FileId, _
		'PTR',DllStructGetPtr($Out) _
	)
	Local $Result[3]=[	DllStructGetData($Out,'name'), _
						DllStructGetData($Out,'private'), _
						DllStructGetData($Out,'size')]
	Return $CallRes[0] _
		?SetError($CallRes[0],0,False) _
		:$Result
EndFunc

Func JCFileRead($FileId)
	Local $FileInfo=JCFileGetInfo($FileId)
	If @error Then Return SetError(@error,0,False)
	Local $Out=DllStructCreate('BYTE ['&$FileInfo[2]&']')
	Local $CallRes=DllCall($ETSdkDll,'WORD','JCFileRead', _
		'DWORD',$FileId, _
		'DWORD',0, _
		'DWORD',0xFFFF, _
		'PTR',DllStructGetPtr($Out), _
		'DWORD',$FileInfo[2] _
	)
	Return $CallRes[0] _
		?SetError($CallRes[0],0,False) _
		:DllStructGetData($Out,1)
EndFunc

Func JCFileWrite($FileId,$Data,$Pos=0)
	$Data=Binary($Data)
	Local $DataSize=BinaryLen($Data)
	Local $In=DllStructCreate('BYTE['&$DataSize&']')
	DllStructSetData($In,1,$Data)
	Local $CallRes=DllCall($ETSdkDll,'WORD','JCFileWrite', _
		'DWORD',$FileId, _
		'DWORD',$Pos, _
		'PTR',DllStructGetPtr($In), _
		'DWORD',$DataSize _
	)
	Return $CallRes[0] _
		?SetError($CallRes[0],0,False) _
		:True
EndFunc

Func JCFileClose($FileId)
	Local $CallRes=DllCall($ETSdkDll,'WORD','JCFileClose', _
		'DWORD',$FileId _
	)
	Return $CallRes[0] _
		?SetError($CallRes[0],0,False) _
		:True
EndFunc

Func JCFileDelete($FileId)
	Local $CallRes=DllCall($ETSdkDll,'WORD','JCFileDelete', _
		'DWORD',$FileId _
	)
	Return $CallRes[0] _
		?SetError($CallRes[0],0,False) _
		:True
EndFunc

Func JCFilesEnumOpen($DirId)
	Local $Out=DllStructCreate('DWORD')
	Local $CallRes=DllCall($ETSdkDll,'WORD','JCFilesEnumOpen', _
		'PTR',DllStructGetPtr($Out), _
		'DWORD',$DirId _
	)

	Return $CallRes[0] _
		?SetError($CallRes[0],0,False) _
		:DllStructGetData($Out,1)
EndFunc

Func JCFilesEnumNext($EnumId)
	Local $Out=DllStructCreate('DWORD')
	Local $CallRes=DllCall($ETSdkDll,'WORD','JCFilesEnumNext', _
		'DWORD',$EnumId, _
		'PTR',DllStructGetPtr($Out) _
	)
	Return $CallRes[0] _
		?SetError($CallRes[0],0,False) _
		:DllStructGetData($Out,1)
EndFunc

Func JCFilesEnumClose($EnumId)
	Local $CallRes=DllCall($ETSdkDll,'WORD','JCFilesEnumClose', _
		'DWORD',$EnumId _
	)
	Return $CallRes[0] _
		?SetError($CallRes[0],0,False) _
		:True
EndFunc

Func JCTokenLabelGet($BindId)
	Local $Out1=DllStructCreate('DWORD')
	Local $CallRes=DllCall($ETSdkDll,'WORD','JCTokenLabelGet', _
		'DWORD',$BindId, _
		'PTR',0, _
		'PTR',DllStructGetPtr($Out1) _
	)
	If $CallRes[0] Then Return SetError($CallRes[0],0,False)
	Local $Out2=DllStructCreate('CHAR['&DllStructGetData($Out1,1)&']')
	$CallRes=DllCall($ETSdkDll,'WORD','JCTokenLabelGet', _
		'DWORD',$BindId, _
		'PTR',DllStructGetPtr($Out2), _
		'PTR',DllStructGetPtr($Out1) _
	)
	Return $CallRes[0] _
		?SetError($CallRes[0],0,False) _
		:DllStructGetData($Out2,1)
EndFunc

Func JCTokenIDGet($BindId)
	Local $Out1=DllStructCreate('DWORD')
	Local $CallRes=DllCall($ETSdkDll,'WORD','JCTokenIDGet', _
		'DWORD',$BindId, _
		'PTR',0, _
		'PTR',DllStructGetPtr($Out1) _
	)
	If $CallRes[0] Then Return SetError($CallRes[0],0,False)
	Local $Out2=DllStructCreate('CHAR['&DllStructGetData($Out1,1)&']')
	$CallRes=DllCall($ETSdkDll,'WORD','JCTokenIDGet', _
		'DWORD',$BindId, _
		'PTR',DllStructGetPtr($Out2), _
		'PTR',DllStructGetPtr($Out1) _
	)
	Return $CallRes[0] _
		?SetError($CallRes[0],0,False) _
		:DllStructGetData($Out2,1)
EndFunc

Func JCTokenMaxPinGet($BindId)
	Local $Out=DllStructCreate('DWORD')
	Local $CallRes=DllCall($ETSdkDll,'WORD','JCTokenMaxPinGet', _
		'DWORD',$BindId, _
		'PTR',DllStructGetPtr($Out) _
	)
	Return $CallRes[0] _
		?SetError($CallRes[0],0,False) _
		:DllStructGetData($Out,1)
EndFunc

Func JCTokenMinPinGet($BindId)
	Local $Out=DllStructCreate('DWORD')
	Local $CallRes=DllCall($ETSdkDll,'WORD','JCTokenMinPinGet', _
		'DWORD',$BindId, _
		'PTR',DllStructGetPtr($Out) _
	)
	Return $CallRes[0] _
		?SetError($CallRes[0],0,False) _
		:DllStructGetData($Out,1)
EndFunc

Func JCTokenUnLock($BindId)
	Local $CallRes=DllCall($ETSdkDll,'WORD','JCTokenUnLock', _
		'DWORD',$BindId _
	)
	Return $CallRes[0] _
		?SetError($CallRes[0],0,False) _
		:True
EndFunc

Func JCTokenLock($BindId)
	Local $CallRes=DllCall($ETSdkDll,'WORD','JCTokenLock', _
		'DWORD',$BindId _
	)
	Return $CallRes[0] _
		?SetError($CallRes[0],0,False) _
		:True
EndFunc

Func JCTokenPinAttemptsGet($BindId)
	Local $Out=DllStructCreate('DWORD')
	Local $CallRes=DllCall($ETSdkDll,'WORD','JCTokenPinAttemptsGet', _
		'DWORD',$BindId, _
		'PTR',DllStructGetPtr($Out) _
	)
	Return $CallRes[0] _
		?SetError($CallRes[0],0,False) _
		:DllStructGetData($Out,1)
EndFunc

;Начало приложения
Opt("GUIOnEventMode", 1)
Dim $BindId, $filelog, $Result, $DirIdRoot=False, $Edit, $msg, $Fileinfo, $treeview, $generalitem, $displayitem, $diritem, $Edit, $SrcSubId, $Output, $pinbutton, $hPinWin, $PinEdit, $pinokbutton, $pincancelbutton, $Pin, $Edit1, $Reader, $Applet, $AppletID, $text, $CreateDirWin
Global $Dir1, $Dir2
Dim $hParentWin, $hChildWin, $sItemText, $folderbutton, $filebutton, $deletebutton, $CreateFileWin, $FileEdit, $fileokbutton, $filecancelbutton, $publicbutton, $privatebutton, $sizefile
Dim $hFile, $hMain
Global Enum $idSave= 1000, $Save
Dim $Appname = 'JaCarta Editor'


;Функция получения applet ID брутфорсом
Func Applet()
	  GUICtrlSetData($Output, 'Попытка получить applet ID... '&@CRLF,1)
	  Local $Result, $AppletTemp= 0
	  For $Applet = 0 To 65535  Step 1
		 $Result = 0
		 $Result=JCSelectApplet($BindId,$Applet) ; 0x2001 PROJAVA для E-token, 0x1002 PRO, 0x1001 R2, 0x2202 GOST, 0x2205 DATASTORE, 0x2206 ГОСТ-2, 0x2201, 0x2204 (чёрные JaCarta)

			If $Result = True   Then
			   $AppletTemp=$Applet
			   $AppletID=$Applet
			   ExitLoop
			EndIf
	  Next

	  Local $Id=ETTokenLabelGet($BindId)
	  if $Id= False Then
		 For $Applet=$AppletTemp+1 To 65535  Step 1
			 $Result=0
			 $Result=JCSelectApplet($BindId,$Applet)
			   If $Result = True   Then
				  ExitLoop
			   EndIf
		 Next
	  EndIf
	  JCSelectApplet($BindId,$Applet)
	  GUICtrlSetData($Output, 'Select applet 0x'&hex($Applet,4)&@CRLF,1)
	  $AppletID=$Applet
EndFunc


;Просмотр директорий и файлов в цикле
Func PrintDir($Id,$Prefix)

	  Local $EnumId=ETDirEnumOpen($Id)
	  While 1
			Local $dir=ETDirEnumNext($EnumId)
			If @error Then ExitLoop
			Local $DirId=ETDirOpen($dir,$Id)
			Local   $Dirinfo
			$Dirinfo=ETDirGetInfo($DirId)
			Local $Dirtext='(dir)'&hex($dir,4)
			$diritem = _GUICtrlTreeView_AddChild($treeview,$Prefix, $Dirtext)
			PrintDir($DirId,$diritem)
			ETDirClose($DirId)
	  WEnd
	  ETDirEnumClose($EnumId)

	  $EnumId=ETFilesEnumOpen($Id)
	  While 1
			Local $file=ETFilesEnumNext($EnumId)
			If @error Then ExitLoop
			Local $FileId=ETFileOpen($file,$Id)
			$Fileinfo=ETFileGetInfo($FileId)
			Local $filetext='(file)'&hex($file,5)&' '&'p: '&$Fileinfo[1]&' s: '&$Fileinfo[2]&@CRLF
			_GUICtrlTreeView_AddChild($treeview,$Prefix,$filetext)
	  WEnd
	  ETFilesEnumClose($EnumId)
EndFunc

;операции подключения к токену и получения от него информации
Func List()
		 GUICtrlSetData($Output, '')
		 Local $text
		 Local $EnumId=ETReadersEnumOpen()

		 GUICtrlSetData($Output, 'В системе установлены ридеры:'&@CRLF,1)
		 While 1
			   $Reader=ETReadersEnumNext($EnumId)
			   If @error Then ExitLoop
			   GUICtrlSetData($Output, $Reader[0]&@CRLF,1)
		 WEnd
		 ETReadersEnumClose($EnumId)
		 Local $EnumId=ETReadersEnumOpen()
		 $Reader=ETReadersEnumNext($EnumId)
		 $BindId=ETTokenBind($Reader[0])
		 $Result=JCTokenLock($BindId)
		 GUICtrlSetData($Output, 'Подключен ридер '&$Reader[0]&@CRLF,1)

		 ;если не получается получить ID токена, значит надо подбирать AppletID
		 $Result=ETTokenIDGet($BindId)
		 if $Result= False Then
			if $AppletID<>0 Then
			   JCSelectApplet($BindId,$AppletID)
			Else
			   Applet()
			EndIf
		 EndIf

		 $Result=ETTokenIDGet($BindId)
		 $text=$Reader[0]&' ID '&$Result
		 $generalitem = _GUICtrlTreeView_AddChild($treeview,0,$text)
		 $Result=ETTokenLabelGet($BindId)
		 GUICtrlSetData($Output, 'Label: '&$Result&@CRLF,1)
		 $DirIdRoot=ETRootDirOpen($BindId,0) ;0xF007 для банков 0x0001 для крипто про
		 $Result=JCTokenPinAttemptsGet($BindId)

		 ;если был введён пин код начинаем авторизацию
		 If $Pin <> 0   Then
			$Result=JCTokenLogin($BindId,$Pin)
			If $Result=False   Then
			   $Result=JCTokenPinAttemptsGet($BindId)
			   MsgBox(0x10,$Appname,'Неверный PIN код'&@CRLF&'Количество попыток ввода PIN кода: '&$Result )
			Else
			GUICtrlSetData($Output, 'Login OK'&@CRLF,1)
			EndIf
		 EndIf
		 $Result=JCTokenPinAttemptsGet($BindId)
		 GUICtrlSetData($Output, 'Количество попыток ввода PIN кода: '&$Result&@CRLF,1)
		 PrintDir($DirIdRoot,0)
		 ETTokenUnbind($BindId)
		 ETReadersEnumClose($EnumId)

EndFunc

;закрытие дочерних окон и программы
Func onClose()
	  GUISetState(@SW_HIDE, $hPinWin)
	  GUISetState(@SW_HIDE, $hChildWin)
	  GUISetState(@SW_HIDE, $CreateFileWin)
	  if @GUI_WinHandle=$hParentWin Then
		 Exit
	  EndIf
EndFunc

;вывод окна ввода пин кода
Func onPin()
	  GUISetState(@SW_SHOW, $hPinWin )
EndFunc

;подготовка к авторизации после ввода пин кода
Func onPinOK()
	  $Pin=GUICtrlRead($PinEdit)
	  GUISetState(@SW_HIDE, $hPinWin)
	  _GUICtrlTreeView_DeleteAll ($treeview)
	  List()
EndFunc

;отмена ввода пин кода
Func onPinCancel()
	  GUISetState(@SW_HIDE, $hPinWin)
EndFunc

;функция удаления
Func Delete()
	  If $Pin=0   Then
		 MsgBox(0x10,$Appname,'Для удаления файла сначала введите пин код' )
	  Else
		 Local $hItem = _GUICtrlTreeView_GetSelection($treeview)
		 Local $Del = _GUICtrlTreeView_GetText($treeview, $hItem)
		 if _GUICtrlTreeView_GetChildren($treeview, $hItem)=False Then
			$Del=StringTrimLeft (  $Del, 6 )
			Local $p=0
			$p=StringInStr ($Del,"p:")
			$Del=StringMid ( $Del, 1, $p-2 )
			if MsgBox(4 + 32, $Appname,  'Удалить '& $Del &' ?') = 6 Then
			   Local $DirID=_GUICtrlTreeView_GetParentHandle($treeview, $hItem)
			   Local $Dir= _GUICtrlTreeView_GetText($treeview, $DirID)
			   $Dir=StringTrimLeft (  $Dir, 5 )
			   $BindId=ETTokenBind($Reader[0])
			   $Result=JCTokenLock($BindId)

			   if $AppletID<>0 Then
				  JCSelectApplet($BindId,$AppletID)
			   EndIf

			   If $Pin <> 0   Then
				  $Result=JCTokenLogin($BindId,$Pin)
				  If $Result=False   Then
					 $Result=JCTokenPinAttemptsGet($BindId)
					 MsgBox(0x10,$Appname,'Неверный PIN код'&@CRLF&'Количество попыток ввода PIN кода: '&$Result)
				  EndIf
			   EndIf

			   Local $HDir=GetDir(ETRootDirOpen($BindId,0), $Dir)
			   Local $DELFile =JCFileOpen(Dec ($Del), $HDir)
			   JCFileDelete($DELFile )
			   ETDirClose($HDir)
			   ETTokenUnbind($BindId)

			   _GUICtrlTreeView_DeleteAll ($treeview)
               List()
			EndIf

		 Else
			   MsgBox(0x10,$Appname,'Сначала удалите все файлы в папке после чего папка будет удалена автоматически' )
		 EndIf
	  EndIf
EndFunc

;функция вывода окна создания файла
Func onFileCreate()
	  If $Pin=0   Then
		 MsgBox(0x10,$Appname,'Для создания файла сначала введите пин код' )
	  Else
		 Local $hItem = _GUICtrlTreeView_GetSelection($treeview)
		 Local $FileText = 0, $Dir1=0, $Dir2=0
		 $FileText = _GUICtrlTreeView_GetText($treeview, $hItem)

		 ;Проверка не выбрана ли корневая директория
		 if  StringLen($FileText) >20 Then
			   GUICtrlSetData($FileEdit, '')
			   GUICtrlSetData($FileEdit, '//',0)
		 Else
			   $Dir1=StringTrimLeft (  $FileText, 5 )

			   Local $ParentID=_GUICtrlTreeView_GetParentHandle($treeview, $hItem)
			   Local $ParentDir= _GUICtrlTreeView_GetText($treeview, $ParentID)
			   if StringInStr ($ParentDir,"Dir")=0 Then
				  $ParentDir=''
				  GUICtrlSetData($FileEdit, '')
				  GUICtrlSetData($FileEdit, '//'&$Dir1&'/',0)
			   Else
				  $Dir2=StringTrimLeft (  $ParentDir, 5 )
				  $Dir2='/'&$Dir2
				  GUICtrlSetData($FileEdit, '')
				  GUICtrlSetData($FileEdit, '/'&$Dir2&'/'&$Dir1&'/',0)
			   EndIf

		 EndIf
		 GUISetState(@SW_SHOW, $CreateFileWin)
	  EndIf
EndFunc


;отмена создания файла
Func onFileCancel()
	  GUISetState(@SW_HIDE, $CreateFileWin)
EndFunc

;функция создания файла
Func onFileOK()
	  Local $filename=GUICtrlRead($FileEdit)
	  Local $isPrivate=_GUICtrlButton_GetCheck($privatebutton)
	  Local $fileSize=GUICtrlRead($sizefile)
	  $BindId=ETTokenBind($Reader[0])
	  $Result=JCTokenLock($BindId)

	  if $AppletID<>0 Then
		 JCSelectApplet($BindId,$AppletID)
	  EndIf

	  If $Pin <> 0   Then
		 $Result=JCTokenLogin($BindId,$Pin)
		 If $Result=False   Then
			$Result=JCTokenPinAttemptsGet($BindId)
			MsgBox(0x10,$Appname,'Неверный PIN код'&@CRLF&'Количество попыток ввода PIN кода: '&$Result )
		 EndIf
	  EndIf

	  Local $rootdir=ETRootDirOpen($BindId,0)
	  Local $text=StringTrimLeft (  $filename, 2 )
	  Local $text1=StringLeft($text, 4)
	  $dir1=JCDirOpen(Dec ($text1), $rootdir)
	  if $dir1=false Then
		 $dir1= ETDirCreate(Dec ($text1), $rootdir)
	  EndIf

	  if StringLen($text) >12 Then
		 $text=StringTrimLeft (  $text, 5 )
		 $text1=StringLeft($text, 4)
		 $dir2=JCDirOpen(Dec ($text1), $dir1)
		 if $dir2=false Then
			$dir2= ETDirCreate(Dec ($text1), $dir1)
		 EndIf

		 $text=StringTrimLeft (  $text, 5 )
		 Local $DstFile=JCFileCreate(Dec ($text),$Dir2,$fileSize,$isPrivate)
		 JCFileClose($DstFile)
	  Else
		 $text=StringTrimLeft (  $text, 5 )
		 Local $DstFile=JCFileCreate(Dec ($text),$Dir1,$fileSize,$isPrivate)
		 JCFileClose($DstFile)
	  EndIf
	  ETTokenUnbind($BindId)
	  GUISetState(@SW_HIDE, $CreateFileWin)
	  GUISetState(@SW_SHOW, $hParentWin)
	  _GUICtrlTreeView_DeleteAll ($treeview)
	  List()
EndFunc

;сохранение изменённого файла на токене
Func SaveFile()
	  If $Pin=0   Then
		 MsgBox(0x10,$Appname,'Для сохранения файла сначала введите пин код' )
	  Else
		 Local $filebody=GUICtrlRead($Edit1)
		 Local $hItem = _GUICtrlTreeView_GetSelection($treeview)
		 Local $FileEd = _GUICtrlTreeView_GetText($treeview, $hItem)
		 $FileEd=StringTrimLeft (  $FileEd, 6 )
		 Local $p=0
		 $p=StringInStr ($FileEd,"p:")
		 $FileEd=StringMid ( $FileEd, 1, $p-2 )
		 Local $DirID=_GUICtrlTreeView_GetParentHandle($treeview, $hItem)
		 Local $Dir= _GUICtrlTreeView_GetText($treeview, $DirID)
		 $Dir=StringTrimLeft (  $Dir, 5 )
		 $BindId=ETTokenBind($Reader[0])
		 $Result=JCTokenLock($BindId)
		 if $AppletID<>0 Then
			JCSelectApplet($BindId,$AppletID)
		 EndIf

		 If $Pin <> 0   Then
			$Result=JCTokenLogin($BindId,$Pin)
			If $Result=False   Then
			   $Result=JCTokenPinAttemptsGet($BindId)
			   MsgBox(0x10,$Appname,'Неверный PIN код'&@CRLF&'Количество попыток ввода PIN кода: '&$Result)
			EndIf
		 EndIf

		 Local $HDir=GetDir(ETRootDirOpen($BindId,0), $Dir)
		 Local $File=JCFileOpen(Dec ($FileEd),$HDir)
		 Local $Data =Binary('0x' & $filebody)
		 JCFileWrite($File, $Data)
		 JCFileClose($File)
		 ETDirClose($HDir)

		 ETTokenUnbind($BindId)
		 GUISetState(@SW_HIDE, $hChildWin)
		 _GUICtrlTreeView_DeleteAll ($treeview)
         List()

	  EndIf
EndFunc

;сохранение открытого на токене файла на компьютер
Func SaveFileAs()
	  Local  $varFile = 0
	  $varFile = FileSaveDialog( "Сохранить файл", @MyDocumentsDir & "\", "Бинарные файлы (*.bin)", 16,'',$hParentWin)

	  If StringLen($varFile) > 3 Then
		 Local  $filedest
		 $filedest = FileOpen($varFile, 17)
		 ; Check if file open
		 If $filedest = -1 Then
			MsgBox(0, "Error", "Unable to open file.")
			Exit
		 EndIf

		 FileWrite($filedest, $text)
		 FileClose($filedest)
	  EndIf

EndFunc

;Обработка команд меню окна просмотра и редактирования файла
Func WM_COMMAND($hWnd, $iMsg, $wParam, $lParam)
    #forceref $hWnd, $iMsg, $lParam

    Switch $wParam
	  Case $Save
            SaveFile()
	  Case $idSave
            SaveFileAs()
    EndSwitch
EndFunc   ;==>WM_COMMAND


;инициализация графического интерфейса
Func GUIInit()
	  $hParentWin=	GUICreate($Appname, 560, 400)
	  GUISetOnEvent($GUI_EVENT_CLOSE,'onClose')

	  ;Создание главного окна
	  $treeview = GUICtrlCreateTreeView(6, 6, 400, 300, BitOR($TVS_HASBUTTONS, $TVS_HASLINES, $TVS_LINESATROOT, $TVS_DISABLEDRAGDROP, $TVS_SHOWSELALWAYS), $WS_EX_CLIENTEDGE)
					 $Output = GUICtrlCreateEdit("" , 6, 320, 400, 70, $ES_AUTOVSCROLL + $WS_VSCROLL + $ES_NOHIDESEL + $ES_WANTRETURN)
					 $pinbutton = GUICtrlCreateButton("&Ввести PIN код", 430, 20, 100, 50)
					 $filebutton = GUICtrlCreateButton("&Создать", 430, 80, 100, 50)
					 $deletebutton = GUICtrlCreateButton("&Удалить", 430, 140, 100, 50)

	  ;Создание окна ввода пин кода
	  $hPinWin = GUICreate('Введите PIN код', 200, 200, -1, -1, $WS_SYSMENU, -1, $hParentWin)
                    $PinEdit = GUICtrlCreateInput ("" , 50, 40, 100, 25, $ES_PASSWORD + $ES_NOHIDESEL + $ES_WANTRETURN)
                    $pinokbutton = GUICtrlCreateButton("&OK", 20, 100, 60, 40)
                    $pincancelbutton = GUICtrlCreateButton("&Отмена", 110, 100, 60, 40)

	  ;Окно создания файла
	  $CreateFileWin = GUICreate('Создание папок и файла', 340, 350, -1, -1, $WS_SYSMENU, -1, $hParentWin)
                    $FileEdit = GUICtrlCreateInput ("" , 50, 70, 230, 25)
                    $fileokbutton= GUICtrlCreateButton("&OK", 70, 240, 60, 40)
                    $filecancelbutton = GUICtrlCreateButton("&Отмена", 210, 240, 60, 40)
                    $publicbutton= _GUICtrlButton_Create($CreateFileWin, "Public", 100, 120, 50, 30,  $BS_AUTORADIOBUTTON, 0)
                    $privatebutton=_GUICtrlButton_Create($CreateFileWin, "Private", 160, 120, 50, 30,  $BS_AUTORADIOBUTTON, 0)
                    _GUICtrlButton_SetCheck($publicbutton,  $BST_CHECKED)
                    Local $label=GUICtrlCreateLabel('Введите имя папок и файла в hex формате 1001 ', 70, 20, 170, 40, $SS_CENTER)
                    $sizefile = GUICtrlCreateInput ("10" , 220, 175, 50, 20)
                    Local $label1=GUICtrlCreateLabel('Введите размер файла в байтах', 20, 180, 200, 60, $SS_CENTER)

	  ;Окно редактирования файла
	  $hChildWin = GUICreate($sItemText, 300, 230, -1, -1, $WS_SYSMENU, -1, $hParentWin)
				    $Edit1 = GUICtrlCreateEdit("", 10, 10, 240, 160, $ES_AUTOVSCROLL + $WS_VSCROLL + $ES_NOHIDESEL + $ES_WANTRETURN)

	  ; Создаёт меню "Файл" в окне редактирования файла
	  $hFile = _GUICtrlMenu_CreateMenu ()
	  _GUICtrlMenu_InsertMenuItem ($hFile, 0, 'Сохранить как...', $idSave)
	  _GUICtrlMenu_InsertMenuItem ($hFile, 1, 'Сохранить изменения', $Save)
	  $hMain = _GUICtrlMenu_CreateMenu ()
	  _GUICtrlMenu_InsertMenuItem ($hMain, 0, 'Файл', 0, $hFile)
	  _GUICtrlMenu_SetMenu ($hChildWin, $hMain)

	  ;Определение событий
	  GUICtrlSetOnEvent($filebutton,'onFileCreate')
	  GUICtrlSetOnEvent($deletebutton,'Delete')
	  GUICtrlSetOnEvent($pinbutton,'onPin')
	  GUICtrlSetOnEvent($pinokbutton,'onPinOK')
	  GUICtrlSetOnEvent($pincancelbutton,'onPinCancel')
	  GUICtrlSetOnEvent($fileokbutton,'onFileOK')
	  GUICtrlSetOnEvent($filecancelbutton,'onFileCancel')
	  GUISetOnEvent($GUI_EVENT_CLOSE,'onClose')

	  GUISetState(@SW_SHOW, $hParentWin)
	  GUIRegisterMsg(0x0111, "WM_COMMAND")
EndFunc

;запуск основных функций приложения
GUIInit()
List()

;функция обработки двойного щелчка мышью на дереве файлов и директорий
GUIRegisterMsg($WM_NOTIFY, "MY_WM_NOTIFY")
Global $iDoubleClick = 0

Func MY_WM_NOTIFY($hWnd, $Msg, $wParam, $lParam)

    Local $tagNMHDR, $vEvent

    Switch $wParam
        Case $treeview
            $tagNMHDR = DllStructCreate("int;int;int", $lParam)
            If @error Then Return
            $vEvent = DllStructGetData($tagNMHDR, 3)
            If $vEvent = $NM_DBLCLK Then
                $iDoubleClick = 1
            EndIf
    EndSwitch
    $tagNMHDR = 0

EndFunc  ;==>MY_WM_NOTIFY

;функция поиска директории, в которой кликнули по файлу
Func GetDir( $Id,$Dir_Id)
	  Local $DirId=0
	  Local $DirResult=0
	  Local $EnumId=ETDirEnumOpen($Id)

	  While 1
		Local $dir=ETDirEnumNext($EnumId)
		If @error Then ExitLoop
			$DirId=ETDirOpen($dir,$Id)
			if hex($dir,4)=$Dir_Id Then
			   $DirResult=$DirId
			   ExitLoop
			EndIf
			$DirResult=GetDir( $DirId, $Dir_Id)
			ETDirClose($DirId)
	  WEnd
	  ETDirEnumClose($EnumId)
	  Return  $DirResult
EndFunc

;функция открытия файла на токене и вывода его содержимого в дочернее окно
Func ListFile($file, $Dir_Id)
	  $BindId=ETTokenBind($Reader[0])
	  $Result=JCTokenLock($BindId)

	  if $AppletID<>0 Then
		 JCSelectApplet($BindId,$AppletID)
	  EndIf
	  If $Pin <> 0   Then
		 $Result=JCTokenLogin($BindId,$Pin)
		 If $Result=False   Then
			$Result=JCTokenPinAttemptsGet($BindId)
			MsgBox(0x10,$Appname,'Неверный PIN код'&@CRLF&'Количество попыток ввода PIN кода: '&$Result )
		 EndIf
	  EndIf

	  if StringLen($Dir_Id)>10 Then
		 $HDir=ETRootDirOpen($BindId,0)
	  Else
		 Local $HDir=GetDir(ETRootDirOpen($BindId,0), $Dir_Id)
	  EndIf

	  $SrcSubId=JCFileOpen(Dec ($file), $HDir)
	  $text=JCFileRead($SrcSubId)
	  GUICtrlSetData($Edit1, hex($text))
	  JCFileClose($SrcSubId)
	  ETDirClose($HDir)
	  ETTokenUnbind($BindId)
EndFunc

;обработка двойного щелчка мышью и получения имени файла на токене
   While 1

      if $iDoubleClick Then
		 Local $hItem = _GUICtrlTreeView_GetSelection($treeview)
		 if _GUICtrlTreeView_GetChildren($treeview, $hItem)=False Then
			Local $hItem = _GUICtrlTreeView_GetSelection($treeview)
			$sItemText = _GUICtrlTreeView_GetText($treeview, $hItem)
			if StringInStr ($sItemText,"Dir")=0 Then
			   Local $text1=0
			   $text1=StringTrimLeft (  $sItemText, 6 )
			   Local $p=0
			   $p=StringInStr ($text1,"p:")
			   $sItemText=0
			   $sItemText=StringMid ( $text1, 1, $p-2 )
			   GUISetState(@SW_SHOW, $hChildWin)
			   GUISetOnEvent($GUI_EVENT_CLOSE,'onClose')
			   Local $DirID=_GUICtrlTreeView_GetParentHandle($treeview, $hItem)
			   Local $Dir= _GUICtrlTreeView_GetText($treeview, $DirID)
			   $text1=StringTrimLeft (  $Dir, 5 )
			   $Dir=$text1
			   ListFile($sItemText, $Dir)
			EndIf
		 EndIf
		 $iDoubleClick = 0
     EndIf

   WEnd




Источники информации

eToken Developer’s Guide Version 3.50 (декабрь 2003)

Комментарии (3)


  1. DuH_Khv
    25.02.2019 17:07

    Подскажите пожалуйста, каким конкретно образом данный скрипт помогает вам в решении поставленной задачи?


    1. DWarlock Автор
      26.02.2019 03:03

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


      1. DuH_Khv
        26.02.2019 10:53

        Я так и подумал, но решил сначала уточнить.
        Поделюсь с вами способом которым пользуюсь самостоятельно — возможно он вам тоже пригодится.
        Существует такая утилита ImDisk Virtual Driver (распространяется под GNU GPL, BSD). В функционале этой софтиры есть возможность монтирования любого файла в качестве диска. В том числе представлять его в качестве Сьемного носителя (Removable Media).

        Порядок действия такой:
        1) Создаем и Монтируем пустую «Виртуальную флешку», проставив при этом галку «Removable Media». Размер обычно ставлю 5 мегабайт. По указанному пути в драйвере создает обычный файлик в который осуществляется запись.
        2) Форматируем появившуюся в системе «Виртуальную флешку» стандартными средствами Windows в FAT.
        3) При помощи оснастки КриптоПро выполняем обычную функцию «Скопировать» (Сервис — Скопировать). В качестве исходного контейнера указываем необходимый на токене — в качестве получателя указываем «Виртуальную флешку». КриптоПро воспринимает такой контейнер вполне адекватно как обычную флешку и создает копию ключа.
        4) Извлекаем виртуальный контейнер через оснастку программы ImDisk Virtual Driver.
        5) Переносим созданный файлик-виртуальную-флешку на другой компьютер.
        6) Монтируем «Виртуальную флешку» через ImDisk Virtual Driver.
        7) Производим обратное копирование контейнера закрытого ключа стандартными средствами Крипто-Про.