Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

Опять приведение PChar к String [D5]


Страницы:   1 2

Ega23 ©   (2005-02-07 11:30:00) 

Есть DLL, в ней по данному Alias'у происходит коннект к БД, возвращает password для sa:

function GetKedrPwd(var pwd:String; var ErrMess:String;
                   const AliasName:String='KEDR' ):Boolean;

type
TGetNewParamFunction=function(AliasName:PChar):PChar; StdCall;
var
ss:string;
GetNewParamFunction:TGetNewParamFunction;
LibHandle:THandle;
aAliasName:PChar;
p:Pchar;
begin
Result:=False;
ErrMess:='';
@GetNewParamFunction:=nil;
pwd:='';
try
 LibHandle:=LoadLibrary('kedrlcd.dll');
 @GetNewParamFunction:=GetProcAddress(LibHandle, 'GetNewParam');
 if @GetNewParamFunction<>nil then
  begin
   aAliasName:=StrAlloc(Length(AliasName)+1);
   aAliasName:=StrPCopy(aAliasName, AliasName);
   p:=GetNewParamFunction(aAliasName);
    ss:=String(p);
   StrDispose(aAliasName);
  end;

 FreeLibrary(LibHandle);
except on E:Exception do
 begin
  ErrMess:=E.Message;
  Exit;
 end;
end;
Result:=True;
pwd:=ss;
end;


Внутри библиотеки всё отрабатывается корректно, проверял.
На ss:=String(p); происходит вылет по AV.

В чём может быть причина?


Владислав   (2005-02-07 15:28:00) [1]

> Anatoly Podgoretsky ©   (07.02.05 14:52) [25]

Это знают все до начальника подразделения информационных технологий (выше только ген. директор). Тем не менее живут с этим и по сей день.
К слову сказать, это авторизация в большом финансовом (стороннем) программном продукте. SCALA называется. Как они на это пошли?..


Anatoly Podgoretsky   (2005-02-07 14:52:00) [2]

При такой методе, враги сожгут родную хату.


Владислав   (2005-02-07 13:32:00) [3]

На прежней работе авторизация к базе была построена на подобной криворукой системе. И там тоже ничего изменить было нельзя :(


Anatoly Podgoretsky   (2005-02-07 13:17:00) [4]

Забыл про приведение к PChar
GetPwd(PChar(Pwd), LG, 'AliasName');


Ega23   (2005-02-07 13:12:00) [5]

2 Anatoly Podgoretsky ©   (07.02.05 13:02) [20]
По поводу памяти уже много описали, правила простые выделять и освобождать должен тот кто требует. Ограничиться только простыми типами, типа PChar, в функцию передавать размер выделенной памяти -1. Если размера недостаточно то возвращать ошибку, в качестве ошибки использовать требуемый размер для результата, в случае успешного исполнения возвращать 0. Данный механизм хорошо себя зарекомендовал в АПИ, где он широко использувется.

Так. Насколько я понял, функция в DLL тогда приобретает следующий вид:

function GetNewParam(aAliasName:PChar; aPass:PChar; BuffLength:Cardinal):Cardinal; StdCall;


aPass:PChar  -  указатель на область памяти, выделенной в клиенте
BuffLength - размер выделенной памяти.

Тогда задача на выделение и освобождение памяти ложится на клиента...

Идея мне нравится!

А насчет прав и хранения паролей серьезно подумай еще раз. Система становится небезопасной.

Боюсь, что в данной ситуации я ничего не могу сделать - не я это решаю...  :-(


Anatoly Podgoretsky   (2005-02-07 13:10:00) [6]

Пример функции

function GetPwd(Pwd: PChar; BufLen: Integer; AliasName: PChar): Integer;

Вызов может выглядеть так

SetLength(Pwd, 16);
LG := GetPwd(Pwd, Length(Pwd), 'AliasName');
if LG = 0 then Pwd := PChar(Pwd) else Error;

Нужный размер и пароль можно еще получить так
LG := GetPwd(Pwd, 0, 'AliasName');
SetLength(Pwd, LG);
GetPwd(Pwd, LG, 'AliasName');
Pwd := PChar(Pwd);


Anatoly Podgoretsky   (2005-02-07 13:02:00) [7]

Адресные пространства у DLL и клиента - одинаковые!

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

По поводу памяти уже много описали, правила простые выделять и освобождать должен тот кто требует. Ограничиться только простыми типами, типа PChar, в функцию передавать размер выделенной памяти -1. Если размера недостаточно то возвращать ошибку, в качестве ошибки использовать требуемый размер для результата, в случае успешного исполнения возвращать 0. Данный механизм хорошо себя зарекомендовал в АПИ, где он широко использувется.

А насчет прав и хранения паролей серьезно подумай еще раз. Система становится небезопасной.


Игорь Шевченко   (2005-02-07 12:51:00) [8]

Олег, не извращайся, а передай вторым параметром буфер под нужную строку. Как делают все API-шные функции. И не нужно никаких CoTaskMem...

С уважением,


Ega23   (2005-02-07 12:50:00) [9]

2 Jay1982 ©   (07.02.05 12:46) [16]

Теоретически - можно. Практически - не все клиенты на Delphi пишутся...


Ega23   (2005-02-07 12:50:00) [10]

2 Jay1982 ©   (07.02.05 12:46) [16]

Теоретически - можно. Практически - не все клиенты на Delphi пишутся...


Jay1982   (2005-02-07 12:46:00) [11]

Можно изпользовать ShortString и никаких тебе указателей и неосвобождённой памяти


Ega23   (2005-02-07 12:45:00) [12]

2 Владислав ©   (07.02.05 12:39) [13]

CoTaskMemAlloc - это получается, что кроме указателя мне ещё и длину в байтах возвращать надо?


Ega23   (2005-02-07 12:41:00) [13]

CoTaskMemAlloc/CoTaskMemFree

Сейчас попробую...


Владислав   (2005-02-07 12:39:00) [14]

CoTaskMemAlloc/CoTaskMemFree
Спасет отца русской демократии ;)


Ega23   (2005-02-07 12:36:00) [15]

Тебе же уже отвечали, что выделять и освобождать память нужно в одном и том же месте, если использовать менеджер памяти borland'а.


Это я понимаю. фишка в том, что нужно по-возможности обойтись ОДНОЙ(!) экпортной функцией в DLL.

Есть, правда, вариант - освобождать память по данному указателю в секции finalization внутри DLL.
Но тут у меня тоже вопросы - с ней (секцией) никогда не работал, поэтому не знаю, насколько это корректно будет...


Владислав   (2005-02-07 12:32:00) [16]

Тебе же уже отвечали, что выделять и освобождать память нужно в одном и том же месте, если использовать менеджер памяти borland'а.

Как пример:

function GetNewParam(aAliasName:PChar; var Pass: PChar; var PassLen: DWORD):PChar; StdCall;
begin
...
 GetMem(Pass, Length(ResultStr));
 Move(Pointer(ResultStr)^, Pass^, Length(ResultStr));
 PassLen := Length(ResultStr);
 Result := Pass;
...
end;

procedure FreePass(Pass: PChar);
begin
 FreeMem(Pass);
end;


Есть и другие варианты...


SVM (Perm)   (2005-02-07 12:30:00) [17]

Используй, например, CoTaskMemAlloc/CoTaskMemFree или SysAllocString/SysFreeString или GlobalAlloc/GlobalFree...


Ega23   (2005-02-07 12:26:00) [18]

2 Игорь Шевченко ©   (07.02.05 12:16) [7]

Игорь, если я тебя правильно понял, то внутри библтотеки надо выделить память под Result, записать туда полученный пароль, после чего вернуть указатель на эту выделенную память.
Теперь вопрос: а где мне потом эту память высвобождать? На клиенте? Но так, вроде, нельзя делать, т.к. адресные пространства у DLL и клиента - разные...


Ega23   (2005-02-07 12:23:00) [19]

2 Игорь Шевченко ©   (07.02.05 12:16) [7]

Да я вот тоже "нутром" чую, что всё неправильно делаю.

Хорошо, попытаюсь описать задачу:
Есть БД под MS SQL 2000. На базу существует 2 логина: первый входит в роль SA, второй имеет права на чтение одной единственной таблицы. В этой таблице лежит закодированный пароль для первого логина.

Действия клиента: коннект по второму логину (пароля на него нет), полуение пароля, ре-коннект под первым логином с полученным pwd.

Задача: написать DLL, которая по некоему алиасу соединяется с базой, получает пароль и возвращает его "наверх".

По-идее, это должна быть DLL с одной единственной функцией.

Вот как можно "изгольнуться" и получить этот чёртов пароль?


Игорь Шевченко   (2005-02-07 12:16:00) [20]

Нельзя возвращать указатель на локальную в функции строку. Она же уничтожается.


Страницы:   1 2

Наверх

Титульная страница Поиск, карта сайта Написать письмо