Куда возвращает команда RET из WndProc

Тема в разделе "WASM.WIN32", создана пользователем Bitfry, 29 авг 2004.

  1. Bitfry

    Bitfry New Member

    Публикаций:
    0
    Регистрация:
    11 авг 2004
    Сообщения:
    54
    Адрес:
    Россия, Санкт-Петербург
    Доброго здоровья,

    пишет ищущий чайник.



    Изучая урок 4 Iczelion'a, задался вопросом



    Куда возвращает команда RET из WndProc



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

    Вопрос как в win32 это происходит, и как в айсе это увидеть.
     
  2. Loger

    Loger New Member

    Публикаций:
    0
    Регистрация:
    28 авг 2003
    Сообщения:
    71
    Адрес:
    Minsk
    Прога вызывает процедуру окна неявно через DispatchMessage
     
  3. Four-F

    Four-F New Member

    Публикаций:
    0
    Регистрация:
    31 авг 2002
    Сообщения:
    1.237
    [ Bitfry: и как в айсе это увидеть. ]



    Добавь int 3 в любое место своей WndProc. В айсе набери i3here on. Когда трапнешься набери p ret и ты в сабже.
     
  4. Bitfry

    Bitfry New Member

    Публикаций:
    0
    Регистрация:
    11 авг 2004
    Сообщения:
    54
    Адрес:
    Россия, Санкт-Петербург
    [Прога вызывает процедуру окна неявно через DispatchMessage]



    Loger я это понимаю, я так же понимаю, что и без DispatchMessage может вызваться процедура окна.

    Я не очень понимаю, что происходит после этой процедуры.

    Команда ret кидает меня в user32, и даже если я буду выполнять код в айсе дальше, я не попаду в цикл сообщений, почему?





    [Добавь int 3 в любое место своей WndProc. В айсе набери i3here on. Когда трапнешься набери p ret и ты в сабже.]



    Four-F у меня не работает или я что делаю не так.



    Насколько я понял нужно выполнить следующее:



    В код программы в WndProc добавить строку int 3

    Вызвать айс и набрать i3here on

    Запустить прогу и трапнуца

    Набрать в айсе p ret



    И вот здесь айс должен оказаться в сабже.

    Только он оказываюсь в том же user32

    А за сабж я принимаю цикл сообщений, или я неправ?
     
  5. leo

    leo Active Member

    Публикаций:
    0
    Регистрация:
    4 авг 2004
    Сообщения:
    2.542
    Адрес:
    Russia
    Bitfry

    "А за сабж я принимаю цикл сообщений"



    Насколько я понимаю, тебе нужен call stack - цепочка вызовов. В айсе call stack вызывается комадой STACK (подробности в Command Reference). Если под циклом сообщенний имеется ввиду обработка сообщений в дебажном процессе, то в итоге ты должен попасть в PeekMessage или GetMessage дебажного процесса, а из них в message loop. Поэтому после трапа на int3 смотрим call stack и откуда идет вызов PeekMessage и т.п.
     
  6. Asterix

    Asterix New Member

    Публикаций:
    0
    Регистрация:
    25 фев 2003
    Сообщения:
    3.576
    Bitfry

    > И вот здесь айс должен оказаться в сабже.



    нажимай F12(p ret) несколько раз, пока не окажешься в адресном пространстве проги.
     
  7. leo

    leo Active Member

    Публикаций:
    0
    Регистрация:
    4 авг 2004
    Сообщения:
    2.542
    Адрес:
    Russia
    Оычно цикл сообщений это: если не PeekMessage, то WaitMessage. Поэтому вместо int3 можно попробовать bpx WaitMessage. Затем смотришь адрес возврата в ESP.
     
  8. Bitfry

    Bitfry New Member

    Публикаций:
    0
    Регистрация:
    11 авг 2004
    Сообщения:
    54
    Адрес:
    Россия, Санкт-Петербург
    Leo, команда stack очень полезная, спасибо, буду пользоваться.



    [пока не окажешься в адресном пространстве проги.]



    Asterix, не окажусь я там. Через несколько p ret'ов айс больше не появляется.



    Да что вы меня путаете!



    Ставлю простой бряк на строку ret

    В айсе выполняю эпилог (leave и ret 0010)

    Прога в user32, и в стеке сверху лежит указатель начала цикла сообщений моей программы.

    Вот и все!



    Но суть не в этом, я не хочу возвратиться в цикл по всяким p ret'ам,

    я хочу понять, кто и где берет из стека этот указатель и возвращается в мой цикл сообщений за новой месагой.

    Блин, я скоро как программер буду изъясняться! :)
     
  9. Bitfry

    Bitfry New Member

    Публикаций:
    0
    Регистрация:
    11 авг 2004
    Сообщения:
    54
    Адрес:
    Россия, Санкт-Петербург
    [Прога в user32, и в стеке сверху лежит указатель начала цикла сообщений моей программы.]



    Наврал!

    Там не указатель цикла сообщений. Там указатель WndProc, но почему?
     
  10. S_T_A_S_

    S_T_A_S_ New Member

    Публикаций:
    0
    Регистрация:
    27 окт 2003
    Сообщения:
    1.754
    Сообщения виндоса - штука довольно муторная.

    Помимо DispatchMessage, многие другие функции (например DefWindowProc, GetClientRect и т.п.) так же могут вызывать WndProc. т.е. вызов происходит непосредственно из WndProc рекурсивно, может по многу раз.



    По RET из WindProc (в XP по крайней маре) попадаем в user32 на

    cmp [dword ss:esp+4], DCBAABCD

    так виндос заботится о тех, кто использует RETN, вместо RETN 10h.



    Ещё поищите Джеффри Рихтер "Создание эффективных WIN32-приложений с учетом специфики 64-разрядной версии Windows", там про сообщения есть целая глава. Ссылки на такие вещи запрещены, но поиск поможет :derisive:
     
  11. Bitfry

    Bitfry New Member

    Публикаций:
    0
    Регистрация:
    11 авг 2004
    Сообщения:
    54
    Адрес:
    Россия, Санкт-Петербург
    S_T_A_S_



    Вот это ответ так ответ, спасибо.

    Буду читать, оно у меня есть.

    Если чего не пойму, опять здесь спрашивать буду.

    Еще раз спасибо.
     
  12. Four-F

    Four-F New Member

    Публикаций:
    0
    Регистрация:
    31 авг 2002
    Сообщения:
    1.237
    [ Bitfry: Да что вы меня путаете! ]



    Так это не мы тебя, а ты нас :) Ты спросил "Куда возвращает команда RET из WndProc?". И я ответил именно на вопрос. А что ты там имел ввиду - пойди разбери. А Рихтера почитай.
     
  13. Bitfry

    Bitfry New Member

    Публикаций:
    0
    Регистрация:
    11 авг 2004
    Сообщения:
    54
    Адрес:
    Россия, Санкт-Петербург
    Four-F



    Да ты прав, я не ясно задал вопрос.



    Я не имел введу каманду айса. Вопрос был про опкод ret 0010 в конце WndProc в 4 уроке у Iczelion'a



    А книга дельная, я ее отложил, потому что название меня сбило, а вот сейчас читаю.
     
  14. Bitfry

    Bitfry New Member

    Публикаций:
    0
    Регистрация:
    11 авг 2004
    Сообщения:
    54
    Адрес:
    Россия, Санкт-Петербург
    Джеффри РИХТЕР "Создание эффективных WIN32-приложений с учетом специфики 64-разрядной версии Windows"



    Цитата из главы 26

    ...

    Алгоритм выборки сообщений из очереди потока



    Когда поток вызывает GetMessage или PeekMessage, система проверяет флаги состояния очередей потока и определяет, какое сообщение надо обработать



    1. Если флаг QS_SENDMESSAGE установлен, система отправляет сообщение соответствующей оконной процедуре GetMessage и PeekMessage контролируют процесс обработки и не передают управление потоку сразу после того, как оконная процедура обработает сообщение, вместо этого обе функции ждут следующего сообщения.



    2. Если очередь асинхронных сообщений потока не пуста, GetMessage и Peek Message заполняют переданную им структуру MSG и возвращают управление в Цикл выборки сообщений (расположенный в потоке) в этот момент обычно обращается к DispatchMessage, чтобы соответствующая оконная процедура обработала сообщение.



    3. Если флаг QS_QUIT установлен, GetMessage и PeekMessage возвращают сообщение WM__QUIT (параметр wParam которого содержит указанный код заверше ния) и сбрасывают этот флаг.



    4 Если в очереди виртуального ввода потока есть какие-то сообщения, GetMessage и PeekMessage возвращают сообщение, связанное с аппаратным вводом.



    5. Если флаг QS_PAINT установлен, GetMessage и PeekMessage возвращают сооб щение WM_PAINT для соответствующего окна

    ...



    Если кто может, объясните, пожалуйста, в пункте 1, идет речь о том, куда прога попадет из WndProc?

    А вообще я не нашел в этой главе про сабж, только это.

    Может, есть еще дельные книги по архитектуре форточек?
     
  15. S_T_A_S_

    S_T_A_S_ New Member

    Публикаций:
    0
    Регистрация:
    27 окт 2003
    Сообщения:
    1.754
    Дык я же написАл - из WndProc мы всегда будем попадать в user32, поскольку именно оттуда и происходит непосредственно вызов.

    Куда попадём дальше - вопрос неоднозначный, зависит от состояния очереди сообщений.



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



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

    Например, до XP можно было обходиться без ф-ции DispatchMessage, самостоятельно вызывая WndProc.

    Можно ещё создать окна без цикла выборки сообщений.

    Или зарегистрировать DefWindowProc в качестве WndProc.
     
  16. Four-F

    Four-F New Member

    Публикаций:
    0
    Регистрация:
    31 авг 2002
    Сообщения:
    1.237
    [ Bitfry: Если кто может, объясните, пожалуйста, в пункте 1, идет речь о том, куда прога попадет из WndProc? ]



    Нет. Из WndProc прога попадает туда, откуда была вызвана WndProc. Т.е. куда-то в user32.dll. Обработка сообщений идет в ядре (в драйвере win32k.sys), куда GetMessage попадает вызвав NtUserGetMessage. Сам процесс весьма сложен, поэтому искать его детальное объяснение в книгах бессмысленно. Вот кусок где проверяется флаг QS_SENDMESSAGE и либо бай-бай, либо xxxReceiveMessages.


    Код (Text):
    1. BOOL xxxInternalGetMessage(
    2.     LPMSG lpMsg,
    3.     HWND hwndFilter,
    4.     UINT msgMin,
    5.     UINT msgMax,
    6.     UINT flags,
    7.     BOOL fGetMessage)
    8. {
    9. . . .
    10.     UINT fsWakeMask;
    11. . . .
    12.     /*
    13.      * Compute the QS* mask that corresponds to the message range
    14.      *  and the wake mask filter (HIWORD(flags))
    15.      */
    16.     fsWakeMask = CalcWakeMask(msgMin, msgMax, HIWORD(flags));
    17.     ptiCurrent->fsChangeBitsRemoved = 0;
    18. . . .
    19.         /*
    20.          * Check for sent messages. Check the the actual wake bits (i.e, from pcti)
    21.          *  so we know for real.
    22.          */
    23.         if (ptiCurrent->pcti->fsWakeBits & fsWakeMask & QS_SENDMESSAGE) {
    24.             xxxReceiveMessages(ptiCurrent);
    25.         } else if (ptiCurrent->pcti->fsWakeBits & QS_SENDMESSAGE) {
    26.             goto NoMessages;
    27.         }
    28. . . .
    29.  
    30. NoMessages:
    31.         /*
    32.          * Looks like we have no input. If we're being called from GetMessage()
    33.          * then go to sleep until we find something.
    34.          */
    35.         if (!fGetMessage) {
    36.             /*
    37.              * This is one last check for pending sent messages. It also
    38.              * yields. Win3.1 does this.
    39.              */
    40.             if (!(flags & PM_NOYIELD)) {
    41.                 /*
    42.                  * This is the point where windows yields. Here we wait to wake
    43.                  * up any threads waiting for this thread to hit "idle state".
    44.                  */
    45.                 zzzWakeInputIdle(ptiCurrent);
    46.  
    47.                 /*
    48.                  * Yield and receive pending messages.
    49.                  */
    50.                 xxxUserYield(ptiCurrent);
    51.             }
    52.             PATHTAKEN(0x800);
    53.             goto FalseExit;
    54.         }
    55.  
    56.         /*
    57.          * This is a getmessage not a peekmessage, so sleep. When we sleep,
    58.          * zzzWakeInputIdle() is called to wake up any apps waiting on this
    59.          * app to go idle.
    60.          */
    61.         if (!xxxSleepThread(fsWakeMask, 0, TRUE))
    62.             goto FalseExit;
    63.     } /* while (TRUE) */
    64. . . .
    65. }






    [ Bitfry: Может, есть еще дельные книги по архитектуре форточек? ]



    Есть. Исходный код системы + отладчик + дизассемблер + мозги + ОГРОМНОЕ количество свободного времени :)
     
  17. Bitfry

    Bitfry New Member

    Публикаций:
    0
    Регистрация:
    11 авг 2004
    Сообщения:
    54
    Адрес:
    Россия, Санкт-Петербург
    Four-F Спасибо. Поздравляю тебя с днем знаний. =)

    Я так спросил, я же чайник и еще не знаю, что можно раскопать сразу, а куда лучше с моими знаниями не соваться. Но я еще попробую с этим вопросом разобраться (в рамках XP и в общих чертах).

    Пункт 1 я толкую так:

    Отработала процедура окна, строка ret посылает в user32. Если есть еще сообщение, то после колдовства виндов управление вернется к проге в её цикл сообщений. А если сообщений нет, нафига тогда цикл крутить, проц занимать? Вот поэтому возврат происходит не сразу из user32 в цикл сообщений, а через кучу всяких функций.



    [S_T_A_S_:Ты б написАл подробнее зачем это нужно, может тогда кто-нибудь и даст более вразумительный ответ.]



    S_T_A_S_ тебя тоже с днем знаний.

    Я пишу дневник чайника, в котором разбираю уроки Iczelion'a. Чтоб понять, как работает программа в виндах, я захотел ответить на кучу вопросов, которые появляются у начинающих, вот и копаю потихоньку сам, а на этот вопрос сам ответа не нашел. Я просто исследователь, и нет никакой такой проги для которой это нужно. Примерно так появляются темы с плюсиком. :)
     
  18. Four-F

    Four-F New Member

    Публикаций:
    0
    Регистрация:
    31 авг 2002
    Сообщения:
    1.237
    user32, в данном случае - это просто прослойка между приложением и ядром, где и происходит работа с очередью сообщений. Возврат происходит в любом случае через user32, и "через кучу всяких функций" в ядро. И ядро уже решает, то ли усыпить поток, если очередь пуста, то ли отправить оконной процедуре какое-нить сообщение, если таковое имеется. Если очередь пуста, то ожидание происходит в режиме ядра.
     
  19. leo

    leo Active Member

    Публикаций:
    0
    Регистрация:
    4 авг 2004
    Сообщения:
    2.542
    Адрес:
    Russia
    Four_F

    "И ядро уже решает.."

    Нда ? Очень интересно..

    А я-чайник думал, что несколько не так. А зачем тогда message loop ? Мне по мастдайски кажется, что иницатива опроса очереди сообщений исходит от приложения:
    Код (Text):
    1. if PeekMessage (или GetMessage) then
    2.   ...
    3.   TranslateMessage
    4.   DispatchMessage  //->...-> WndProc ->...-> ???
    5. xxx:
    6. else
    7.   WaitMessage //-> здесь ес-но засыпаем
    8. yyy:
    9.   ...
    Что, в данном случае мы после Dispatch застрянем в ядре и не попадем на xxx ? Хотя с другой стороны, если мы спим, то пропудить нас может только ядро - вопрос с какого места - с yyy или, как ты говоришь, "отправить оконной процедуре какое-нить сообщение" ?
     
  20. Four-F

    Four-F New Member

    Публикаций:
    0
    Регистрация:
    31 авг 2002
    Сообщения:
    1.237
    Ладно, я не так выразился. Если в очереди есть сообщения, то GetMessage вернется из ядра, а DispatchMessage уже передает его оконной процедуре. Но если сообщений нет, то GetMessage не вернется из ядра, до тех пор пока они не появятся. WaitMessage, скорее всего, тоже в ядро уходит.