News:

MASM32 SDK Description, downloads and other helpful links
MASM32.com New Forum Link
masmforum WebSite

Windows calling the windows procedure

Started by raleeper, May 24, 2007, 11:34:56 PM

Previous topic - Next topic

raleeper

Do I have this right?

Windows [or "the system"] cannot pass control to the windows procedure until it has written data to its stack.

But it cannot know where its stack is until it has called the procedure.

The only way it can locate the procedure's stack without passing control is to hook or trap the procedure, first replacing the first few bytes with a jump to a routine that gets the stack pointer, writes the data, restores the replaced bytes, and then jumps to the procedure.

hutch--

raleeper,

If you are talking about a normal "WndProc" using CreateWindowEx() the ADDRESS of the WndProc is set in the WNDCLASSEX structure which is used to register a window class with the operating system.

Set that address in the WNDCLASSEX, usually OFFSET WndProc or whatever else you call it.
Register the class.
Create the window.
Display the window.
Enter the message loop.

The OS will point most messages directly to the adress you placed in the WNDCLASSEX but keyboard and a few others are sent to the message loop so they can be processed first then dispatched to the WndProc.
Download site for MASM32      New MASM Forum
https://masm32.com          https://masm32.com/board/index.php

raleeper


The OS will point most messages directly to the adress you placed in the WNDCLASSEX
Quote

Don't you mean 'The OS will point most messages directly to *the stack of the procedure that starts at* the adress you placed in the WNDCLASSEX?

The OS knows where the procedure is, but how does it know where its stack is - since its stack doesn't exist til the procedure is called?

hutch--

Not exactly, the OS pushes the arguments onto THE STACK, the calls the address set in the WNDCLASSEX. As you should be aware each thread running in the system has its own stack and as the OS controls ALL THREADS, it in fact knows where to push the arguments for the WndProc.

>  since its stack doesn't exist til the procedure is called?

This is simply wrong, the OS knows exactly where the stack is in every thread. You are confusing local variables created on the stack with that stack itself. In a PE file it is a section of memory within the thread's address space set aside for the stack in accordance with the settings in the PE header file for stack reserve/stack commit.
Download site for MASM32      New MASM Forum
https://masm32.com          https://masm32.com/board/index.php

donkey

The stack exists before your procedure is called, each procedure run in a thread uses that threads stack, not a totally different one. What normally happens when a procedure is called is the parameters are first pushed onto the stack followed by the return address, then the program branches to the procedures entry address, the base pointer is pushed onto the stack then the base pointer for the stack is adjusted to the top of the stack and the stack pointer is adjusted depending on the amount of local space needed. At that point the arguments for the procedure are available as an offset from the base pointer below the bottom of the stack. For example

----------- old bottom of stack (OBS)
data
----------
param4
param3
param2
param1
RTA << return address
---------- Old top of stack (OTS)
OBS << (EBP is pushed onto the stack)
--------- New bottom of stack (EBP is set to this address)
locals
-------- New top of stack (ESP is set to this address)

When the procedure exits ESP is set to the value of EBP, EBP is popped from the stack, the return address is popped as part of the RET opcode and the stack has been restored to it's previous state. Note that the calling convention is responsible for adjusting the stack in regards to the parameters that have been left on it, C calling convention leaves them while STDCALL will adjust ESP accordingly.

Donkey
"Ahhh, what an awful dream. Ones and zeroes everywhere...[shudder] and I thought I saw a two." -- Bender
"It was just a dream, Bender. There's no such thing as two". -- Fry
-- Futurama

Donkey's Stable

raleeper


Entry:      esp = x

000000E2 55      *   push   ebp                        ;esp = x-4
000000E3 8B EC      *   mov   ebp, esp                 ;ebp = esp = x-4
000000E5 83 C4 B4   *   add   esp, 0FFFFFFB4h        ;esp = x-50h
000000E8 8B 45 0C   mov   eax, [uMsg]                    ;ie   mov   eax, [ebp+0C]      eax <- [x-4+0Ch = x+8]

When the mov eax [uMsg] instruction is executed the OS has already written a value, say WM_PAINT, to memory location x+8.

In order to do this it had to know the value of x, the value of esp at the time the windows procedure is called.

As a matter of fact, it is the same as the entry esp for winmain, which the OS has called and does know - this for all the sample programs I've seen and my own rudimentary, but working program.  But it could, I assume, be different, eg. if a push edx were inserted between winmain and the windows procedure.

zooba

When you call DispatchMessage some processing is done but eventually that function will call your window procedure. Hence, the window procedure is called in the same thread as your message loop (which it generally has to, since message queues are attached to threads rather than any other object), (almost) exactly as if you'd written invoke WindowProc, hWnd, uMsg, wParam, lParam yourself (calling your window procedure directly may break stuff, don't do it :wink ).

As others have said, there is one stack per thread, not per function, and the top of the stack is stored in ESP (there is one ESP per thread, and they can all be different. In fact, if they're the same or even close, two threads may write over each other's stacks and cause huge issues, so let's hope they're different...).

Cheers,

Zooba :U

tenkey

Quote from: raleeper on May 25, 2007, 10:38:59 AM
When the mov eax [uMsg] instruction is executed the OS has already written a value, say WM_PAINT, to memory location x+8.

In order to do this it had to know the value of x, the value of esp at the time the windows procedure is called.

The OS does not need to know where x is - it can set x to whatever it wants, thus establishing where the stack is for the window procedure. The OS uses a stack, and the window procedure inherits it.

If you think that means that data stored in local "stack" variables can't be retrieved in later calls - you're right!
A programming language is low level when its programs require attention to the irrelevant.
Alan Perlis, Epigram #8

raleeper

Thanks to all who responded to this question that I now see was misguided from the beginning.