169 похожих чатов

Коллеги, добрый вечер! Странный глюк наблюдаю - у пользователей иногда

(не постоянно) "западает" модальное окно, в видимости остается главная форма MainForm, а модального окна ModalForm не видно.

Отлавливаю WM_ACTIVATE разные.

Как это происходит у меня на компьютере: при показывании модального окна ModalForm.ShowModal сначала приходит WM_ACTIVATE(0, ...) главной форме, что она потеряла активность, потом модальной форме приходит WM_ACTIVATE(1, ...) что она получила активность. Всё. Больше WM_ACTIVATE нету.

Как это происходит у клиента, когда баг НЕ воспроизводится: сначала приходит WM_ACTIVATE(0, ...) главной форме, что она потеряла активность, потом модальной форме приходит WM_ACTIVATE(1, ...) что она получила активность, буквально через 100 мс активность переходит на TApplication окно, потом возвращается на модальное окно, баг не визуализируется.
Уже странно, почему есть это перепрыгивание фокуса на TApplication и обратно (а у меня нет).

Как это происходит у клиента, когда баг воспроизводится: сначала приходит WM_ACTIVATE(0, ...) главной форме, что она потеряла активность, потом модальной форме приходит WM_ACTIVATE(1, ...) что она получила активность, буквально через 100 мс активность переходит на MainForm (!!!), баг визуализируется. Вместо модального окна видно главную форму (которая зависла конечно как бы). Если кликнуть на приложение в панели задач - то всплывает и начинает визуализироваться модальное окно.

Почему ТАКОЕ может происходить? Есть подозрение, что все это происходит на достаточно слабых и тормозных компьютерах, но это только предположение.

Кто-нибудь может хотя бы предположить что происходит?

40 ответов

5 просмотров

linux ?

Михаил- Автор вопроса

Стикер

Михаил
windows

ХР? У меня на ней только такие глюки бывали. ЕМНИП, на скруле этот вопрос поднимался. Выше ссылка на форум от @nikron79 была, можно поискать

там от версии Делфи зависит, они несколько лет назад сильно переписали весь этот механизм

Михаил- Автор вопроса

Надо, но как Я вижу что приходит сообщение от винды, но я же не знаю что послужило этому

Михаил- Автор вопроса
Михаил
Надо, но как Я вижу что приходит сообщение от ви...

с какой стати винда будет посылать твоему окну ACTIVATE ? проблема у тебя

Михаил- Автор вопроса
Iluha Companets
с какой стати винда будет посылать твоему окну ACT...

Что значит с какой, винда так работает, рассылает всем сообщения о происходящих событиях

Михаил
Что значит с какой, винда так работает, рассылает ...

каких событиях? я имел ввиду повторную посылку

Михаил
Что значит с какой, винда так работает, рассылает ...

попробуй у модальной формы установить PopupParent := главная форма

Я еще давно с похожей хренью сталкивался, но не помню уже решение. Вроде был какой-то VclFix или что-то вроде. Но я потом сделал проще и лучше - отказался от модальных форм.

Михаил- Автор вопроса
Михаил
А подробностей нет?..

Были проблемы с формами из dll, решается передачей в dll дескриптора Application и главной формы. Только перед закрытием dll нужно дескриптор вернуть как было.

Ну тут фокусов быть не может. Нужно трамплином встать на SetWindowPos причем не в таблице импорта а на точке входа и прологировать, желательно со стеком вызова откуда она дергается. Только там и можно будет понять откуда идет паразитная передача фокуса с модалки на левое окно. Скорее всего используется какой-то левый контрол на модалке, который криво написан который лезет к Application и неявно активирует либо его либо главное окно. Пример трамплина можешь взять из примеров к статье о его применении (в архиве пример к шестой главе): https://rouse.drkb.ru/winapi.php#splice2

Михаил- Автор вопроса
Александр (Rouse_) Багель
Ну тут фокусов быть не может. Нужно трамплином вст...

А ты уверен что SetWindowPos, остальные апи вызывают его? Поэтому и трамплин на точку входа?

Михаил
А ты уверен что SetWindowPos, остальные апи вызыва...

Ну все такие функции (SetWindowPos/BringWindowToTop/) вызывают NtUserSetWindowPos, но на ней будет много ненужных старатываний.

Михаил- Автор вопроса
Александр (Rouse_) Багель
Ну все такие функции (SetWindowPos/BringWindowToTo...

А почему тогда именно SetWindowPos рекомендуешь? Если вдруг "вредоносный" код вызывает BringToFront или типа того? Или не может этого быть?

Михаил- Автор вопроса
Александр (Rouse_) Багель
Потому что VCL использует SetWindowPos

что-то фейл... Воспользовался примером из "4. Вызов перехваченной функции без снятия кода перехвата" Перехватываю InitHotPatchSpliceRec(user32, 'SetWindowPos', @InterceptedSetWindowPos, HotPathSpliceRec); SpliceNearJmp(PAnsiChar(HotPathSpliceRec.FuncAddr) - NearJmpSpliceRecSize, HotPathSpliceRec.SpliceRec); SpliceLockJmp(HotPathSpliceRec.FuncAddr, LOCK_JMP_OPKODE); когда вызываю оригинальную: @ASetWindowPos := PAnsiChar(HotPathSpliceRec.FuncAddr) + LockJmpOpcodeSize; Result := ASetWindowPos(hWnd, hWndInsertAfter, X, Y, cx, cy, uFlags); то попадаю на первый скрин там переход jmp dword ptr [$7670ab5c] попадаю на второй скриншот Потом на третий, далее на четвертый и там уже хана :(

Михаил- Автор вопроса

не работает (( Делаю: OrigAddr := GetProcAddress(GetModuleHandle(user32), 'SetWindowPos'); ReplaceIATEntry(OrigAddr, @InterceptedSetWindowPos); дальше в ReplaceIATEntry ImageBase := GetModuleHandle(user32); в результате в цикле Pointer(Thunk^._function) = OldProc не выполняется, не находит...

Михаил
не работает (( Делаю: OrigAddr := GetProcAddress(...

Ну потому что ты ищешь адрес в своей таблице импорта, причем не той функции. SetWindowPos это шлюз на win32u.NtUserSetWindowPos через таблицу импорта поэтому искать надо вот так OrigAddr := GetProcAddress(GetModuleHandle('win32u.dll'), 'NtUserSetWindowPos');

Михаил- Автор вопроса

Посмотрел через свой PMM как реализован вызов SetWindowPos

Михаил
Ох, магия ☺️

Ну а кто сказал что будет легко? Если разбираешся там конечно нет ничего сложного, но если нет - то повозиться конечно придется капитально чтобы понять что за чем идет и как это всё связано друг с другом

Михаил- Автор вопроса
Александр (Rouse_) Багель
Ну а кто сказал что будет легко? Если разбираешся ...

Ну нет бы единообразно, а то эта функция подходит для hotpatch, а эта вот нет, по другому сделано...

Михаил- Автор вопроса
Александр (Rouse_) Багель
Ну а кто сказал что будет легко? Если разбираешся ...

Ты кстати пишешь в статье что с вин64 не разбирался, а сейчас уже разобрался? вы перешли на 64 бита или для всего хватает 32 бита?

Михаил
Ну нет бы единообразно, а то эта функция подходит ...

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

Михаил
Ты кстати пишешь в статье что с вин64 не разбиралс...

Ну разобрался, но там тоже есть нюансы, не все применительное к перехвату в 32 битах подойдет для применения в 64 битах.

Михаил- Автор вопроса

Эээ... Если я правильно понял, просто не хватает 32 битов для указания своей точки входа?

Михаил- Автор вопроса
Александр (Rouse_) Багель
Да, поэтому там приходится извращаться

Хм, странно зачем так сделали... Совместимость? И винда знает что все ее библиотеки точно влезут в диапазон 4гб?

Михаил
Хм, странно зачем так сделали... Совместимость? И...

Они гарантированно туда не влезут, им это и не надо т.к. нам RVA оффсеты и они в 64 биитах не совсем приспособлены под перехват

Похожие вопросы

Обсуждают сегодня

Господа, а что сейчас вообще с рынком труда на делфи происходит? Какова ситуация?
Rꙮman Yankꙮvsky
29
А вообще, что может смущать в самой Julia - бы сказал, что нет единого стандартного подхода по многим моментам, поэтому многое выглядит как "хаки" и произвол. Короче говоря, с...
Viktor G.
2
30500 за редактор? )
Владимир
47
а через ESC-код ?
Alexey Kulakov
29
Чёт не понял, я ж правильной функцией воспользовался чтобы вывести отладочную информацию? но что-то она не ловится
notme
18
У меня есть функция где происходит это: write_bit(buffer, 1); write_bit(buffer, 0); write_bit(buffer, 1); write_bit(buffer, 1); write_bit(buffer, 1); w...
~
14
Добрый день! Скажите пожалуйста, а какие программы вы бы рекомендовали написать для того, чтобы научиться управлять памятью? Можно написать динамический массив, можно связный ...
Филипп
7
Недавно Google Project Zero нашёл багу в SQLite с помощью LLM, о чём достаточно было шумно в определённых интернетах, которые сопровождались рассказами, что скоро всех "ибешни...
Alex Sherbakov
5
Ребят в СИ можно реализовать ООП?
Николай
33
https://github.com/erlang/otp/blob/OTP-27.1/lib/kernel/src/logger_h_common.erl#L174 https://github.com/erlang/otp/blob/OTP-27.1/lib/kernel/src/logger_olp.erl#L76 15 лет назад...
Maksim Lapshin
20
Карта сайта