hook HttpSendRequest + DELPHI
От: Аноним  
Дата: 07.09.11 16:28
Оценка:
приветствую!

Я перехватываю функцию HttpSendRequestW из WinInet в IE9 , наблюдаю мистическое поведение
Код выглядит так:
var
  HttpSendRequestWhook: THttpSendRequestW;

function HttpSendRequestWHookProc(hRequest: HINTERNET; lpszHeaders: PWideChar;
                                  dwHeadersLength: DWORD; lpOptional: Pointer;
                                  dwOptionalLength: DWORD): BOOL; stdcall;
var
  wsTmp: WideString;
begin
  OutputDebugStringA('[HttpSendRequestWHookProc]');
//  wsTmp := '11';

  Result := HttpSendRequestWhook(hRequest, lpszHeaders, dwHeadersLength, lpOptional, dwOptionalLength);
end;

begin
  OutputDebugString('Dll Main');
  @HttpSendRequestWhook := HookCode(GetProcAddress(LoadLibrary('WinInet.dll'), 'HttpSendRequestW'), @HttpSendRequestWHookProc);
end.


Если в HttpSendRequestWHookProc делать какие-то действия, например, OutputDebugStringW(lpszHeaders); или еще чего — всё ок. А вот если убрать комментарий с wsTmp := '11' — IE начнёт возвращать Internet Explorer cannot display the webpage!!

Я грешил на менеджер памяти, попробовал подключить FastMM — пофигу. Пробовал отлаживать, но проблему найти так и не удалось.
Кто постарше, посоветуйте как искать причину или помогите разобраться, пожалуйста..

Спасибо!
Re: hook HttpSendRequest + DELPHI
От: Alexander G Украина  
Дата: 07.09.11 20:44
Оценка:
Здравствуйте, Аноним, Вы писали:

А>приветствую!


А>Я перехватываю функцию HttpSendRequestW из WinInet в IE9 , наблюдаю мистическое поведение

А>Код выглядит так:
А>
А>var
А>  HttpSendRequestWhook: THttpSendRequestW;

А>function HttpSendRequestWHookProc(hRequest: HINTERNET; lpszHeaders: PWideChar;
А>                                  dwHeadersLength: DWORD; lpOptional: Pointer;
А>                                  dwOptionalLength: DWORD): BOOL; stdcall;
А>var
А>  wsTmp: WideString;
А>begin
А>  OutputDebugStringA('[HttpSendRequestWHookProc]');
А>//  wsTmp := '11';

А>  Result := HttpSendRequestWhook(hRequest, lpszHeaders, dwHeadersLength, lpOptional, dwOptionalLength);
А>end;

А>begin
А>  OutputDebugString('Dll Main');
А>  @HttpSendRequestWhook := HookCode(GetProcAddress(LoadLibrary('WinInet.dll'), 'HttpSendRequestW'), @HttpSendRequestWHookProc);
А>end.
А>


А>Если в HttpSendRequestWHookProc делать какие-то действия, например, OutputDebugStringW(lpszHeaders); или еще чего — всё ок. А вот если убрать комментарий с wsTmp := '11' — IE начнёт возвращать Internet Explorer cannot display the webpage!!


А>Я грешил на менеджер памяти, попробовал подключить FastMM — пофигу. Пробовал отлаживать, но проблему найти так и не удалось.

А>Кто постарше, посоветуйте как искать причину или помогите разобраться, пожалуйста..

А>Спасибо!


Если делать действия в HttpSendRequestWHookProc, они могут изменить GetLastError()-значение в TEB.
wsTmp := '11'; приводит у вызову SysFreeString с ненулевым параметром при достижении end, оно делает SetLastError(0);

решение — аккуратно сохранять значение LastError, полученное после вызова оригинальной функции и восстанавливать его перед возвратом. при использовании строк WideString — использовать восстановление LastError после освобождение Wide-строк, т.к. в некоторых случаях именно ненулевой LastError будет тем что нужно.
Русский военный корабль идёт ко дну!
Re[2]: hook HttpSendRequest + DELPHI
От: Аноним  
Дата: 08.09.11 04:02
Оценка:
Такой изврат. Не юзайте это дерьмо(в смысле дельфи).
Re[3]: hook HttpSendRequest + DELPHI
От: hattab  
Дата: 08.09.11 06:39
Оценка:
Здравствуйте, Аноним, Вы писали:

> Такой изврат. Не юзайте это дерьмо(в смысле дельфи).


Нечего на зеркало пенять, коли рожа крива (с). Если ты не знаешь, что WideString это системные строки, так это проблема твоя, а не дельфей.
avalon 1.0rc3 rev 419, zlib 1.2.3
Re[2]: hook HttpSendRequest + DELPHI
От: Аноним  
Дата: 08.09.11 07:25
Оценка:
Здравствуйте, Alexander G, Вы писали:

AG>Если делать действия в HttpSendRequestWHookProc, они могут изменить GetLastError()-значение в TEB.

AG>wsTmp := '11'; приводит у вызову SysFreeString с ненулевым параметром при достижении end, оно делает SetLastError(0);

AG>решение — аккуратно сохранять значение LastError, полученное после вызова оригинальной функции и восстанавливать его перед возвратом. при использовании строк WideString — использовать восстановление LastError после освобождение Wide-строк, т.к. в некоторых случаях именно ненулевой LastError будет тем что нужно.


Большое спасибо, это то, что нужно. Единственное, — не пойму каким образом можно восстановить значение LastError, т.к. SysFreeString вставляет компилятор в самый конец функции и на этот процесс я, видимо, влиять не могу. Т.е. любой код, написанный мною до "end;", будет перед SysFreeString.
Re[3]: hook HttpSendRequest + DELPHI
От: Alexander G Украина  
Дата: 08.09.11 08:52
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Большое спасибо, это то, что нужно. Единственное, — не пойму каким образом можно восстановить значение LastError, т.к. SysFreeString вставляет компилятор в самый конец функции и на этот процесс я, видимо, влиять не могу. Т.е. любой код, написанный мною до "end;", будет перед SysFreeString.


вижу несколько вариантов:

1. Не использовать wide-строки

2. использовать обёртки

function HttpSendRequestWHookProc(hRequest: HINTERNET; lpszHeaders: PWideChar;
                                  dwHeadersLength: DWORD; lpOptional: Pointer;
                                  dwOptionalLength: DWORD; var LastErrorValue: DWORD): BOOL; 
var
  wsTmp: WideString;
begin
  OutputDebugStringA('[HttpSendRequestWHookProc]');
//  wsTmp := '11';

  Result := HttpSendRequestWhook(hRequest, lpszHeaders, dwHeadersLength, lpOptional, dwOptionalLength);
  LastErrorValue := GetLastError();
end;


function HttpSendRequestWHookProcWrap(hRequest: HINTERNET; lpszHeaders: PWideChar;
                                      dwHeadersLength: DWORD; lpOptional: Pointer;
                                      dwOptionalLength: DWORD): BOOL; stdcall;
var LastErrorValue: DWORD;
begin
  LastErrorValue := GetLastError();
  Result := HttpSendRequestWHookProc(hRequest, lpszHeaders, dwHeadersLength, lpOptional, dwOptionalLength, LastErrorValue);
  SetLastError(LastErrorValue);
end;



3. использовать фичу с автоудалением интерфейсов


type 
  ILastErrorRestore = inteface
    ...
  end;

  TLastErrorRestore = class(TInterfacedObject, ILastErrorRestore)
    ...
  end;

  
function HttpSendRequestWHookProc(hRequest: HINTERNET; lpszHeaders: PWideChar;
                                  dwHeadersLength: DWORD; lpOptional: Pointer;
                                  dwOptionalLength: DWORD; var LastErrorValue: DWORD): BOOL; 
var
  LastErrorRestore: ILastErrorRestore;
  wsTmp: WideString;
begin
  LastErrorRestore := TLastErrorRestore.Create() as ILastErrorRestore;
  OutputDebugStringA('[HttpSendRequestWHookProc]');
//  wsTmp := '11';

  Result := HttpSendRequestWhook(hRequest, lpszHeaders, dwHeadersLength, lpOptional, dwOptionalLength);
  LastErrorRestore.SetValue( GetLastError() );
end;


деструктор TLastErrorRestore будет вызываться тоже неявно по end; . про порядок этих неявных вызовов нужно уточнить, но если он соотвествует порядку объявения переменных, можно добиться его вызова после SysFreeString

4. Обнулять строки перед выходом. Похоже, SysFreeString не меняет LastError значение для нулевого параметра.

я бы предпочёл решение 2, несмотря на его громоздкость, т.к. оно меньше полагается на детали реализации SysFreeString и поведения компилятора/рантайма Delphi.
Русский военный корабль идёт ко дну!
Re[4]: hook HttpSendRequest + DELPHI
От: Аноним  
Дата: 10.09.11 04:55
Оценка:
Здравствуйте, hattab, Вы писали:

H>Нечего на зеркало пенять, коли рожа крива (с). Если ты не знаешь, что WideString это системные строки, так это проблема твоя, а не дельфей.


У меня нет проблем, вы товарищ что то попутали. А что даже со строками компилятор не может разобраться, это его проблема, а не моя. Дельфи дерьмом было им и осталось.
Re[5]: hook HttpSendRequest + DELPHI
От: hattab  
Дата: 10.09.11 06:15
Оценка:
Здравствуйте, Аноним, Вы писали:

> У меня нет проблем, вы товарищ что то попутали. А что даже со строками компилятор не может разобраться, это его проблема, а не моя. Дельфи дерьмом было им и осталось.


Со строками он отлично таки разбирается. Кто же виноват, что ты не в курсе того, что WideString это строки системные
avalon 1.0rc3 rev 419, zlib 1.2.3
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.