Форум: "Основная";
Текущий архив: 2005.02.20;
Скачать: [xml.tar.bz2];
ВнизОпять приведение PChar к String Найти похожие ветки
← →
Ega23 © (2005-02-07 11:30) [0]Есть 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 11:35) [1]SetString не проще ?
← →
Ega23 © (2005-02-07 11:48) [2]2 Игорь Шевченко © (07.02.05 11:35) [1]
Проблема в том, что я в отладчике значения P не вижу.... :-(
← →
Владислав © (2005-02-07 11:50) [3]Покажу функцию из DLL.
← →
Ega23 © (2005-02-07 12:04) [4]Функция из DLL:
function GetNewParam(aAliasName:PChar):PChar; StdCall;
function CodeIt(aStr,aKey:string):string;
begin
................
Result:=S;
end;
const
stdsql="select LimitNum from dbo.paramsglb";
xkey="836519";
var
DB:TDataBase;
Qu:TQuery;
ss:string;
begin
Result:="";
try
DB:=TDataBase.Create(nil);
try
With DB do
begin
AliasName := String(aAliasName);
DatabaseName := "BD0";
LoginPrompt:=False;
Params.Clear;
Params.Add("USER NAME=KEDR0");
Params.Add("SQLQRYMODE=SERVER");
Params.Add("PASSWORD=");
Connected:=True;
end; //With DB do
Qu:=TQuery.Create(nil);
try
With Qu do
begin
DatabaseName:=DB.DatabaseName;
RequestLive:=True;
SQL.Text:=stdsql;
Open;
if (Active) and (not IsEmpty) then
begin
ss:=Fields[0].AsString;
ss:=CodeIt(ss, xkey);
Result:=PChar(ss);
end;
end;
finally
Qu.Active:=False;
Qu.Free;
end;
finally
DB.Connected:=False;
DB.Free;
end;
except
end;
end;
//*************************************************************************************
exports
GetNewParam name "GetNewParam";
← →
Anatoly Podgoretsky © (2005-02-07 12:09) [5]Ega23 © (07.02.05 11:30)
приведение PChar к String не возможно, структура разная, возможно только преобразование из PChar в String.
Что такое Result:=S;
← →
Ega23 © (2005-02-07 12:15) [6]Что такое Result:=S;
Там кодирование-декодирование пароля происходит. S - внутренняя переменная функции function CodeIt(aStr,aKey:string):string;, раздел var и текст функции пропустил, экран засорять не стал.
← →
Игорь Шевченко © (2005-02-07 12:16) [7]Нельзя возвращать указатель на локальную в функции строку. Она же уничтожается.
← →
Ega23 © (2005-02-07 12:23) [8]2 Игорь Шевченко © (07.02.05 12:16) [7]
Да я вот тоже "нутром" чую, что всё неправильно делаю.
Хорошо, попытаюсь описать задачу:
Есть БД под MS SQL 2000. На базу существует 2 логина: первый входит в роль SA, второй имеет права на чтение одной единственной таблицы. В этой таблице лежит закодированный пароль для первого логина.
Действия клиента: коннект по второму логину (пароля на него нет), полуение пароля, ре-коннект под первым логином с полученным pwd.
Задача: написать DLL, которая по некоему алиасу соединяется с базой, получает пароль и возвращает его "наверх".
По-идее, это должна быть DLL с одной единственной функцией.
Вот как можно "изгольнуться" и получить этот чёртов пароль?
← →
Ega23 © (2005-02-07 12:26) [9]2 Игорь Шевченко © (07.02.05 12:16) [7]
Игорь, если я тебя правильно понял, то внутри библтотеки надо выделить память под Result, записать туда полученный пароль, после чего вернуть указатель на эту выделенную память.
Теперь вопрос: а где мне потом эту память высвобождать? На клиенте? Но так, вроде, нельзя делать, т.к. адресные пространства у DLL и клиента - разные...
← →
SVM (Perm) (2005-02-07 12:30) [10]Используй, например, CoTaskMemAlloc/CoTaskMemFree или SysAllocString/SysFreeString или GlobalAlloc/GlobalFree...
← →
Владислав © (2005-02-07 12:32) [11]Тебе же уже отвечали, что выделять и освобождать память нужно в одном и том же месте, если использовать менеджер памяти 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;
Есть и другие варианты...
← →
Ega23 © (2005-02-07 12:36) [12]Тебе же уже отвечали, что выделять и освобождать память нужно в одном и том же месте, если использовать менеджер памяти borland"а.
Это я понимаю. фишка в том, что нужно по-возможности обойтись ОДНОЙ(!) экпортной функцией в DLL.
Есть, правда, вариант - освобождать память по данному указателю в секции finalization внутри DLL.
Но тут у меня тоже вопросы - с ней (секцией) никогда не работал, поэтому не знаю, насколько это корректно будет...
← →
Владислав © (2005-02-07 12:39) [13]CoTaskMemAlloc/CoTaskMemFree
Спасет отца русской демократии ;)
← →
Ega23 © (2005-02-07 12:41) [14]CoTaskMemAlloc/CoTaskMemFree
Сейчас попробую...
← →
Ega23 © (2005-02-07 12:45) [15]2 Владислав © (07.02.05 12:39) [13]
CoTaskMemAlloc - это получается, что кроме указателя мне ещё и длину в байтах возвращать надо?
← →
Jay1982 © (2005-02-07 12:46) [16]Можно изпользовать ShortString и никаких тебе указателей и неосвобождённой памяти
← →
Ega23 © (2005-02-07 12:50) [17]2 Jay1982 © (07.02.05 12:46) [16]
Теоретически - можно. Практически - не все клиенты на Delphi пишутся...
← →
Ega23 © (2005-02-07 12:50) [18]2 Jay1982 © (07.02.05 12:46) [16]
Теоретически - можно. Практически - не все клиенты на Delphi пишутся...
← →
Игорь Шевченко © (2005-02-07 12:51) [19]Олег, не извращайся, а передай вторым параметром буфер под нужную строку. Как делают все API-шные функции. И не нужно никаких CoTaskMem...
С уважением,
← →
Anatoly Podgoretsky © (2005-02-07 13:02) [20]Адресные пространства у DLL и клиента - одинаковые!
Судя по скромному описанию задачи ты что то делаешь неправильно, не надо никого включать в роль SA, надо просто задуматься над правильной раздачей прав, чтобы клиент всегда работал под самим собой, а не под администратором. Как разграничить права только ты можешь решить.
По поводу памяти уже много описали, правила простые выделять и освобождать должен тот кто требует. Ограничиться только простыми типами, типа PChar, в функцию передавать размер выделенной памяти -1. Если размера недостаточно то возвращать ошибку, в качестве ошибки использовать требуемый размер для результата, в случае успешного исполнения возвращать 0. Данный механизм хорошо себя зарекомендовал в АПИ, где он широко использувется.
А насчет прав и хранения паролей серьезно подумай еще раз. Система становится небезопасной.
← →
Anatoly Podgoretsky © (2005-02-07 13:10) [21]Пример функции
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);
← →
Ega23 © (2005-02-07 13:12) [22]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:17) [23]Забыл про приведение к PChar
GetPwd(PChar(Pwd), LG, "AliasName");
← →
Владислав © (2005-02-07 13:32) [24]На прежней работе авторизация к базе была построена на подобной криворукой системе. И там тоже ничего изменить было нельзя :(
← →
Anatoly Podgoretsky © (2005-02-07 14:52) [25]При такой методе, враги сожгут родную хату.
← →
Владислав © (2005-02-07 15:28) [26]> Anatoly Podgoretsky © (07.02.05 14:52) [25]
Это знают все до начальника подразделения информационных технологий (выше только ген. директор). Тем не менее живут с этим и по сей день.
К слову сказать, это авторизация в большом финансовом (стороннем) программном продукте. SCALA называется. Как они на это пошли?..
Страницы: 1 вся ветка
Форум: "Основная";
Текущий архив: 2005.02.20;
Скачать: [xml.tar.bz2];
Память: 0.52 MB
Время: 0.038 c