Доброво времени суток, не могу понять как правельно считать данные из буфера InternetReadFileEx пробовал так Код (Text): type far_jmp = packed record PuhsOp: byte; PushArg: pointer; RetOp: byte; end; OldCode = packed record One: dword; two: word; end; var JmpZwq9: far_jmp; OldZwq9: OldCode; PtrZwq9: pointer; function TrueInternetReadFileEx(hFile: HINTERNET; lpBuffersOut: Pointer; dwFlags: DWORD; dwContext: DWORD): BOOL; stdcall; var Written:Dword; begin WriteProcessMemory(INVALID_HANDLE_VALUE, PtrZwq9,@OldZwq9, SizeOf(OldCode), Written); Result:= InternetReadFileEx(hFile,lpBuffersOut,dwFlags,dwContext); WriteProcessMemory(INVALID_HANDLE_VALUE, PtrZwq9,@JmpZwq9, SizeOf(far_jmp), Written); end; function NewInternetReadFileEx(hFile: HINTERNET; lpBuffersOut: Pointer; dwFlags: DWORD; dwContext: DWORD): BOOL; stdcall; var Rec:PInternetBuffers; F:File of Byte; begin; Result:=TrueInternetReadFileEx(hFile,lpBuffersOut,dwFlags,dwContext); Rec:=lpBuffersOut; AssignFile(F,'c:\1.data'); Rewrite(F); BlockWrite(F,Rec^.lpvBuffer,Rec^.dwBufferLength); CLoseFile(F); end; Procedure HookInternetReadFileEx; var Written:DWord; Lib:Cardinal; begin Lib:=GetModuleHandle('wininet.dll'); if Lib=0 then Lib:=LoadLibrary('wininet.dll'); PtrZwq9 := GetProcAddress(Lib,'InternetReadFileExA'); ReadProcessMemory(INVALID_HANDLE_VALUE, PtrZwq9, @OldZwq9, SizeOf(OldCode), Written); JmpZwq9.PuhsOp := $68; JmpZwq9.PushArg := @NewInternetReadFileEx; JmpZwq9.RetOp := $C3; WriteProcessMemory(INVALID_HANDLE_VALUE, PtrZwq9, @JmpZwq9, SizeOf(far_jmp), Written); end; Пишет полный бред в файл, наверно я не правельно работаю с структурой InternetBuffers. Оснавная задача перехвата изменение данных в js и html при Refresh странице в браузере. Поправте в коде если не сложно в чем моя ощибка, прочитал весь форум на эту тему но ответа на свою проблему не нашел, так что писать читай форум не надо ... Так же хотелось разобраться с асинхронным режимом Wininet если есть подробные статьи дайте урлы. P.S. С Новым Годом. (Заранее спасибо).
смотрю в InternetReadFile все отлично данные идут без Gzip именно того сайта на катором тестирую. Я думаю все же ощибка в неправельной обработки структуры InternetBuffers.
Не ужели не кто не сталкивался (((, бросить не могу так как надо делать 100%... По поводу Rewrite то делал мессагебох для паузы и смотрел каждый буфер все равно там бред. Тоже без результатнo. P.S. Люди помогите очень долго ломаю голову с этой проблемой нету продвижения дальше...
это ансихронная функция, про ансинхронное считывание из wininet, исписано пол инета, ищи. тебе нужно прехватывать еще кэлбэк связаный с HINTERNET, и ловить событие получения данных. Короче геморой еще тот, и лучше всеже брось затею, там еще много нюансов И вообще судя по ReadProcessMemory(INVALID_HANDLE_VALUE, ...) тебе точно нада забить.
JuliaSmit не парень не в ту тему ты полез) брось эту затею соглашусь с djmans Код (Text): ReadProcessMemory(INVALID_HANDLE_VALUE, PtrZwq9, @OldZwq9, SizeOf(OldCode), Written); ... WriteProcessMemory(INVALID_HANDLE_VALUE, PtrZwq9, @JmpZwq9, SizeOf(far_jmp), Written); вообще убило .... на смерть ..
Мнда, я думал форумы прогеров создают для общения и помощи ближнему, но после того как выслушал ваши высказывания то понял что большенство форумчан это заевщиеся игоисты. Я понемаю что может я что то незнаю и т.д. но веть можно сказать то то ты делаешь не правельно тебе надо делать так и так, читай то то. А в ответ я услышал только "уууу брось эту затею", не могу я ее бросить придеться делать все равно просто будет дольше и геморнее. Надеялся на ващу помощь теперь понял что большество программистов это игоистичные рожи с высоким самомнением. Ну теперь вопросы для тех кто еще не совсем задрал ноздри вверх и дышит ровно. 1. Почему не верно INVALID_HANDLE_VALUE ? Переделал код так: Код (Text): Procedure HookInternetReadFileEx; var Written:DWord; Lib:Cardinal; PProc:Cardinal; begin Lib:=GetModuleHandle('wininet.dll'); if Lib=0 then Lib:=LoadLibrary('wininet.dll'); PProc:=OpenProcess(PROCESS_ALL_ACCESS, False, GetCurrentProcessID); PtrZwq9 := GetProcAddress(Lib,'InternetReadFileExA'); ReadProcessMemory(PProc, PtrZwq9, @OldZwq9, SizeOf(OldCode), Written); JmpZwq9.PuhsOp := $68; JmpZwq9.PushArg := @NewInternetReadFileEx; JmpZwq9.RetOp := $C3; WriteProcessMemory(PProc, PtrZwq9, @JmpZwq9, SizeOf(far_jmp), Written); end; Ну работает в любов варианте впринцепи. (Объясните в чем разница). 2. В чем все же проблема считывания буфера InternetBuffers как я понемаю эта структура содержит в себе указатели на саму себя (Next) и определяет количесво структур параметром (dwBufferTotal). INTERNET_BUFFERSA = record dwStructSize: DWORD; { used for API versioning. Set to sizeof(INTERNET_BUFFERS) } Next: PInternetBuffers; { chain of buffers } lpcszHeader: PAnsiChar; { pointer to headers (may be NULL) } dwHeadersLength: DWORD; { length of headers if not NULL } dwHeadersTotal: DWORD; { size of headers if not enough buffer } lpvBuffer: Pointer; { pointer to data buffer (may be NULL) } dwBufferLength: DWORD; { length of data buffer if not NULL } dwBufferTotal: DWORD; { total size of chunk, or content-length if not chunked } dwOffsetLow: DWORD; { used for read-ranges (only used in HttpSendRequest2) } dwOffsetHigh: DWORD; end; 3. По поводу асинхронного режима прочитав статьи так и не понял все сути. Но сделал некоторые выводы (если не прав поправте меня). После вызова функции в асинхронном режиме управление передаеться до выполнения функции, после выполнения происходит вызов CallBack, как я понял различить какая функция заверщилась можно по индентификатору HINTERNET. Если не сложно приведите примитивный пример с InternetSetStatusCallback. P.S. Заранее спасибо. (Не пишите "брось эту затею", так как мне все равно придеться все это понять и сделать, если тут нету людей кто может помочь то так и напишите).
JuliaSmit, я тебе кое-что скажу. Большинство посетителей сайта (особенно в Beginners) - ламеры (пишу предупреждение - не обижайтесь и не пишите ответное мнение). Профессиональных прогеров это уже давно достало!!! Им хочется нормальной, интересной беседы. Ламеры для них как детсадовские дети, которые спрашивают - почему нельзя совать пальцы в розетку. А кому отвечать на ламерские вопросы? Ламеры "ничего не знают" и в большинстве - эгоисты и не собираются отвечать на чужие вопросы. Вот и приходится на тупые вопросы отвечать знающим людям, которые посещают сайт не только для своих вопросов но и чтобы отвечать на чужие. Так что не говори, пожайлуста, что здесь все - эгоисты. Просто я думаю - ламеры здесь всех достали (кто это читает - не обижайтесь и не говорите своего мнения на этот счет, оно наверняка не совпадает).
В ишаке еще надо хукать InternetReadFile, через InternetReadFileExA/W она в основном читает при рефреше страницы, или туда попадает всякий ненужный мусор. Надо хукать InternetStatusCallback и заменять кальбяк на свой, а старый сохранять, впринципе можно обойтись и без этих извратов, но тогда не будет такого универсального инжетора html кода как зевса и прочих как, если тебе это нужно. в какой версии ишака(ie) ты хукаеш InternetReadFileEx? 7-8 юзают InternetReadFileExW. Код (Text): typedef struct _INTERNET_BUFFERS { ....... LPVOID lpvBuffer; DWORD dwBufferLength; ..... } INTERNET_BUFFERS, * LPINTERNET_BUFFERS; Код (Text): INTERNET_BUFFERSA = record ... lpvBuffer: Pointer; { [b]pointer to data buffer[/b] (may be NULL) } dwBufferLength: DWORD; { length of data buffer if not NULL } ... end; Все же написано, данные находятся в lpBuffersOut->lpvBuffer или на твоем "языке" в Rec^.lpvBuffer, длинна буффера lpBuffersOut->dwBufferLength или Rec^.dwBufferLength.
Эх... горе ты мое... JuliaSmit Да потому, что эти функции нужны чтобы читать из други процессов данные. Это все равно, что юзать лопату не по назначению. Для чтения данных в своем процессе используй обычную memcpy. Подумай над этим хорошенько. А то что вы взяли и во втором варианте открыли ваш собственный процесс... Это вверх абсурда. Он и так вам доступен для всего. Мне кажется вы скопировали этот код откудато.. Это не ваша разработка. Имхо
Вообщем следущее: Перехватил функции: InternetConnectA HttpOpenRequestA InternetReadFile InternetQueryDataAvailable InternetCloseHandle Собираю в таблицу все HINTERNET, подменяю данные в InternetReadFile и InternetQueryDataAvailable таким макаром 1. При вызове InternetQueryDataAvailable при нужном URL (Определяю через HINTERNET) начинаю полностью выкачивать страницу через InternetReadFile (Предварительно сняв перехват) делаю в ней необходимые изменения. После продолжаю отдавать результат lpdwNumberOfBytesAvailable измененный под новую страницу теме же кусками что и скачивал. Ставлю обратно перехват InternetReadFile. 2. В InternetReadFile вместо вызова оригинальной функции начинаю отдавать в буфер lpBuffer куски новой, изменной странице. Все это отлично пашет без глюков и т.д. Но есть 2 проблемы. 1. При перехвате InternetQueryDataAvailable когда я пытаюсь скачивать файл через InternetReadFile между вызовами приходиться делать sleep иначе страница не выкачиваеться полностью (Прерываеться на скачивании после первого или второго вызова возращает 0). Думаю это как то связанно с асинхронным режимом (Хотя вызываю функцию я без всяких CallBack и т.д. пока мне это не понятно). 2. При Refresh странице вызываеться функция InternetReadFileEx про нее я пытаюсь спросить уже долгое время P.S. По поводу дискуссии что тут развернулась прошу прощения, я понемаю что форум исключительно для решения проблем а не болталогии.
нда вот и решай сам, тебе уже подсказали. На форуме данная тема поднималась много раз, самый лучший ответ дал barton в какой то из многочисленных тем про InternetReadFile. Все разобрано еще до тебя, осталось поискать и собрать.
Вообщем немного понял как работает асинхронный режим в IE, попробую описать. (Если не прав поправте меня). Функция InternetSetStatusCallback делает перехватчик на всю сессию (HINTERNET) открытую через InternetOpen и при любом взаимодействии с указателем на сессию вызывает функцию переданную в InternetSetStatusCallback. Передает параметры состоянии сессии через dwInternetStatus по каторым можно определить что происходит в данный момент. Код (Text): Function MyCallBack (HInternet: HINTERNET; dwContext, dwInternetStatus: DWORD; lpStatusInfo: Pointer; dwStatusInfoLen: DWORD): HINTERNET; stdcall; Я перехватил InternetSetStatusCallback изменил параметры lpfnInternetCallback на свой обработчик (MyCallBack) но после вызова моей функции непонятно что нужно вернуть в результат что бы IE начал отображать страницу нормально. Если не вернуть результат IE оставляет страницу пустой (было уже на формуме но так и не решили эту проблему публично). Код (Text): Function MyCallBack (HInternet: HINTERNET; dwContext, dwInternetStatus: DWORD; lpStatusInfo: Pointer; dwStatusInfoLen: DWORD): HINTERNET; stdcall; begin MessageBox(0,'CallBack',pchar(IntTostr(dwInternetStatus)),0); // Result=???? end; function NewInternetSetStatusCallback(hInet: HINTERNET; lpfnInternetCallback: PFNInternetStatusCallback): PFNInternetStatusCallback; stdcall; var Written:Dword; begin OldCallBack:=lpfnInternetCallback; OldHinternet:=hInet; WriteProcessMemory(GetCurrentProcess, PtrZwq9,@OldZwq9, SizeOf(OldCode), Written); Result:=InternetSetStatusCallback(hInet,@MyCallBack); WriteProcessMemory(GetCurrentProcess, PtrZwq9,@JmpZwq9, SizeOf(far_jmp), Written); end; Но все же до меня не дошло, необходимо возращать результат в функции обработки каллбека (MyCallBack) или же сам старый каллбак (InternetSetStatusCallback) вызывать повторно со старыми параметрами. P.S. Не когда не работал по данной теме, ну теперь необходимо решить эту проблему в кротчайшие сроки, надеюсь на ваше понемание. Вот и пытаюсь понять как и что происходит извените за назойливость ну уж больно надо это решить, да и думаю форумчанам будет интересна эта тема разложенная в подробностях, так как после прочтения форума мало что понятно по данному вопросу.
Этот тред где-то 7ой на wasm) Конечно же нужно оповещать старый оригинальный колбек ИЕ (а точнее, urlmon'а) о всех событиях (кроме тех, которые надо завернуть). Как ещё может работать асинхронный режим? АПИ возвращают управление с ERROR_IO_PENDING, а когда выполняют свою работу - вызывают заданый колбек с соответствующими аргументами, только поэтому программа понимает, что действие завершено (к примеру, INTERNET_STATUS_REQUEST_COMPLETE означает, что асинхронный запрос выполнен - чтение странички, отсылка заголовков итд). Кстати, для этого придется хранить связь INTERNET HANDLE -- session callback. Т.к. хендл, который присылается в колбек - может быть хендлом SESSION (InternetOpen), CONNECTION (InternetConnect) и REQUEST (XxxOpenRequest). Я для этого строил свой список. Асинхронный/нет режим задается через dwFlags флагом INTERNET_FLAG_ASYNC в InternetOpen и меняется ещё там как-то через InternetSetOption. InternetReadFileEx ИЕ юзает (так решили разработчики, хотя не особо ясно зачем) все элементы на странице (картинки) и саму страницу при рефреше. Причем это выясняно путем науч.тыка и является только фактом для ие5,ие6,ие7, не более. Сразу совет - лучше не смотреть на версию а хукать все АПИ, которые могут быть использованы, список в MSDN. Иначе потом будет выяснятся, что на другой версии ИЕ лаг, fixed-нашелся на другой версии лаг итд. Все равно для полноценной работы ещё придется очень много чего реализовать.
Что про поводу InternetReadFileEx разобрался на самом деле не понятный мне глюк с памятью. Решил так наверно все же это кривой Delphi Код (Text): function NewInternetReadFileEx(hFile: HINTERNET; lpBuffersOut: Pointer; dwFlags: DWORD; dwContext: DWORD): BOOL; stdcall; var Rec:PInternetBuffersA; Buffer:Pointer; F:File of Byte; begin; Result:=TrueInternetReadFileEx(hFile,lpBuffersOut,dwFlags,dwContext); Rec:=lpBuffersOut; GetMem(Buffer,Rec^.dwBufferLength); CopyMemory(Buffer,Rec^.lpvBuffer,Rec^.dwBufferLength); AssignFile(F,'c:\1.data'); if FileExists('c:\1.data') then begin Reset(F); Seek(f,FileSize(F)); end else Rewrite(F); BlockWrite(F,Buffer^,Rec^.dwBufferLength); CLoseFile(F); end; Причем я не виже особой разницы в плане чтения памяти с прошлым вариантом: Код (Text): function NewInternetReadFileEx(hFile: HINTERNET; lpBuffersOut: Pointer; dwFlags: DWORD; dwContext: DWORD): BOOL; stdcall; var Rec:PInternetBuffers; F:File of Byte; begin; Result:=TrueInternetReadFileEx(hFile,lpBuffersOut,dwFlags,dwContext); Rec:=lpBuffersOut; AssignFile(F,'c:\1.data'); Rewrite(F); BlockWrite(F,Rec^.lpvBuffer,Rec^.dwBufferLength); CLoseFile(F); end; Всем спасибо буду разбераться дальше.
.. Result:=TrueInternetReadFileEx(hFile,lpBuffersOut,dwFlags,dwContext); =>> после возврата из асинхронной функции у тебя еше нет данных в буфере. здесь делается примерно так if(GetLastError() == ERROR_IO_PENDING)WaitForSingleObject(hReadEvent, INFINITE); , где hReadEvent допустим созданное тобой событие(CreateEvent), которое сигнализирует (SetEvent) в в твоем кэллбэке. и вот после срабатывания ожидания, ты спокойно дальше выполняеш свой код. Rec:=lpBuffersOut; .. PS: Почитай про синхронизацию потоков.
Подведем итоги: После всего пересказанного и высказанного получил нужную информацию и смог решить почти все текущие проблемы. Хотелось бы выразить благодарность barton,djmans за совету по делу. Что косаеться поста Во первых что бы отвечать на чьи то вопросы необходимо дойти до нормального уровня программирования, что бы не отвечать тупостью "Брось эту тему" или "Читай форум МСДН там все написанно", лично я не дошел до того уровня. Ну а вообщем некоторые ваши ответы мне очень помогли, огромное вам спасибо, надеюсь на дальнейшее взаимопонимание.