Hi,
So far, I already completed a simple control, thanks to tutorial in catch22 for a the great article (http://www.catch22.net/tuts/custctrl.asp) in writting win32 control from scratch. One of the method mentioned from the article is assembly thunking, I tried, but I got no luck making it to work, this is where I'm asking for some help.
Probably, some of you already managed to do this:
http://www.pluralsight.com/articlecontent/cpprep0399.htm
The idea is to change the first parameter (hWnd) of WndProc, into a pointer to window's properties (struct), then jumping to the real WndProc, something like this:
WndProperties struct
__hwnd dd ?
__backcolor COLORREF ?
__forecolor COLORREF ?
WndProperties ends
ThunkBlock:
mov [esp+4], 0ffffffffh ; <-- replace 0ffffffffh with pointer to hWnd properties
jmp RealWndProc
ThunkBlockEnd:
StartupWndProc proc hWnd:HWND, uMsg:dword, wParam:WPARAM, lParam:LPARAM
; This WndProc will be executed only once
.if eax==WM_NCCREATE
; Create a new assembly thunk here, copying ThunkBlock to ThunkBlockEnd
; And then subclass the window to the new created assembly thunk
.endif
StartupWndProc endp
RealWndProc proc hWnd:HWND, uMsg:dword, wParam:WPARAM, lParam:LPARAM
push ebx
mov ebx, hWnd
assume ebx: ptr WndProperties
; [ebx] contains a pointer to WndProperties instance for this hWnd
; we can use it to easily get/set property values, when the
; appropriate message is called
invoke DefWindowProc, [ebx].__hwnd, uMsg, wParam, lParam
pop ebx
assume ebx: nothing
ret
RealWndProc endp
The problem is, if I catch WM_NCCREATE message (from StartupWndProc) to install the assembly thunk for my control, then it is throwing an exception that there's an illegal code executed, thi happens because I'm creating the assembly thunk to the process heap. But if I created the assembly thunk somewhere to a predefined area in the .code section (I have to patch the executable to allow write to .code section by doing this), everything works fine. I am thinking that the process heap has no execute permission...
Any suggestion into where is the best place to store created assembly thunk?
I was wondering how ATL managed to do this... ::)
Thanks in advance,
-chris
Hi
You can place it in the .data section, but you have to deactivate DEP on modern machines that supports it on hardware.
Basically you can put it on the heap but you must set the PAGE_EXECUTE_READWRITE attribute using the VirtualProtect API.
Biterider
Thanks biterider for the hint on using VirtualProtect API, but I can't make it work; can I ask for a small isnipet on how to enable execute in the heap. I'm doing it like this:
invoke GetProcessHeap
mov _pheap, eax
invoke VirtualProtect, _pheap, sizeof WndProperties, PAGE_EXECUTE_READWRITE, addr _oldProtect
The code above seems okay, but when I allocate some heap for executable code, the program is shutdown by windows due to protection fault. Any more hint?
Regards,
-chris
I have an alternative to the current OA32 Event calling based on thunking. It was not developed by me so I can not make it public, but I can send it to you by email if you get it to me. Be avare that it is not well commented since it is an experimental code but the thunking part works OK.
Regards,
Biterider
Thanks for the reply, I think I already managed to make it work :U
Although I'm still solving some area, but I think it should be fine.
I'll post the working code when my control is fully working, thanks again.
Cheers,
-chris
gwapo,
The Virtual* functions don't use a heap. You need to specify the actual address of the allocated memory there. I don't believe it is possible to enable execute in the heap, you'll have to allocate memory using VirtualAlloc instead.
Cheers,
Zooba
Thanks zooba, (sorry for the long response)
That's actually what I did, using VirtualAlloc function to store my dynamically created thunks, but eventually when there are already instances of my custom control that implement thunking, the size grow and I have to pull some linked list to maintain it.
Regards,
-chris
gwapo,
please post full source-code of that example in your starting post!
How do you allocate WndProperties structure ?
How do you pass that returned pointer here ? |mov [esp+4], 0ffffffffh ; <-- replace 0ffffffffh with pointer to hWnd properties|
Behold!
This is a pure "ATL thunking" example adapted for assembly projects.
After a long day of debugging, tracing, reading listing files I made it.
The demonstration is based by control that I made in three minutes.
[attachment deleted by admin]
It's already morethan a year since I posted this. But it's not too late to say thanks!
Thanks ramguru for this great demo on thunking., this give me another reason to work with custom controls again :wink
Cheers,
-chris
It took me a while, but I've made 64bit version of the ATL thunking (used goasm syntax). Now I can get started with some controls :}
And it seems SetWndowLongPtr is not supported in Window 7 (7201build) (not appear in user32.dll export list) - what a pain..
[attachment deleted by admin]
64bit version ? thanks ,but i don't know how to build it?
I'm using gorc,goasm,golink.
I have a bat file (it's assumed that goasm resides in C:\goasm dir &
that donkey's include (*.h) files reside in C:\goasm\inc dir:
@echo off
set INCLUDE=C:\GoASM\inc
if not exist rsrc.rc goto over1
C:\GOASM\bin\gorc /o /machine X64 rsrc.rc
:over1
if exist "%1.obj" del "%1.obj"
if exist "%1.exe" del "%1.exe"
C:\GOASM\bin\goasm /x64 "%1.asm"
if errorlevel 1 goto errasm
if not exist rsrc.obj goto nores
C:\GOASM\bin\golink "%1.obj" rsrc.obj
if errorlevel 1 goto errlink
dir "%1.*"
goto TheEnd
:nores
C:\GOASM\bin\golink "%1.obj"
if errorlevel 1 goto errlink
dir "%1.*"
goto TheEnd
:errlink
echo _
echo Link error
goto TheEnd
:errasm
echo _
echo Assembly Error
goto TheEnd
:TheEnd
del "%1.obj"
del rsrc.obj
build example:
C:\GOASM\projects\dummy_control64>c:\goasm\bin\bldallx64.bat dummy_control
GoRC.Exe Version 0.90.4 - Copyright Jeremy Gordon 1998/2009 - JG@JGnet.co.uk
Output file: rsrc.obj format: X64
GoAsm.Exe Version 0.56.6b - Copyright Jeremy Gordon 2001/9 - JG@JGnet.co.uk
Output file: dummy_control.obj
GoLink.Exe Version 0.26.10 - Copyright Jeremy Gordon 2002/9 - JG@JGnet.co.uk
Output file: dummy_control.exe
Format: X64 size: 5,120 bytes
Volume in drive C has no label.
Volume Serial Number is FC38-E563
Directory of C:\GOASM\projects\dummy_control64
06/11/2009 12:52 AM 4,390 dummy_control.asm
06/26/2009 07:22 PM 5,120 dummy_control.exe
06/26/2009 07:22 PM 4,061 dummy_control.obj
3 File(s) 13,571 bytes
0 Dir(s) 395,880,914,944 bytes free