• 15 апреля стартует «Курс «SQL-injection Master» ©» от команды The Codeby

    За 3 месяца вы пройдете путь от начальных навыков работы с SQL-запросами к базам данных до продвинутых техник. Научитесь находить уязвимости связанные с базами данных, и внедрять произвольный SQL-код в уязвимые приложения.

    На последнюю неделю приходится экзамен, где нужно будет показать свои навыки, взломав ряд уязвимых учебных сайтов, и добыть флаги. Успешно сдавшие экзамен получат сертификат.

    Запись на курс до 25 апреля. Получить промодоступ ...

Проблема с передачей строки работающему приложению

  • Автор темы NightmareTerrible
  • Дата начала
N

NightmareTerrible

Здравствуйте, уважаемые дельфисты.
У меня возникла следующая проблема.

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

Приложение при запуске проверяет, не запущена ли уже его копия, и если да, то передаёт ему параметры командной строки.
Код:
if ParamCount <> 0 then
begin
try
cd.cbData := Length(ParamStr(1));
cd.lpData := PChar(ParamStr(1));
cd.dwData := 0;
WParam := Application.Handle;
LParam := Integer(@cd);
SendMessage(OriChemesWindow, WM_COPYDATA, WParam, LParam);
finally
end;
end;

В переменной OriChemesWindow хранится дескриптор окна открытого ранее приложения (первой копии). Также существует обработчик этого сообщения:

Код:
procedure TOriChemesForm.WMCopyData(var Msg: TWMCopyData);
var
cd:TCopyDataStruct;
FileName : string;
i,len : integer;
begin
// Открываем файл, переданный в качетсве параметра (при открытии второй копии приложения)
cd := Msg.CopyDataStruct^;
FileName := '';
len := cd.cbData;
for i := 0 to len - 1 do
FileName := Filename + (PChar(cd.lpData) + i)^;
if FileExists(FileName) then begin
FileOpen1.Dialog.FileName := FileName;
FileOpen1Accept(nil);
end;
inherited;
end;

Процедура описана как
Код:
procedure WMCopyData(var Msg: TWMCopyData); message WM_COPYDATA;

Вроде бы всё должно работать хорошо, но вот проблема: при передаче параметров происходит какая-то ошибка, и часть текста преобразуется в крякозябры, например, во второй копии это был файл D:\Chemes\ver1.4\111temp.ori , а при получении параметров в первой копии получается что-то в роде D:\Chemeﲧ酋癔醀癔＀
Помогите, пожалуйста, решить эту проблемку. Использую Delphi 2010.
 
S

sinkopa

Здравствуйте, уважаемые дельфисты.
Помогите, пожалуйста, решить эту проблемку. Использую Delphi 2010.
Юникод батенька... :)
1.1. String в Delphi 7 = AnsiString
1.2. String в Delphi 2010 = WideString

2.1. PChar в Delphi 7 = PAnsiChar
2.2. PChar в Delphi 2010 = PWideChar

3. Функция ParamStr возвращает AnsiString, следовательно
Код:
PWideChar(ParamStr(1)) = лабуда... :-)
нужно как минимум
Код:
cd.lpData := PAnsiChar(ParamStr(1));
4.
Код:
	 cd.cbData := Length(ParamStr(1));
cd.lpData := PChar(ParamStr(1));
С кодом прямо скажем Вы пожадничали выложить... но если это локально (внутри процедуры) память выделяется, то на мой взгляд это совсем не гуд...
Надо
Код:
var
param: AnsiString = ''; // глобальная!!!! переменная

//...
param := ParamStr(1);

cd.cbData := Length(param);
cd.lpData := PAnsiChar(param);

5. И вот это
Код:
 FileName := '';
len := cd.cbData;
for i := 0 to len - 1 do
FileName := Filename + (PChar(cd.lpData) + i)^;
я бы поменял на вот это:
Код:
var
FileName: AnsiString;
cd:TCopyDataStruct;
len: Integer;
begin

FileName := '';
len := cd.cbData;
SetLength(FileName,len);
CopyMemory(PAnsiChar(FileName),cd.lpData,len);
//...
А может и проще еще
Код:
 FileName := StrPas(PAnsiChar(cd.lpData));
 
N

NightmareTerrible

sinkopa
Огромное спасибо, помогло. О том, что в 2010-м строки стали уникодовскими я знал, но видимо не хватило опыта (или сообразительности). Без вашей помощи маялся бы ещё очень долго. Кстати, через StrPas не прокатило; возможно потому, что функция преобразует к строкам паскаля.
 
Мы в соцсетях:

Обучение наступательной кибербезопасности в игровой форме. Начать игру!