Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Основная";
Текущий архив: 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
1-1107772136
Raider
2005-02-07 13:28
2005.02.20
Как сделаь так чтоб


3-1106291585
Scorpio
2005-01-21 10:13
2005.02.20
несоответствие типов


3-1105871854
cherrex
2005-01-16 13:37
2005.02.20
DBGRID и Excel


6-1102056721
JohnS
2004-12-03 09:52
2005.02.20
Indy(idFtp) , Выделенка , проблемы


3-1106304368
Grab3
2005-01-21 13:46
2005.02.20
Mysql и Delphi





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский