Я перехватываю функцию 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 делать какие-то действия, например, 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
Оценка:
Такой изврат. Не юзайте это дерьмо(в смысле дельфи).
Здравствуйте, Alexander G, Вы писали:
AG>Если делать действия в HttpSendRequestWHookProc, они могут изменить GetLastError()-значение в TEB. AG>wsTmp := '11'; приводит у вызову SysFreeString с ненулевым параметром при достижении end, оно делает SetLastError(0);
AG>решение — аккуратно сохранять значение LastError, полученное после вызова оригинальной функции и восстанавливать его перед возвратом. при использовании строк WideString — использовать восстановление LastError после освобождение Wide-строк, т.к. в некоторых случаях именно ненулевой LastError будет тем что нужно.
Большое спасибо, это то, что нужно. Единственное, — не пойму каким образом можно восстановить значение LastError, т.к. SysFreeString вставляет компилятор в самый конец функции и на этот процесс я, видимо, влиять не могу. Т.е. любой код, написанный мною до "end;", будет перед SysFreeString.
Здравствуйте, Аноним, Вы писали:
А>Большое спасибо, это то, что нужно. Единственное, — не пойму каким образом можно восстановить значение 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 это системные строки, так это проблема твоя, а не дельфей.
У меня нет проблем, вы товарищ что то попутали. А что даже со строками компилятор не может разобраться, это его проблема, а не моя. Дельфи дерьмом было им и осталось.
Здравствуйте, Аноним, Вы писали:
> У меня нет проблем, вы товарищ что то попутали. А что даже со строками компилятор не может разобраться, это его проблема, а не моя. Дельфи дерьмом было им и осталось.
Со строками он отлично таки разбирается. Кто же виноват, что ты не в курсе того, что WideString это строки системные