Помогите адаптировать API функцию

Вопросы программирования и использования среды Lazarus.

Модератор: Модераторы

Помогите адаптировать API функцию

Сообщение gvido » 18.02.2014 19:33:53

Код: Выделить всё
T16bit WINAPI GetCKeysF (char *afile_name,P16bit ab,P16bit *us_list,char *ser);


Пример использования:
Код: Выделить всё
char ser[7];
error_code = GetCKeysF("C:\\TEST.TST", ab, us_list, ser);
for(i = 0; i < *ab; i++) printf("%u\n", *us_list[i]);
FreeMemory(us_list);


с ser, вроде все, понятно -
Код: Выделить всё
ser: array[0..6] of char;


afile_name - строка полное имя файла, то есть:
Код: Выделить всё
afile_name: ^char; // или PChar

ab - указатель на Word, то есть
Код: Выделить всё
ab: ^Word; //или PWord

us_list - указатель на указатель получается???

Что из себя представляет параметр us_list???

Need help!!! Помогите, а???
gvido
постоялец
 
Сообщения: 188
Зарегистрирован: 28.03.2012 11:35:31

Re: Помогите адаптировать API функцию

Сообщение Vadim » 19.02.2014 11:08:01

gvido
Если Вы уже точно знаете, что:
gvido писал(а):ab - указатель на Word

то отчего же другой параметр с точно таким же типом не можете опознать?

Вообще-то, двойной указатель в Си - это массив, т.е. список указателей. В вашем случае, первый указатель - это указатель на список из указателей.

Пытаетесь Вербой овладеть? :)
Vadim
долгожитель
 
Сообщения: 4112
Зарегистрирован: 05.10.2006 08:52:59
Откуда: Красноярск

Re: Помогите адаптировать API функцию

Сообщение wavebvg » 19.02.2014 11:36:20

gvido писал(а):Что из себя представляет параметр us_list???

Он представляет из себя PPWord: такой фокус используется в низкоуровневых "высокоуровневых" языках, чтобы передать массив значений в качестве аргумента.
Для начала стоит попробовать использовать массив
Код: Выделить всё
array of PWord
в качестве аргумента - есть вероятность, что компилятор справится и вы получите то, что нужно почти без танцев.
Если нет - придётся либо работать с указателями напрямую, либо завернуть всё это дело в функцию, возвращающую массив PWord-ов
PS1: С массивом работать куда проще - прокатит - лучше на нем остановиться
PS2: В примере
Код: Выделить всё
FreeMemory(ab);
случаем не забыли?
PS3: Про диррективы компилятору помните, иначе он C-ые параметры никак не распарсит
PS4: Стоит тему перенести в FPC, потому что LAZARUS - IDE и частный случай реализации VCL с использованием FPC
PS5: На FPC тоже придётся чистить память от сишной шелухи
wavebvg
постоялец
 
Сообщения: 355
Зарегистрирован: 28.02.2008 04:57:35

Re: Помогите адаптировать API функцию

Сообщение gvido » 19.02.2014 17:28:09

:)
Пытаетесь Вербой овладеть?
- точно , пытаюсь. :)
С Указателями вообще морока, для меня.
Как то не было нужды с ними работать, не стал вникать. А тут, смотрю, как баран на новые ворота, и не могу в голове уложить - что и к чему. :(
С одиночным указателем все вроде бы понятно, поправьте , если не прав:
указатель на переменную либо тип данных - это тоже переменная, но хранить она адрес.
Что тогда хранит переменная указатель на указатель типа данных?

Вообще-то, двойной указатель в Си - это массив, т.е. список указателей. В вашем случае, первый указатель - это указатель на список из указателей.

как выглядит аналогичная конструкция в паскале?

Ок вот как в оригинале выглядит функция от разработчика с описанием:
Получение списка получателей зашифрованного файла
Для получения списка получателей (абонентов, которые могут расшифровать данный закрытый файл), служит функция GetCryptKeysF(wbotho). При формировании списка получателей зашифрованного файла расшифрование и проверка правильности этого файла не производятся.
Функция GetCryptKeysF имеет прототип:
Код: Выделить всё
T16bit WINAPI GetCryptKeysF (char *file_name,
P16bit abonents,
P16bit *user_list,
char *ser);

Функция имеет параметры:
(i) file_name — указатель на строку полного пути к зашифрованному файлу;
(o) abonents — указатель на переменную, в которую возвращается число получателей;
(o) user_list — список получателей файла file_name, который имеет такую же структуру, как и в функции EnCryptFile, т. е. представлен строкой элементов, имеющих тип unsigned short, и оканчивающийся нулем (0).
Внимание. Память под этот массив отводится внутри функции GetCryptKeysF и должна быть освобождена функцией FreeMemory (см. п. 8.12), как только user_list обработан.
(o) ser — указатель на строку, куда возвращается номер серии (7 байт) ключей отправителей.
Пример использования функции GetCryptKeysF:
Код: Выделить всё
char ser[7];
error_code = GetCryptKeysF("C:\\TEST.TST", abonents, user_list, ser);
for(i = 0; i < *abonents; i++) printf("%u\n", *user_list[i]);
FreeMemory(user_list);


Вот так в wboth.pas который нарыл в инете:
Код: Выделить всё
function GetCryptKeysF(file_name:LPSTR; abonents:PWORD;user_list:PWORD;ser:LPSTR):WORD;
  stdcall; external cDLLFn name 'GetCryptKeysF';

как правильно вызвать данную функцию?
gvido
постоялец
 
Сообщения: 188
Зарегистрирован: 28.03.2012 11:35:31

Re: Помогите адаптировать API функцию

Сообщение wavebvg » 19.02.2014 17:53:53

Попробуй вначале вот таким образом решить вопрос:
Код: Выделить всё
function GetCryptKeysF(file_name:LPSTR; abonents:PWORD;user_list:array of const;ser:LPSTR):WORD;
  stdcall; external cDLLFn name 'GetCryptKeysF';


Если не получится, тогда делать придётся так:
Код: Выделить всё
function GetCryptKeysF(file_name: PChar; abonents: PWORD; user_list: PPWORD;ser:PChar):WORD; stdcall; external cDLLFn name 'GetCryptKeysF';


Код: Выделить всё
const NO_ERROR = 0;
var Values: PPWord; Value: PWord;
...
if GetCryptKeysF(file_name, abonents, user_list, ser) = NO_ERROR then
begin
  Values := user_list;
  for i := 0 to abonents^ - 1 do
  begin
     Value := ^Values;
     WriteLn(Value^);
     Inc(Values);
  end;
end;
...


Код на скорую руку, только чтобы показать принцип
Память толже потом нужно очистить
wavebvg
постоялец
 
Сообщения: 355
Зарегистрирован: 28.02.2008 04:57:35

Re: Помогите адаптировать API функцию

Сообщение gvido » 19.02.2014 18:23:54

Я не могу объявить переменную с типом array of const в первом случае.
Второй вариант пробовал самостоятельно. :(
всегда функция возвращает 8 то есть "ошибка инициализации"
возможно я неправильно объявляю переменную user_list и abonents?

Исходя из описания прототипа функции переменные abonents, user-list и ser заполняются в теле функции.
Наверно по этому в функцию передаются указатели.

повнимательнее почитал доку и думаю нужно
переменные объявить так:
abonents: Word;
user_list: PWord;
ser: array[0..6] of char;
и вызвать функцию так:
err_code:=GetCryptKeysF('c:\test.txt',@abonents,@user_list,ser);
В функцию ведь нужно передать адреса переменных в случае с abonents и user_list.
gvido
постоялец
 
Сообщения: 188
Зарегистрирован: 28.03.2012 11:35:31

Re: Помогите адаптировать API функцию

Сообщение Vadim » 20.02.2014 05:01:27

Можно попробовать что-то типа:
Код: Выделить всё
Var
  file_name: PChar;
  abonents: PWord;
  user_list: PPWord;
  user: PWord;
  ser: PShar;
  i: Integer;

Begin
...
  GetCryptKeysF(file_name, abonents, user_list, ser);
  For i:=0 To abonements^-1 Do
  Begin
    user:=user_list^;
    WriteLn(user^);
    Inc(user_list);
  End;
   
End;
Vadim
долгожитель
 
Сообщения: 4112
Зарегистрирован: 05.10.2006 08:52:59
Откуда: Красноярск

Re: Помогите адаптировать API функцию

Сообщение wavebvg » 20.02.2014 09:56:14

gvido писал(а):В функцию ведь нужно передать адреса переменных в случае с abonents и user_list.


Нет, как раз функция должна вернуть указатели на данные, которые (указатели) нужно потом освободить (или как это по русски: "освободить память по указателям")

Если результат функции "ошибка инициализации", тогда есть ненулевая вероятность, что библиотека требует вызова функции для инициализации. Т.е. до GetCryptKeysF нужно вызвать что-то вроде InitCrypt или подобное...
wavebvg
постоялец
 
Сообщения: 355
Зарегистрирован: 28.02.2008 04:57:35

Re: Помогите адаптировать API функцию

Сообщение Vadim » 20.02.2014 11:36:34

gvido
wavebvg писал(а):. Т.е. до GetCryptKeysF нужно вызвать что-то вроде InitCrypt или подобное...

А действительно, мысль здравая...
Вы в начале программы функцию CryptoInit() вызываете? Или, если речь идёт о подписи - SignInit()?
Vadim
долгожитель
 
Сообщения: 4112
Зарегистрирован: 05.10.2006 08:52:59
Откуда: Красноярск

Re: Помогите адаптировать API функцию

Сообщение gvido » 20.02.2014 12:58:41

InitCrypt нужна для инициализации драйвера и загрузки ключей в нулевой слот. По запуску asrkeyw.exe проверил что драйвер инициализирован и ключи подгружены. Тем более вызов этой
Код: Выделить всё
function GetFileSenderID(path,sender_id:LPSTR):WORD;
  stdcall; external cDLLFn name 'GetFileSenderID';
функции проходит на ура!!!
Код: Выделить всё
procedure TForm1.Button5Click(Sender: TObject);
var
   my_ID: array[0..10] of char;
   err_code: integer;
begin
      err_code:=GetFileSenderID('c:\ZNO14030821_780520140218_002186.VRB',my_ID);
      ShowMessage(Inttostr(err_code)+#13#10+my_ID);
end;

В окно сообщения выводит
0
xxxxsssssss
то есть все таки что-то не так у меня с вызовом функции

Добавлено спустя 1 час 20 минут 21 секунду:
Прислали кусок рабочего С кода:
Код: Выделить всё
/*** GET USERS_LIST OF ENCRYPTED FILE ***/
        case    'g':
        case    'G':
                if( (argc !=3) || (!CRYPT) )
                        {
                        Usage();
                        return;
                        }
                {
                unsigned short abonents,i;
                unsigned short *user_list;
                char          ser[]={"\0\0\0\0\0\0\0"};

                err_code = pCryptoInit("c:\\","c:\\");
                if(err_code)
                        {
                        printf("CryptoInit error : %d\n",err_code);
                        return;
                        }
                err_code = pGetCryptKeysF(in_file,&abonents,&user_list,ser);
                if(err_code)
                        {
                        printf("DeCryptFile error : %d\n",err_code);
                        return;
                        }
                pCryptoDone();

                printf("File %s is encrypted for this abonents :\n",in_file);
                for(i=0;i<abonents;i++)
                printf("ID%d - %d\n",i+1,user_list[i]);

        };
        break;


Уверили что код рабочий. :(
Из него видно что CryptoInit вызывается предварительно, для загрузки ключа
gvido
постоялец
 
Сообщения: 188
Зарегистрирован: 28.03.2012 11:35:31

Re: Помогите адаптировать API функцию

Сообщение wavebvg » 20.02.2014 15:02:55

Значит нужно пробовать проинициализировать:
Код: Выделить всё
const NO_ERROR = 0;
var Values: PPWord; Value: PWord;
...
if CryptoInit('c:\','c:\') = NO_ERROR then
begin
  if GetCryptKeysF(file_name, abonents, user_list, ser) = NO_ERROR then
  begin
    ... // Все хорошо
  end else
  begin
    ... // Код ошибки
  end;
  ***CryptoDeinit***
end;
wavebvg
постоялец
 
Сообщения: 355
Зарегистрирован: 28.02.2008 04:57:35

Re: Помогите адаптировать API функцию

Сообщение gvido » 20.02.2014 15:28:50

wavebvg писал(а):const NO_ERROR = 0;
var Values: PPWord; Value: PWord;
...
if CryptoInit('c:','c:') = NO_ERROR then
begin
  if GetCryptKeysF(file_name, abonents, user_list, ser) = NO_ERROR then
  begin
    ... // Все хорошо
  end else
  begin
    ... // Код ошибки
  end;
  ***CryptoDeinit***
end;

проблема в передаче переменной user_list
проверил отладчиком. переменную abonents объявил как word и передал @abonents
По выходу из функции переменная получала значение 1 как и должно быть. получатель файла один в случае с этим конкретным файлом.
переменную user_list как только не объявлял.
Array of pword и как PPWORD, как a: array of word; user_list:^a;
результат всегда один, либо пустой массив, или c переменной не связана память.

Добавлено спустя 1 час 25 минут 22 секунды:
Может проблема в том что я не использую дерективы?
попробовал посмотреть что будет:
Код: Выделить всё
var
   Values:PPWORD;
   Value:PWORD;
   user: word;
.....
   user:=2554;
   value:=@user;
   Values:=@value;
   showmessage(inttostr(user)+#13#10+inttostr(Integer(value))+#13#10+inttostr(Integer(values))+#13#10+inttostr(Integer(values)-integer(value)));

вывод:
2554
22868956
22868964
8
получается что значение указателя на указатель на тип word это адрес со смещением на 8, видимо, бит.
Что-то херня какая то получается.....

Добавлено спустя 4 минуты 35 секунд:
Я видимо плохо объясняю чего мне нужно....
Я хочу понять, какую структуру я должен передать в качестве параметра user_list функции. Знание чего я туда передаю даст понимание, что я получу обратно и как этим безобразием работать.
К тому же отладчик в лазарусе не все понимает, к сожалению....

Добавлено спустя 50 минут 10 секунд:
Код: Выделить всё
var
   Values:PPWORD;
   Value:PWORD;
   user,u: word;
.....
   user:=2554;
   value:=@user;
   Values:=@value;
          u:=Values^[0]; //вернет 2554


Добавлено спустя 18 часов 13 минут 10 секунд:
Парни, проблему решил!!!!! Спасибо всем кто помогал!!!! вот работающий код.
Код: Выделить всё
procedure TForm1.Button6Click(Sender: TObject);
type
     auser_list= array[0..0] of word;
var
   user_list:^auser_list;
   ser: array[0..6] of char;
   abonents: word;
   err_code: integer;
   i: integer;
   str: string;

begin
     err_code:= CryptoInit(PChar(''),PChar('')); // в данном случае эта функция таки нужна. Возможно выделяется память под что-то...
     err_code:=GetCryptKeysF('c:\1\BOS1_RPO14030821_785020140219_000017.vrb',@abonents,@user_list,ser);
     //корректно заполнились все три переменные - abonents - получил количество получателей; user_list - получает массив получателей, размер массива соответствует значению переменной abonents; ser получает номер ключевой серии
     CryptoDone;
     //Showmessage(GetVerbaErrorStr(err_code));
     for i:=0 to abonents-1 do
     begin
        str:=str+inttostr(i)+' '+inttostr(user_list^[i])+' '+ser+#13#10;
     end;
     FreeMemory(user_list);
     label1.Caption:=str;
     label1.Width:=length(str);
   //  showmessage(str);
end;
gvido
постоялец
 
Сообщения: 188
Зарегистрирован: 28.03.2012 11:35:31


Вернуться в Lazarus

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 230

Рейтинг@Mail.ru