Модераторы: Snowy, bartram, MetalFan, bems, Poseidon, Riply
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Перехват ExtTextOut мусор или непонятная кодировка 
V
    Опции темы
-Сергей-
Дата 10.4.2014, 10:59 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 224
Регистрация: 2.8.2003
Где: Россия

Репутация: 1
Всего: 1



Внедряю код в процесс с целью перехватить текст, передаваемый в ExtTextOut.
Перехватываю обе функции ExtTextOutA и ExtTextOutW.
Для тестирования написал прогу, которая использует обе функции.
Функции перехватываются хорошо.
Для передачи отловленного текста использую WM_COPYDATA


ExtTextOutW перехватывается, но дело в том, что когда я сам вызываю ее в коде, текст получаю нужный, а вот контроллы которые рисуют текст, например TButton, с надписью "Кнопка" от нее я получаю непонятную кодировку "DzȕȖȗȒȈ" или текст "Button" приходит как "%XWWRQ"

C ExtTextOutA совсем все плачевно - там я получаю мусор вместе с Access violation. Вызываю я ее правильно, но перехватывается она как ExtTextOutW (в приемнике Msg.CopyDataStruct.dwData = 2) непонимаю почему.

Помогите разобраться в чем дело. Работаю в OC W7 Delphi XE5

Перехват и передача:
Код

procedure SendCopyData(hTargetWnd: HWND; ACopyDataStruct: TCopyDataStruct);
begin
  if hTargetWnd <> 0 then
    SendMessage(hTargetWnd, WM_COPYDATA, 0, Longint(@ACopyDataStruct));
end;

//Перехват ExtTextOutA 
function xSendtA(DC: HDC; X, Y: Integer; Options: LongWord; Rect: PRect; Str: LPCSTR; Count: LongWord; Dx: PInteger): Bool; stdcall;
var
  CopyDataStruct: TCopyDataStruct;
  hRecieverWnd: HWND;
begin
  Form1.Memo1.Lines.Add(Str);
  OutStr := PWideChar(((UnicodeString(Str))));

  with CopyDataStruct do
  begin
    dwData := 1; //  1-текст Ansi
    cbData := StrLen(Str) * SizeOf(PAnsiChar);  // длина данных +1 с учетом #0 (terminating)
    lpData := Str;
  end;
   hRecieverWnd := FindWindow('TMsgRcvr', nil);
  // Передаем нашу структуру приемнику
  SendCopyData(hRecieverWnd, CopyDataStruct);

   result := _pOldExtTextOutA(DC, X, Y, Options, Rect, Str, Count, Dx);
end;

//Перехват ExtTextOutW
function xSendtW(DC: HDC; X, Y: Integer; Options: LongWord; Rect: PRect; Str: LPCWSTR; Count: LongWord; Dx: PInteger): Bool; stdcall;
var
  CopyDataStruct: TCopyDataStruct;
  hRecieverWnd: HWND;
begin
  with CopyDataStruct do
  begin
    dwData := 2; //  2-текст Wide
   cbData := StrLen(Str) * SizeOf(PWideChar);
   lpData := Str;
  end;
   hRecieverWnd := FindWindow('TMsgRcvr', nil);
  // Передаем нашу структуру приемнику
  SendCopyData(hRecieverWnd, CopyDataStruct);
  result := _pOldExtTextOutW(DC, X, Y, Options, Rect, Str, Count, Dx);
end;


Принимающая сторона:
Код

procedure TMsgRcvr.WMCopyData(var Msg: TWMCopyData);

function StrLCopyA(Dest: PAnsiChar; const Source: PAnsiChar; MaxLen: Cardinal): PAnsiChar;
var
  Len: Cardinal;
begin
  Result := Dest;
  Len := StrLen(Source);
  if Len > MaxLen then
    Len := MaxLen;
  Move(Source^, Dest^, Len * SizeOf(AnsiChar));
  Dest[Len] := #0;
end;

function StrLCopyW(Dest: PWideChar; const Source: PWideChar; MaxLen: Cardinal): PWideChar;
var
  Len: Cardinal;

begin
  Result := Dest;
  Len := StrLen(Source);
  if Len > MaxLen then
    Len := MaxLen;
  Move(Source^, Dest^, Len * SizeOf(WideChar));
  Dest[Len] := #0;

end;

 var
   sTextA: array[0..260] of AnsiChar;
   sTextW: array[0..260] of WideChar;
 begin

  case Msg.CopyDataStruct.dwData of
    1:
      begin
        Memo1.Lines.Add('Message type 1');
        StrLCopyA(sTextA, PAnsiChar(Msg.CopyDataStruct.lpData), Msg.CopyDataStruct.cbData);
        Memo1.Lines.Add(sTextA);
      end;
    2:
      begin
        Memo1.Lines.Add('Message type 2');
        StrLCopyW(sTextW, PWideChar(Msg.CopyDataStruct.lpData), Msg.CopyDataStruct.cbData);
        Memo1.Lines.Add(sTextW);
      end;
  end;
 end;




Это сообщение отредактировал(а) -Сергей- - 10.4.2014, 11:00
--------------------
Для утвердительного ответа достаточно лишь одного слова - "да". Все прочие слова придуманы, чтобы сказать "нет".
PM MAIL WWW ICQ MSN   Вверх
CynicRus
Дата 10.4.2014, 14:37 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 248
Регистрация: 31.5.2012

Репутация: 1
Всего: 5



Хм, можно попробовать проверить Options на:
Код

if Options and ETO_GLYPH_INDEX = ETO_GLYPH_INDEX then
...


ну и если оно соответствует, то декодировать это.

Пример разбора на C++
Код


 if ( fuOptions & ETO_GLYPH_INDEX )
{
LPGLYPHSET ranges;
WCHAR * allChars, * ptr, * restoredString;
WORD * allIndices;
unsigned x;
// Here we have to decode glyph indices back to chars. We do this
// by tedious and ineffective iteration.
//
ranges = malloc( GetFontUnicodeRanges( hdc, 0 ) );
GetFontUnicodeRanges( hdc, ranges );
// Render up all available chars into one ridiculously big string
allChars = malloc( ( ranges->cGlyphsSupported ) * sizeof( WCHAR ) );
allIndices = malloc( ( ranges->cGlyphsSupported ) * sizeof( WORD ) );
ptr = allChars;
for( x = 0; x < ranges->cRanges; ++x )
{
WCHAR c = ranges->ranges[ x ].wcLow;
unsigned y = ranges->ranges[ x ].cGlyphs;
while( y-- )
*ptr++ = c++;
}
// Amazing. Now get glyph indices for this one nice string.
GetGlyphIndicesW( hdc, allChars, ranges->cGlyphsSupported, allIndices,
GGI_MARK_NONEXISTING_GLYPHS );
// Fascinating. Now translate our original input string back into
// its readable form.
restoredString = malloc( cbString * sizeof( WCHAR ) );
for( x = 0; x < cbString; ++x )
{
unsigned y;
WORD idx = lpszString[ x ];
for( y = 0; y < ranges->cGlyphsSupported; ++y )
if ( allIndices[ y ] == idx )
{
restoredString[ x ] = allChars[ y ];
break;
}
if ( y == ranges->cGlyphsSupported )
{
// Not found
restoredString[ x ] = L'?';
}
}
// And we're done.
free( allIndices );
free( allChars );
free( ranges );



Это сообщение отредактировал(а) CynicRus - 10.4.2014, 14:51
PM MAIL   Вверх
-Сергей-
Дата 14.4.2014, 05:13 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 224
Регистрация: 2.8.2003
Где: Россия

Репутация: 1
Всего: 1



Спасибо за пример!
Я не сильный знаток С, кое-что понимаю, кое-что не совсем.
Как на паскале будет это:
Код

while( y-- ) 
*ptr++ = c++; 


Так что ли?
Код

//for z := y downto 0 do
while z >=0 do
begin
  Inc(ptr);
  Inc(c);
  ptr := c;
  Dec(z)
end;


И здесь непонятно
Код

if ( allIndices[ y ] == idx )

allIndices это же не массив, а WORD

Это сообщение отредактировал(а) -Сергей- - 14.4.2014, 06:35
--------------------
Для утвердительного ответа достаточно лишь одного слова - "да". Все прочие слова придуманы, чтобы сказать "нет".
PM MAIL WWW ICQ MSN   Вверх
CynicRus
Дата 14.4.2014, 07:39 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 248
Регистрация: 31.5.2012

Репутация: 1
Всего: 5



Цитата(-Сергей- @ 14.4.2014,  05:13)
Спасибо за пример!
Я не сильный знаток С, кое-что понимаю, кое-что не совсем.
Как на паскале будет это:
Код

while( y-- ) 
*ptr++ = c++; 


Так что ли?
Код

//for z := y downto 0 do
while z >=0 do
begin
  Inc(ptr);
  Inc(c);
  ptr := c;
  Dec(z)
end;


И здесь непонятно
Код

if ( allIndices[ y ] == idx )

allIndices это же не массив, а WORD

allIndices - указатель на Word массив же.

В случае с циклом - да, похоже на то.
PM MAIL   Вверх
-Сергей-
Дата 22.4.2014, 08:16 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 224
Регистрация: 2.8.2003
Где: Россия

Репутация: 1
Всего: 1



Перевел на Delphi, может кому пригодится.
Код

function ConvertGlyphIdxToString(Str: PWideChar; DC: HDC): PWideChar; stdcall;
var
  ranges: PGLYPHSET;
  restoredString: PWideChar;
  allChars : array of WCHAR;
  allIndices: array of WORD;
  x, y : cardinal;
  idx : WORD;
  Count: LongWord;
begin
  Result:= '';

  Count := Length(Str);

  ranges := AllocMem(GetFontUnicodeRanges(DC, nil));
  GetFontUnicodeRanges(DC, ranges);

  SetLength(allChars, ranges.cGlyphsSupported * sizeof(PWideChar));
  SetLength(allIndices, ranges.cGlyphsSupported * SizeOf(Word));

  for x := 0 to (ranges.cGlyphsSupported * sizeof(PWideChar)) -1 do
    allChars[x] := WCHAR(x);

  if GetGlyphIndicesW(DC, Pointer(allChars), ranges.cGlyphsSupported, Pointer(allIndices),
  GGI_MARK_NONEXISTING_GLYPHS ) = GDI_ERROR then exit;

  restoredString := AllocMem(Count * sizeof(PWideChar));

  for x := 0 to Count -1 do
  begin
    idx := Ord(Str[x]);
    for y := 0 to ranges.cGlyphsSupported -1 do
    begin
      if allIndices[y] = idx then
      begin
        restoredString[x] := allChars[y];
        Break;
      end;
      if  y = ranges.cGlyphsSupported then
      begin
        // Not found
        restoredString[ x ] := '?';
      end;
    end;
  end;

  Result := PWideChar(Copy(restoredString, 0, Count));

  SysFreeMem(ranges);
  SysFreeMem(allChars);
  SysFreeMem(@allIndices);
  SysFreeMem(restoredString);
end;


Это сообщение отредактировал(а) -Сергей- - 22.4.2014, 08:17
--------------------
Для утвердительного ответа достаточно лишь одного слова - "да". Все прочие слова придуманы, чтобы сказать "нет".
PM MAIL WWW ICQ MSN   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Delphi: WinAPI и системное программирование"
Snowybartram
MetalFanbems
PoseidonRrader
Riply

Запрещено:

1. Публиковать ссылки на вскрытые компоненты

2. Обсуждать взлом компонентов и делиться вскрытыми компонентами

  • Литературу по Delphi обсуждаем здесь
  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Вопросы по реализации алгоритмов рассматриваются здесь
  • 90% ответов на свои вопросы можно найти в DRKB (Delphi Russian Knowledge Base) - крупнейшем в рунете сборнике материалов по Дельфи
  • 99% ответов по WinAPI можно найти в MSDN Library, оставшиеся 1% здесь

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Snowy, bartram, MetalFan, bems, Poseidon, Rrader, Riply.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Delphi: WinAPI и системное программирование | Следующая тема »


 




[ Время генерации скрипта: 0.0453 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.